api.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. package volume
  2. import (
  3. "log"
  4. "net/http"
  5. "github.com/docker/go-plugins-helpers/sdk"
  6. )
  7. const (
  8. // DefaultDockerRootDirectory is the default directory where volumes will be created.
  9. DefaultDockerRootDirectory = "/var/lib/docker-volumes"
  10. manifest = `{"Implements": ["VolumeDriver"]}`
  11. createPath = "/VolumeDriver.Create"
  12. getPath = "/VolumeDriver.Get"
  13. listPath = "/VolumeDriver.List"
  14. removePath = "/VolumeDriver.Remove"
  15. hostVirtualPath = "/VolumeDriver.Path"
  16. mountPath = "/VolumeDriver.Mount"
  17. unmountPath = "/VolumeDriver.Unmount"
  18. capabilitiesPath = "/VolumeDriver.Capabilities"
  19. )
  20. // CreateRequest is the structure that docker's requests are deserialized to.
  21. type CreateRequest struct {
  22. Name string
  23. Options map[string]string `json:"Opts,omitempty"`
  24. }
  25. // RemoveRequest structure for a volume remove request
  26. type RemoveRequest struct {
  27. Name string
  28. }
  29. // MountRequest structure for a volume mount request
  30. type MountRequest struct {
  31. Name string
  32. ID string
  33. }
  34. // MountResponse structure for a volume mount response
  35. type MountResponse struct {
  36. Mountpoint string
  37. }
  38. // UnmountRequest structure for a volume unmount request
  39. type UnmountRequest struct {
  40. Name string
  41. ID string
  42. }
  43. // PathRequest structure for a volume path request
  44. type PathRequest struct {
  45. Name string
  46. }
  47. // PathResponse structure for a volume path response
  48. type PathResponse struct {
  49. Mountpoint string
  50. }
  51. // GetRequest structure for a volume get request
  52. type GetRequest struct {
  53. Name string
  54. }
  55. // GetResponse structure for a volume get response
  56. type GetResponse struct {
  57. Volume *Volume
  58. }
  59. // ListResponse structure for a volume list response
  60. type ListResponse struct {
  61. Volumes []*Volume
  62. }
  63. // CapabilitiesResponse structure for a volume capability response
  64. type CapabilitiesResponse struct {
  65. Capabilities Capability
  66. }
  67. // Volume represents a volume object for use with `Get` and `List` requests
  68. type Volume struct {
  69. Name string
  70. Mountpoint string
  71. Status map[string]interface{}
  72. }
  73. // Capability represents the list of capabilities a volume driver can return
  74. type Capability struct {
  75. Scope string
  76. }
  77. // ErrorResponse is a formatted error message that docker can understand
  78. type ErrorResponse struct {
  79. Err string
  80. }
  81. // NewErrorResponse creates an ErrorResponse with the provided message
  82. func NewErrorResponse(msg string) *ErrorResponse {
  83. return &ErrorResponse{Err: msg}
  84. }
  85. // Driver represent the interface a driver must fulfill.
  86. type Driver interface {
  87. Create(*CreateRequest) error
  88. List() (*ListResponse, error)
  89. Get(*GetRequest) (*GetResponse, error)
  90. Remove(*RemoveRequest) error
  91. Path(*PathRequest) (*PathResponse, error)
  92. Mount(*MountRequest) (*MountResponse, error)
  93. Unmount(*UnmountRequest) error
  94. Capabilities() *CapabilitiesResponse
  95. }
  96. // Handler forwards requests and responses between the docker daemon and the plugin.
  97. type Handler struct {
  98. driver Driver
  99. sdk.Handler
  100. }
  101. // NewHandler initializes the request handler with a driver implementation.
  102. func NewHandler(driver Driver) *Handler {
  103. h := &Handler{driver, sdk.NewHandler(manifest)}
  104. h.initMux()
  105. return h
  106. }
  107. func (h *Handler) initMux() {
  108. h.HandleFunc(createPath, func(w http.ResponseWriter, r *http.Request) {
  109. log.Println("Entering go-plugins-helpers createPath")
  110. req := &CreateRequest{}
  111. err := sdk.DecodeRequest(w, r, req)
  112. if err != nil {
  113. return
  114. }
  115. err = h.driver.Create(req)
  116. if err != nil {
  117. sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true)
  118. return
  119. }
  120. sdk.EncodeResponse(w, struct{}{}, false)
  121. })
  122. h.HandleFunc(removePath, func(w http.ResponseWriter, r *http.Request) {
  123. log.Println("Entering go-plugins-helpers removePath")
  124. req := &RemoveRequest{}
  125. err := sdk.DecodeRequest(w, r, req)
  126. if err != nil {
  127. return
  128. }
  129. err = h.driver.Remove(req)
  130. if err != nil {
  131. sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true)
  132. return
  133. }
  134. sdk.EncodeResponse(w, struct{}{}, false)
  135. })
  136. h.HandleFunc(mountPath, func(w http.ResponseWriter, r *http.Request) {
  137. log.Println("Entering go-plugins-helpers mountPath")
  138. req := &MountRequest{}
  139. err := sdk.DecodeRequest(w, r, req)
  140. if err != nil {
  141. return
  142. }
  143. res, err := h.driver.Mount(req)
  144. if err != nil {
  145. sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true)
  146. return
  147. }
  148. sdk.EncodeResponse(w, res, false)
  149. })
  150. h.HandleFunc(hostVirtualPath, func(w http.ResponseWriter, r *http.Request) {
  151. log.Println("Entering go-plugins-helpers hostVirtualPath")
  152. req := &PathRequest{}
  153. err := sdk.DecodeRequest(w, r, req)
  154. if err != nil {
  155. return
  156. }
  157. res, err := h.driver.Path(req)
  158. if err != nil {
  159. sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true)
  160. return
  161. }
  162. sdk.EncodeResponse(w, res, false)
  163. })
  164. h.HandleFunc(getPath, func(w http.ResponseWriter, r *http.Request) {
  165. log.Println("Entering go-plugins-helpers getPath")
  166. req := &GetRequest{}
  167. err := sdk.DecodeRequest(w, r, req)
  168. if err != nil {
  169. return
  170. }
  171. res, err := h.driver.Get(req)
  172. if err != nil {
  173. sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true)
  174. return
  175. }
  176. sdk.EncodeResponse(w, res, false)
  177. })
  178. h.HandleFunc(unmountPath, func(w http.ResponseWriter, r *http.Request) {
  179. log.Println("Entering go-plugins-helpers unmountPath")
  180. req := &UnmountRequest{}
  181. err := sdk.DecodeRequest(w, r, req)
  182. if err != nil {
  183. return
  184. }
  185. err = h.driver.Unmount(req)
  186. if err != nil {
  187. sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true)
  188. return
  189. }
  190. sdk.EncodeResponse(w, struct{}{}, false)
  191. })
  192. h.HandleFunc(listPath, func(w http.ResponseWriter, r *http.Request) {
  193. log.Println("Entering go-plugins-helpers listPath")
  194. res, err := h.driver.List()
  195. if err != nil {
  196. sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true)
  197. return
  198. }
  199. sdk.EncodeResponse(w, res, false)
  200. })
  201. h.HandleFunc(capabilitiesPath, func(w http.ResponseWriter, r *http.Request) {
  202. log.Println("Entering go-plugins-helpers capabilitiesPath")
  203. sdk.EncodeResponse(w, h.driver.Capabilities(), false)
  204. })
  205. }