From 594ac4a14658a90ad7bc5541dab6349a0c629a5c Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Mon, 16 Nov 2020 14:32:12 -0500 Subject: Add API for communicating with Docker volume plugins Docker provides extensibility through a plugin system, of which several types are available. This provides an initial library API for communicating with one type of plugins, volume plugins. Volume plugins allow for an external service to create and manage a volume on Podman's behalf. This does not integrate the plugin system into Libpod or Podman yet; that will come in subsequent pull requests. Signed-off-by: Matthew Heon --- .../docker/go-plugins-helpers/volume/api.go | 230 +++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 vendor/github.com/docker/go-plugins-helpers/volume/api.go (limited to 'vendor/github.com/docker/go-plugins-helpers/volume/api.go') diff --git a/vendor/github.com/docker/go-plugins-helpers/volume/api.go b/vendor/github.com/docker/go-plugins-helpers/volume/api.go new file mode 100644 index 000000000..dcc2f3abf --- /dev/null +++ b/vendor/github.com/docker/go-plugins-helpers/volume/api.go @@ -0,0 +1,230 @@ +package volume + +import ( + "log" + "net/http" + + "github.com/docker/go-plugins-helpers/sdk" +) + +const ( + // DefaultDockerRootDirectory is the default directory where volumes will be created. + DefaultDockerRootDirectory = "/var/lib/docker-volumes" + + manifest = `{"Implements": ["VolumeDriver"]}` + createPath = "/VolumeDriver.Create" + getPath = "/VolumeDriver.Get" + listPath = "/VolumeDriver.List" + removePath = "/VolumeDriver.Remove" + hostVirtualPath = "/VolumeDriver.Path" + mountPath = "/VolumeDriver.Mount" + unmountPath = "/VolumeDriver.Unmount" + capabilitiesPath = "/VolumeDriver.Capabilities" +) + +// CreateRequest is the structure that docker's requests are deserialized to. +type CreateRequest struct { + Name string + Options map[string]string `json:"Opts,omitempty"` +} + +// RemoveRequest structure for a volume remove request +type RemoveRequest struct { + Name string +} + +// MountRequest structure for a volume mount request +type MountRequest struct { + Name string + ID string +} + +// MountResponse structure for a volume mount response +type MountResponse struct { + Mountpoint string +} + +// UnmountRequest structure for a volume unmount request +type UnmountRequest struct { + Name string + ID string +} + +// PathRequest structure for a volume path request +type PathRequest struct { + Name string +} + +// PathResponse structure for a volume path response +type PathResponse struct { + Mountpoint string +} + +// GetRequest structure for a volume get request +type GetRequest struct { + Name string +} + +// GetResponse structure for a volume get response +type GetResponse struct { + Volume *Volume +} + +// ListResponse structure for a volume list response +type ListResponse struct { + Volumes []*Volume +} + +// CapabilitiesResponse structure for a volume capability response +type CapabilitiesResponse struct { + Capabilities Capability +} + +// Volume represents a volume object for use with `Get` and `List` requests +type Volume struct { + Name string + Mountpoint string `json:",omitempty"` + CreatedAt string `json:",omitempty"` + Status map[string]interface{} `json:",omitempty"` +} + +// Capability represents the list of capabilities a volume driver can return +type Capability struct { + Scope string +} + +// ErrorResponse is a formatted error message that docker can understand +type ErrorResponse struct { + Err string +} + +// NewErrorResponse creates an ErrorResponse with the provided message +func NewErrorResponse(msg string) *ErrorResponse { + return &ErrorResponse{Err: msg} +} + +// Driver represent the interface a driver must fulfill. +type Driver interface { + Create(*CreateRequest) error + List() (*ListResponse, error) + Get(*GetRequest) (*GetResponse, error) + Remove(*RemoveRequest) error + Path(*PathRequest) (*PathResponse, error) + Mount(*MountRequest) (*MountResponse, error) + Unmount(*UnmountRequest) error + Capabilities() *CapabilitiesResponse +} + +// Handler forwards requests and responses between the docker daemon and the plugin. +type Handler struct { + driver Driver + sdk.Handler +} + +// NewHandler initializes the request handler with a driver implementation. +func NewHandler(driver Driver) *Handler { + h := &Handler{driver, sdk.NewHandler(manifest)} + h.initMux() + return h +} + +func (h *Handler) initMux() { + h.HandleFunc(createPath, func(w http.ResponseWriter, r *http.Request) { + log.Println("Entering go-plugins-helpers createPath") + req := &CreateRequest{} + err := sdk.DecodeRequest(w, r, req) + if err != nil { + return + } + err = h.driver.Create(req) + if err != nil { + sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true) + return + } + sdk.EncodeResponse(w, struct{}{}, false) + }) + h.HandleFunc(removePath, func(w http.ResponseWriter, r *http.Request) { + log.Println("Entering go-plugins-helpers removePath") + req := &RemoveRequest{} + err := sdk.DecodeRequest(w, r, req) + if err != nil { + return + } + err = h.driver.Remove(req) + if err != nil { + sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true) + return + } + sdk.EncodeResponse(w, struct{}{}, false) + }) + h.HandleFunc(mountPath, func(w http.ResponseWriter, r *http.Request) { + log.Println("Entering go-plugins-helpers mountPath") + req := &MountRequest{} + err := sdk.DecodeRequest(w, r, req) + if err != nil { + return + } + res, err := h.driver.Mount(req) + if err != nil { + sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true) + return + } + sdk.EncodeResponse(w, res, false) + }) + h.HandleFunc(hostVirtualPath, func(w http.ResponseWriter, r *http.Request) { + log.Println("Entering go-plugins-helpers hostVirtualPath") + req := &PathRequest{} + err := sdk.DecodeRequest(w, r, req) + if err != nil { + return + } + res, err := h.driver.Path(req) + if err != nil { + sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true) + return + } + sdk.EncodeResponse(w, res, false) + }) + h.HandleFunc(getPath, func(w http.ResponseWriter, r *http.Request) { + log.Println("Entering go-plugins-helpers getPath") + req := &GetRequest{} + err := sdk.DecodeRequest(w, r, req) + if err != nil { + return + } + res, err := h.driver.Get(req) + if err != nil { + sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true) + return + } + sdk.EncodeResponse(w, res, false) + }) + h.HandleFunc(unmountPath, func(w http.ResponseWriter, r *http.Request) { + log.Println("Entering go-plugins-helpers unmountPath") + req := &UnmountRequest{} + err := sdk.DecodeRequest(w, r, req) + if err != nil { + return + } + err = h.driver.Unmount(req) + if err != nil { + sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true) + return + } + sdk.EncodeResponse(w, struct{}{}, false) + }) + h.HandleFunc(listPath, func(w http.ResponseWriter, r *http.Request) { + log.Println("Entering go-plugins-helpers listPath") + res, err := h.driver.List() + if err != nil { + sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true) + return + } + sdk.EncodeResponse(w, res, false) + }) + + h.HandleFunc(capabilitiesPath, func(w http.ResponseWriter, r *http.Request) { + log.Println("Entering go-plugins-helpers capabilitiesPath") + sdk.EncodeResponse(w, h.driver.Capabilities(), false) + }) +} -- cgit v1.2.3-54-g00ecf