Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,27 @@ A collection of helper packages to extend Docker Engine in Go
Graph (experimental) | [Link](https://github.com/docker/docker/blob/master/experimental/plugins_graphdriver.md) | Extend image and container fs storage

See the [understand Docker plugins documentation section](https://docs.docker.com/engine/extend/plugins/).

# Serving multiple drivers on a single socket

An abridged example of serving identically named handlers over the same socket.

```go

import (
"github.com/docker/go-plugins-helpers/sdk"
"github.com/docker/go-plugins-helpers/ipam"
"github.com/docker/go-plugins-helpers/network"
)

handler := sdk.NewHandler()

driver := &NetworkDriver{}
ipamDriver := &IpamDriver{}

network.InitMux(handler, driver)
ipam.InitMux(handler, ipamDriver)

handler.ServeUnix("/run/docker/plugins/my_combined_driver.sock", 0)

```
26 changes: 15 additions & 11 deletions authorization/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
)

const (
manifest = `{"Implements": ["` + authorization.AuthZApiImplements + `"]}`
reqPath = "/" + authorization.AuthZApiRequest
resPath = "/" + authorization.AuthZApiResponse
pluginType = authorization.AuthZApiImplements
reqPath = "/" + authorization.AuthZApiRequest
resPath = "/" + authorization.AuthZApiResponse
)

// Request is the structure that docker's requests are deserialized to.
Expand All @@ -34,24 +34,28 @@ type Handler struct {

// NewHandler initializes the request handler with a plugin implementation.
func NewHandler(plugin Plugin) *Handler {
h := &Handler{plugin, sdk.NewHandler(manifest)}
h.initMux()
h := &Handler{plugin, sdk.NewHandler()}
InitMux(h, plugin)
return h
}

func (h *Handler) initMux() {
h.handle(reqPath, func(req Request) Response {
return h.plugin.AuthZReq(req)
// InitMux initializes a compatible HTTP mux with routes for the specified driver. Can be used
// to combine multiple drivers into a single plugin mux.
func InitMux(h sdk.Mux, plugin Plugin) {
handle(h, reqPath, func(req Request) Response {
return plugin.AuthZReq(req)
})

h.handle(resPath, func(req Request) Response {
return h.plugin.AuthZRes(req)
handle(h, resPath, func(req Request) Response {
return plugin.AuthZRes(req)
})

h.AddImplementation(pluginType)
}

type actionHandler func(Request) Response

func (h *Handler) handle(name string, actionCall actionHandler) {
func handle(h sdk.Mux, name string, actionCall actionHandler) {
h.HandleFunc(name, func(w http.ResponseWriter, r *http.Request) {
var (
req Request
Expand Down
11 changes: 6 additions & 5 deletions authorization/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,15 @@ func TestActivate(t *testing.T) {

defer response.Body.Close()

body, err := ioutil.ReadAll(response.Body)
manifest := &sdk.PluginManifest{}
json.NewDecoder(response.Body).Decode(manifest)

if err != nil {
t.Fatal(err)
if len(manifest.Implements) != 1 {
t.Fatalf("Expected %v, got %v", 1, len(manifest.Implements))
}

if string(body) != manifest+"\n" {
t.Fatalf("Expected %s, got %s\n", manifest+"\n", string(body))
if manifest.Implements[0] != pluginType {
t.Fatalf("Expected %s, got %s\n", pluginType, manifest.Implements[0])
}
}

Expand Down
39 changes: 21 additions & 18 deletions graphdriver/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const (
// DefaultDockerRootDirectory is the default directory where graph drivers will be created.
DefaultDockerRootDirectory = "/var/lib/docker/graph"

manifest = `{"Implements": ["GraphDriver"]}`
pluginType = "GraphDriver"
initPath = "/GraphDriver.Init"
createPath = "/GraphDriver.Create"
createRWPath = "/GraphDriver.CreateReadWrite"
Expand Down Expand Up @@ -246,19 +246,21 @@ type Handler struct {

// NewHandler initializes the request handler with a driver implementation.
func NewHandler(driver Driver) *Handler {
h := &Handler{driver, sdk.NewHandler(manifest)}
h.initMux()
h := &Handler{driver, sdk.NewHandler()}
InitMux(h, driver)
return h
}

func (h *Handler) initMux() {
// InitMux initializes a compatible HTTP mux with routes for the specified driver. Can be used
// to combine multiple drivers into a single plugin mux.
func InitMux(h sdk.Mux, driver Driver) {
h.HandleFunc(initPath, func(w http.ResponseWriter, r *http.Request) {
req := InitRequest{}
err := sdk.DecodeRequest(w, r, &req)
if err != nil {
return
}
err = h.driver.Init(req.Home, req.Options, req.UIDMaps, req.GIDMaps)
err = driver.Init(req.Home, req.Options, req.UIDMaps, req.GIDMaps)
msg := ""
if err != nil {
msg = err.Error()
Expand All @@ -271,7 +273,7 @@ func (h *Handler) initMux() {
if err != nil {
return
}
err = h.driver.Create(req.ID, req.Parent, req.MountLabel, req.StorageOpt)
err = driver.Create(req.ID, req.Parent, req.MountLabel, req.StorageOpt)
msg := ""
if err != nil {
msg = err.Error()
Expand All @@ -284,7 +286,7 @@ func (h *Handler) initMux() {
if err != nil {
return
}
err = h.driver.CreateReadWrite(req.ID, req.Parent, req.MountLabel, req.StorageOpt)
err = driver.CreateReadWrite(req.ID, req.Parent, req.MountLabel, req.StorageOpt)
msg := ""
if err != nil {
msg = err.Error()
Expand All @@ -297,7 +299,7 @@ func (h *Handler) initMux() {
if err != nil {
return
}
err = h.driver.Remove(req.ID)
err = driver.Remove(req.ID)
msg := ""
if err != nil {
msg = err.Error()
Expand All @@ -311,7 +313,7 @@ func (h *Handler) initMux() {
if err != nil {
return
}
dir, err := h.driver.Get(req.ID, req.MountLabel)
dir, err := driver.Get(req.ID, req.MountLabel)
msg := ""
if err != nil {
msg = err.Error()
Expand All @@ -324,7 +326,7 @@ func (h *Handler) initMux() {
if err != nil {
return
}
err = h.driver.Put(req.ID)
err = driver.Put(req.ID)
msg := ""
if err != nil {
msg = err.Error()
Expand All @@ -337,11 +339,11 @@ func (h *Handler) initMux() {
if err != nil {
return
}
exists := h.driver.Exists(req.ID)
exists := driver.Exists(req.ID)
sdk.EncodeResponse(w, &ExistsResponse{Exists: exists}, "")
})
h.HandleFunc(statusPath, func(w http.ResponseWriter, r *http.Request) {
status := h.driver.Status()
status := driver.Status()
sdk.EncodeResponse(w, &StatusResponse{Status: status}, "")
})
h.HandleFunc(getMetadataPath, func(w http.ResponseWriter, r *http.Request) {
Expand All @@ -350,15 +352,15 @@ func (h *Handler) initMux() {
if err != nil {
return
}
metadata, err := h.driver.GetMetadata(req.ID)
metadata, err := driver.GetMetadata(req.ID)
msg := ""
if err != nil {
msg = err.Error()
}
sdk.EncodeResponse(w, &GetMetadataResponse{Err: msg, Metadata: metadata}, msg)
})
h.HandleFunc(cleanupPath, func(w http.ResponseWriter, r *http.Request) {
err := h.driver.Cleanup()
err := driver.Cleanup()
msg := ""
if err != nil {
msg = err.Error()
Expand All @@ -371,7 +373,7 @@ func (h *Handler) initMux() {
if err != nil {
return
}
stream := h.driver.Diff(req.ID, req.Parent)
stream := driver.Diff(req.ID, req.Parent)
sdk.StreamResponse(w, stream)
})
h.HandleFunc(changesPath, func(w http.ResponseWriter, r *http.Request) {
Expand All @@ -380,7 +382,7 @@ func (h *Handler) initMux() {
if err != nil {
return
}
changes, err := h.driver.Changes(req.ID, req.Parent)
changes, err := driver.Changes(req.ID, req.Parent)
msg := ""
if err != nil {
msg = err.Error()
Expand All @@ -391,7 +393,7 @@ func (h *Handler) initMux() {
params := r.URL.Query()
id := params.Get("id")
parent := params.Get("parent")
size, err := h.driver.ApplyDiff(id, parent, r.Body)
size, err := driver.ApplyDiff(id, parent, r.Body)
msg := ""
if err != nil {
msg = err.Error()
Expand All @@ -404,13 +406,14 @@ func (h *Handler) initMux() {
if err != nil {
return
}
size, err := h.driver.DiffSize(req.ID, req.Parent)
size, err := driver.DiffSize(req.ID, req.Parent)
msg := ""
if err != nil {
msg = err.Error()
}
sdk.EncodeResponse(w, &DiffSizeResponse{Err: msg, Size: size}, msg)
})
h.AddImplementation(pluginType)
}

// CallInit is the raw call to the Graphdriver.Init method
Expand Down
23 changes: 13 additions & 10 deletions ipam/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
)

const (
manifest = `{"Implements": ["IpamDriver"]}`
pluginType = "IpamDriver"

capabilitiesPath = "/IpamDriver.GetCapabilities"
addressSpacesPath = "/IpamDriver.GetDefaultAddressSpaces"
Expand Down Expand Up @@ -96,14 +96,16 @@ type Handler struct {

// NewHandler initializes the request handler with a driver implementation.
func NewHandler(ipam Ipam) *Handler {
h := &Handler{ipam, sdk.NewHandler(manifest)}
h.initMux()
h := &Handler{ipam, sdk.NewHandler()}
InitMux(h, ipam)
return h
}

func (h *Handler) initMux() {
// InitMux initializes a compatible HTTP mux with routes for the specified driver. Can be used
// to combine multiple drivers into a single plugin mux.
func InitMux(h sdk.Mux, ipam Ipam) {
h.HandleFunc(capabilitiesPath, func(w http.ResponseWriter, r *http.Request) {
res, err := h.ipam.GetCapabilities()
res, err := ipam.GetCapabilities()
if err != nil {
msg := err.Error()
sdk.EncodeResponse(w, NewErrorResponse(msg), msg)
Expand All @@ -112,7 +114,7 @@ func (h *Handler) initMux() {
sdk.EncodeResponse(w, res, "")
})
h.HandleFunc(addressSpacesPath, func(w http.ResponseWriter, r *http.Request) {
res, err := h.ipam.GetDefaultAddressSpaces()
res, err := ipam.GetDefaultAddressSpaces()
if err != nil {
msg := err.Error()
sdk.EncodeResponse(w, NewErrorResponse(msg), msg)
Expand All @@ -126,7 +128,7 @@ func (h *Handler) initMux() {
if err != nil {
return
}
res, err := h.ipam.RequestPool(req)
res, err := ipam.RequestPool(req)
if err != nil {
msg := err.Error()
sdk.EncodeResponse(w, NewErrorResponse(msg), msg)
Expand All @@ -140,7 +142,7 @@ func (h *Handler) initMux() {
if err != nil {
return
}
err = h.ipam.ReleasePool(req)
err = ipam.ReleasePool(req)
if err != nil {
msg := err.Error()
sdk.EncodeResponse(w, NewErrorResponse(msg), msg)
Expand All @@ -154,7 +156,7 @@ func (h *Handler) initMux() {
if err != nil {
return
}
res, err := h.ipam.RequestAddress(req)
res, err := ipam.RequestAddress(req)
if err != nil {
msg := err.Error()
sdk.EncodeResponse(w, NewErrorResponse(msg), msg)
Expand All @@ -168,11 +170,12 @@ func (h *Handler) initMux() {
if err != nil {
return
}
err = h.ipam.ReleaseAddress(req)
err = ipam.ReleaseAddress(req)
if err != nil {
msg := err.Error()
sdk.EncodeResponse(w, NewErrorResponse(msg), msg)
}
sdk.EncodeResponse(w, make(map[string]string), "")
})
h.AddImplementation(pluginType)
}
Loading