diff --git a/authorization/api.go b/authorization/api.go index 7e157f7..b10771c 100644 --- a/authorization/api.go +++ b/authorization/api.go @@ -108,7 +108,7 @@ type Handler struct { // NewHandler initializes the request handler with a plugin implementation. func NewHandler(plugin Plugin) *Handler { - h := &Handler{plugin, sdk.NewHandler(manifest)} + h := &Handler{plugin, *sdk.NewHandler(manifest)} h.initMux() return h } diff --git a/graphdriver/api.go b/graphdriver/api.go index 193f77a..c394f74 100644 --- a/graphdriver/api.go +++ b/graphdriver/api.go @@ -236,7 +236,7 @@ type Handler struct { // NewHandler initializes the request handler with a driver implementation. func NewHandler(driver Driver) *Handler { - h := &Handler{driver, sdk.NewHandler(manifest)} + h := &Handler{driver, *sdk.NewHandler(manifest)} h.initMux() return h } diff --git a/ipam/api.go b/ipam/api.go index 7ebc906..678b82a 100644 --- a/ipam/api.go +++ b/ipam/api.go @@ -96,7 +96,7 @@ type Handler struct { // NewHandler initializes the request handler with a driver implementation. func NewHandler(ipam Ipam) *Handler { - h := &Handler{ipam, sdk.NewHandler(manifest)} + h := &Handler{ipam, *sdk.NewHandler(manifest)} h.initMux() return h } diff --git a/network/api.go b/network/api.go index a3c4396..33d22df 100644 --- a/network/api.go +++ b/network/api.go @@ -214,7 +214,7 @@ type Handler struct { // NewHandler initializes the request handler with a driver implementation. func NewHandler(driver Driver) *Handler { - h := &Handler{driver, sdk.NewHandler(manifest)} + h := &Handler{driver, *sdk.NewHandler(manifest)} h.initMux() return h } diff --git a/sdk/handler.go b/sdk/handler.go index c0d042e..81a550f 100644 --- a/sdk/handler.go +++ b/sdk/handler.go @@ -1,6 +1,7 @@ package sdk import ( + "context" "crypto/tls" "fmt" "net" @@ -13,11 +14,12 @@ const activatePath = "/Plugin.Activate" // Handler is the base to create plugin handlers. // It initializes connections and sockets to listen to. type Handler struct { - mux *http.ServeMux + mux *http.ServeMux + server *http.Server } // NewHandler creates a new Handler with an http mux. -func NewHandler(manifest string) Handler { +func NewHandler(manifest string) *Handler { mux := http.NewServeMux() mux.HandleFunc(activatePath, func(w http.ResponseWriter, r *http.Request) { @@ -25,25 +27,33 @@ func NewHandler(manifest string) Handler { fmt.Fprintln(w, manifest) }) - return Handler{mux: mux} + return &Handler{mux: mux} } // Serve sets up the handler to serve requests on the passed in listener -func (h Handler) Serve(l net.Listener) error { +func (h *Handler) Serve(l net.Listener) error { server := http.Server{ Addr: l.Addr().String(), Handler: h.mux, } + + h.server = &server return server.Serve(l) } +// Shutdown gracefully shuts down the http.Server serving requests after Serve or +// Serve{TCP,Unix,Windows} was called. +func (h *Handler) Shutdown(c context.Context) error { + return h.server.Shutdown(c) +} + // ServeTCP makes the handler to listen for request in a given TCP address. // It also writes the spec file in the right directory for docker to read. // Due to constrains for running Docker in Docker on Windows, data-root directory // of docker daemon must be provided. To get default directory, use // WindowsDefaultDaemonRootDir() function. On Unix, this parameter is ignored. -func (h Handler) ServeTCP(pluginName, addr, daemonDir string, tlsConfig *tls.Config) error { - l, spec, err := newTCPListener(addr, pluginName, daemonDir, tlsConfig) +func (h *Handler) ServeTCP(pluginName, addr, daemonDir string, tlsConfig *tls.Config) error { + l, spec, err := NewTCPListener(addr, pluginName, daemonDir, tlsConfig) if err != nil { return err } @@ -55,8 +65,8 @@ func (h Handler) ServeTCP(pluginName, addr, daemonDir string, tlsConfig *tls.Con // ServeUnix makes the handler to listen for requests in a unix socket. // It also creates the socket file in the right directory for docker to read. -func (h Handler) ServeUnix(addr string, gid int) error { - l, spec, err := newUnixListener(addr, gid) +func (h *Handler) ServeUnix(addr string, gid int) error { + l, spec, err := NewUnixListener(addr, gid) if err != nil { return err } @@ -71,8 +81,8 @@ func (h Handler) ServeUnix(addr string, gid int) error { // Due to constrains for running Docker in Docker on Windows, data-root directory // of docker daemon must be provided. To get default directory, use // WindowsDefaultDaemonRootDir() function. On Unix, this parameter is ignored. -func (h Handler) ServeWindows(addr, pluginName, daemonDir string, pipeConfig *WindowsPipeConfig) error { - l, spec, err := newWindowsListener(addr, pluginName, daemonDir, pipeConfig) +func (h *Handler) ServeWindows(addr, pluginName, daemonDir string, pipeConfig *WindowsPipeConfig) error { + l, spec, err := NewWindowsListener(addr, pluginName, daemonDir, pipeConfig) if err != nil { return err } @@ -83,6 +93,6 @@ func (h Handler) ServeWindows(addr, pluginName, daemonDir string, pipeConfig *Wi } // HandleFunc registers a function to handle a request path with. -func (h Handler) HandleFunc(path string, fn func(w http.ResponseWriter, r *http.Request)) { +func (h *Handler) HandleFunc(path string, fn func(w http.ResponseWriter, r *http.Request)) { h.mux.HandleFunc(path, fn) } diff --git a/sdk/tcp_listener.go b/sdk/tcp_listener.go index bad85f7..047c4b8 100644 --- a/sdk/tcp_listener.go +++ b/sdk/tcp_listener.go @@ -8,7 +8,13 @@ import ( "github.com/docker/go-connections/sockets" ) -func newTCPListener(address, pluginName, daemonDir string, tlsConfig *tls.Config) (net.Listener, string, error) { +// NewTCPListener constructs a net.Listener to use for serving requests at the given TCP address. +// It also writes the spec file in the right directory for docker to read. +// +// Due to constrains for running Docker in Docker on Windows, data-root directory +// of docker daemon must be provided. To get default directory, use +// WindowsDefaultDaemonRootDir() function. On Unix, this parameter is ignored. +func NewTCPListener(address, pluginName, daemonDir string, tlsConfig *tls.Config) (net.Listener, string, error) { listener, err := sockets.NewTCPSocket(address, tlsConfig) if err != nil { return nil, "", err diff --git a/sdk/unix_listener.go b/sdk/unix_listener.go index 54b9a6d..96457c4 100644 --- a/sdk/unix_listener.go +++ b/sdk/unix_listener.go @@ -12,7 +12,9 @@ import ( const pluginSockDir = "/run/docker/plugins" -func newUnixListener(pluginName string, gid int) (net.Listener, string, error) { +// NewUnixListener constructs a net.Listener to use for serving requests at the given unix socket. +// It also creates the socket file in the right directory for docker to read. +func NewUnixListener(pluginName string, gid int) (net.Listener, string, error) { path, err := fullSocketAddress(pluginName) if err != nil { return nil, "", err diff --git a/sdk/windows_listener_unsupported.go b/sdk/windows_listener_unsupported.go index 0f5e113..b319b35 100644 --- a/sdk/windows_listener_unsupported.go +++ b/sdk/windows_listener_unsupported.go @@ -11,7 +11,13 @@ var ( errOnlySupportedOnWindows = errors.New("named pipe creation is only supported on Windows") ) -func newWindowsListener(address, pluginName, daemonRoot string, pipeConfig *WindowsPipeConfig) (net.Listener, string, error) { +// NewWindowsListener constructs a net.Listener to use for serving requests at the given Windows named pipe. +// It also creates the spec file in the right directory for docker to read. +// +// Due to constrains for running Docker in Docker on Windows, the data-root directory +// of docker daemon must be provided. To get default directory, use +// WindowsDefaultDaemonRootDir() function. On Unix, this parameter is ignored. +func NewWindowsListener(address, pluginName, daemonRoot string, pipeConfig *WindowsPipeConfig) (net.Listener, string, error) { return nil, "", errOnlySupportedOnWindows } diff --git a/secrets/api.go b/secrets/api.go index e05fd38..2c5c797 100644 --- a/secrets/api.go +++ b/secrets/api.go @@ -68,7 +68,7 @@ type Handler struct { // NewHandler initializes the request handler with a driver implementation. func NewHandler(driver Driver) *Handler { - h := &Handler{driver, sdk.NewHandler(manifest)} + h := &Handler{driver, *sdk.NewHandler(manifest)} h.initMux() return h } diff --git a/volume/api.go b/volume/api.go index dcc2f3a..f2df941 100644 --- a/volume/api.go +++ b/volume/api.go @@ -123,7 +123,7 @@ type Handler struct { // NewHandler initializes the request handler with a driver implementation. func NewHandler(driver Driver) *Handler { - h := &Handler{driver, sdk.NewHandler(manifest)} + h := &Handler{driver, *sdk.NewHandler(manifest)} h.initMux() return h }