From dd93571c69cc5284f695a21d5504fb57b1a4891a Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Wed, 30 Dec 2015 18:20:41 +0100 Subject: [PATCH 1/2] Decouple the "container" router from the actual daemon implementation. This is done by moving the following types to api/types/config.go: - ContainersConfig - ContainerAttachWithLogsConfig - ContainerWsAttachWithLogsConfig - ContainerLogsConfig - ContainerStatsConfig Remove dependency on "version" package from types.ContainerStatsConfig. Decouple the "container" router from the "daemon/exec" implementation. * This is done by making daemon.ContainerExecInspect() return an interface{} value. The same trick is already used by daemon.ContainerInspect(). Improve documentation for router packages. Extract localRoute and router into separate files. Move local.router to image.imageRouter. Changes: - Move local/image.go to image/image_routes.go. - Move local/local.go to image/image.go - Rename router to imageRouter. - Simplify imports for image/image.go (remove alias for router package). Merge router/local package into router package. Decouple the "image" router from the actual daemon implementation. Add Daemon.GetNetworkByID and Daemon.GetNetworkByName. Decouple the "network" router from the actual daemon implementation. This is done by replacing the daemon.NetworkByName constant with an explicit GetNetworkByName method. Remove the unused Daemon.GetNetwork method and the associated constants NetworkByID and NetworkByName. Signed-off-by: Lukas Waslowski Signed-off-by: David Calavera --- api/server/router/build/build.go | 7 +- api/server/router/container/backend.go | 12 +- api/server/router/container/container.go | 65 +++++------ .../router/container/container_routes.go | 14 +-- api/server/router/image/backend.go | 44 +++++++ api/server/router/image/image.go | 44 +++++++ .../{local/image.go => image/image_routes.go} | 22 ++-- api/server/router/local.go | 61 ++++++++++ api/server/router/local/local.go | 107 ------------------ api/server/router/network/backend.go | 15 ++- api/server/router/network/network.go | 13 +-- api/server/router/network/network_routes.go | 3 +- api/server/router/router.go | 3 +- api/server/router/system/system.go | 26 ++--- api/server/router/volume/volume.go | 17 ++- api/server/server.go | 4 +- daemon/attach.go | 27 +---- daemon/list.go | 31 ++--- daemon/logs.go | 21 +--- daemon/network.go | 63 +++++------ daemon/stats.go | 17 +-- 21 files changed, 286 insertions(+), 330 deletions(-) create mode 100644 api/server/router/image/backend.go create mode 100644 api/server/router/image/image.go rename api/server/router/{local/image.go => image/image_routes.go} (88%) create mode 100644 api/server/router/local.go delete mode 100644 api/server/router/local/local.go diff --git a/api/server/router/build/build.go b/api/server/router/build/build.go index 166f97bc66..dc85d1df00 100644 --- a/api/server/router/build/build.go +++ b/api/server/router/build/build.go @@ -1,9 +1,6 @@ package build -import ( - "github.com/docker/docker/api/server/router" - "github.com/docker/docker/api/server/router/local" -) +import "github.com/docker/docker/api/server/router" // buildRouter is a router to talk with the build controller type buildRouter struct { @@ -27,6 +24,6 @@ func (r *buildRouter) Routes() []router.Route { func (r *buildRouter) initRoutes() { r.routes = []router.Route{ - local.NewPostRoute("/build", r.postBuild), + router.NewPostRoute("/build", r.postBuild), } } diff --git a/api/server/router/container/backend.go b/api/server/router/container/backend.go index 80bed6442e..145a1b7424 100644 --- a/api/server/router/container/backend.go +++ b/api/server/router/container/backend.go @@ -4,11 +4,11 @@ import ( "io" "time" - "github.com/docker/docker/daemon" "github.com/docker/docker/daemon/exec" "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/version" "github.com/docker/engine-api/types" + "github.com/docker/engine-api/types/backend" "github.com/docker/engine-api/types/container" ) @@ -51,17 +51,17 @@ type stateBackend interface { type monitorBackend interface { ContainerChanges(name string) ([]archive.Change, error) ContainerInspect(name string, size bool, version version.Version) (interface{}, error) - ContainerLogs(name string, config *daemon.ContainerLogsConfig) error - ContainerStats(name string, config *daemon.ContainerStatsConfig) error + ContainerLogs(name string, config *backend.ContainerLogsConfig) error + ContainerStats(name string, config *backend.ContainerStatsConfig) error ContainerTop(name string, psArgs string) (*types.ContainerProcessList, error) - Containers(config *daemon.ContainersConfig) ([]*types.Container, error) + Containers(config *backend.ContainersConfig) ([]*types.Container, error) } // attachBackend includes function to implement to provide container attaching functionality. type attachBackend interface { - ContainerAttachWithLogs(name string, c *daemon.ContainerAttachWithLogsConfig) error - ContainerWsAttachWithLogs(name string, c *daemon.ContainerWsAttachWithLogsConfig) error + ContainerAttachWithLogs(name string, c *backend.ContainerAttachWithLogsConfig) error + ContainerWsAttachWithLogs(name string, c *backend.ContainerWsAttachWithLogsConfig) error } // Backend is all the methods that need to be implemented to provide container specific functionality. diff --git a/api/server/router/container/container.go b/api/server/router/container/container.go index dd931650dd..873f13d295 100644 --- a/api/server/router/container/container.go +++ b/api/server/router/container/container.go @@ -1,9 +1,6 @@ package container -import ( - "github.com/docker/docker/api/server/router" - "github.com/docker/docker/api/server/router/local" -) +import "github.com/docker/docker/api/server/router" // containerRouter is a router to talk with the container controller type containerRouter struct { @@ -20,7 +17,7 @@ func NewRouter(b Backend) router.Router { return r } -// Routes returns the available routers to the container controller +// Routes returns the available routes to the container controller func (r *containerRouter) Routes() []router.Route { return r.routes } @@ -29,38 +26,38 @@ func (r *containerRouter) Routes() []router.Route { func (r *containerRouter) initRoutes() { r.routes = []router.Route{ // HEAD - local.NewHeadRoute("/containers/{name:.*}/archive", r.headContainersArchive), + router.NewHeadRoute("/containers/{name:.*}/archive", r.headContainersArchive), // GET - local.NewGetRoute("/containers/json", r.getContainersJSON), - local.NewGetRoute("/containers/{name:.*}/export", r.getContainersExport), - local.NewGetRoute("/containers/{name:.*}/changes", r.getContainersChanges), - local.NewGetRoute("/containers/{name:.*}/json", r.getContainersByName), - local.NewGetRoute("/containers/{name:.*}/top", r.getContainersTop), - local.NewGetRoute("/containers/{name:.*}/logs", r.getContainersLogs), - local.NewGetRoute("/containers/{name:.*}/stats", r.getContainersStats), - local.NewGetRoute("/containers/{name:.*}/attach/ws", r.wsContainersAttach), - local.NewGetRoute("/exec/{id:.*}/json", r.getExecByID), - local.NewGetRoute("/containers/{name:.*}/archive", r.getContainersArchive), + router.NewGetRoute("/containers/json", r.getContainersJSON), + router.NewGetRoute("/containers/{name:.*}/export", r.getContainersExport), + router.NewGetRoute("/containers/{name:.*}/changes", r.getContainersChanges), + router.NewGetRoute("/containers/{name:.*}/json", r.getContainersByName), + router.NewGetRoute("/containers/{name:.*}/top", r.getContainersTop), + router.NewGetRoute("/containers/{name:.*}/logs", r.getContainersLogs), + router.NewGetRoute("/containers/{name:.*}/stats", r.getContainersStats), + router.NewGetRoute("/containers/{name:.*}/attach/ws", r.wsContainersAttach), + router.NewGetRoute("/exec/{id:.*}/json", r.getExecByID), + router.NewGetRoute("/containers/{name:.*}/archive", r.getContainersArchive), // POST - local.NewPostRoute("/containers/create", r.postContainersCreate), - local.NewPostRoute("/containers/{name:.*}/kill", r.postContainersKill), - local.NewPostRoute("/containers/{name:.*}/pause", r.postContainersPause), - local.NewPostRoute("/containers/{name:.*}/unpause", r.postContainersUnpause), - local.NewPostRoute("/containers/{name:.*}/restart", r.postContainersRestart), - local.NewPostRoute("/containers/{name:.*}/start", r.postContainersStart), - local.NewPostRoute("/containers/{name:.*}/stop", r.postContainersStop), - local.NewPostRoute("/containers/{name:.*}/wait", r.postContainersWait), - local.NewPostRoute("/containers/{name:.*}/resize", r.postContainersResize), - local.NewPostRoute("/containers/{name:.*}/attach", r.postContainersAttach), - local.NewPostRoute("/containers/{name:.*}/copy", r.postContainersCopy), - local.NewPostRoute("/containers/{name:.*}/exec", r.postContainerExecCreate), - local.NewPostRoute("/exec/{name:.*}/start", r.postContainerExecStart), - local.NewPostRoute("/exec/{name:.*}/resize", r.postContainerExecResize), - local.NewPostRoute("/containers/{name:.*}/rename", r.postContainerRename), - local.NewPostRoute("/containers/{name:.*}/update", r.postContainerUpdate), + router.NewPostRoute("/containers/create", r.postContainersCreate), + router.NewPostRoute("/containers/{name:.*}/kill", r.postContainersKill), + router.NewPostRoute("/containers/{name:.*}/pause", r.postContainersPause), + router.NewPostRoute("/containers/{name:.*}/unpause", r.postContainersUnpause), + router.NewPostRoute("/containers/{name:.*}/restart", r.postContainersRestart), + router.NewPostRoute("/containers/{name:.*}/start", r.postContainersStart), + router.NewPostRoute("/containers/{name:.*}/stop", r.postContainersStop), + router.NewPostRoute("/containers/{name:.*}/wait", r.postContainersWait), + router.NewPostRoute("/containers/{name:.*}/resize", r.postContainersResize), + router.NewPostRoute("/containers/{name:.*}/attach", r.postContainersAttach), + router.NewPostRoute("/containers/{name:.*}/copy", r.postContainersCopy), + router.NewPostRoute("/containers/{name:.*}/exec", r.postContainerExecCreate), + router.NewPostRoute("/exec/{name:.*}/start", r.postContainerExecStart), + router.NewPostRoute("/exec/{name:.*}/resize", r.postContainerExecResize), + router.NewPostRoute("/containers/{name:.*}/rename", r.postContainerRename), + router.NewPostRoute("/containers/{name:.*}/update", r.postContainerUpdate), // PUT - local.NewPutRoute("/containers/{name:.*}/archive", r.putContainersArchive), + router.NewPutRoute("/containers/{name:.*}/archive", r.putContainersArchive), // DELETE - local.NewDeleteRoute("/containers/{name:.*}", r.deleteContainers), + router.NewDeleteRoute("/containers/{name:.*}", r.deleteContainers), } } diff --git a/api/server/router/container/container_routes.go b/api/server/router/container/container_routes.go index 4e2ffca29b..cd429e1d72 100644 --- a/api/server/router/container/container_routes.go +++ b/api/server/router/container/container_routes.go @@ -13,7 +13,6 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/distribution/registry/api/errcode" "github.com/docker/docker/api/server/httputils" - "github.com/docker/docker/daemon" derr "github.com/docker/docker/errors" "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/signal" @@ -21,6 +20,7 @@ import ( "github.com/docker/docker/runconfig" "github.com/docker/docker/utils" "github.com/docker/engine-api/types" + "github.com/docker/engine-api/types/backend" "github.com/docker/engine-api/types/container" timetypes "github.com/docker/engine-api/types/time" "golang.org/x/net/context" @@ -32,7 +32,7 @@ func (s *containerRouter) getContainersJSON(ctx context.Context, w http.Response return err } - config := &daemon.ContainersConfig{ + config := &backend.ContainersConfig{ All: httputils.BoolValue(r, "all"), Size: httputils.BoolValue(r, "size"), Since: r.Form.Get("since"), @@ -77,11 +77,11 @@ func (s *containerRouter) getContainersStats(ctx context.Context, w http.Respons closeNotifier = notifier.CloseNotify() } - config := &daemon.ContainerStatsConfig{ + config := &backend.ContainerStatsConfig{ Stream: stream, OutStream: out, Stop: closeNotifier, - Version: httputils.VersionFromContext(ctx), + Version: string(httputils.VersionFromContext(ctx)), } return s.backend.ContainerStats(vars["name"], config) @@ -133,7 +133,7 @@ func (s *containerRouter) getContainersLogs(ctx context.Context, w http.Response output := ioutils.NewWriteFlusher(w) defer output.Close() - logsConfig := &daemon.ContainerLogsConfig{ + logsConfig := &backend.ContainerLogsConfig{ Follow: httputils.BoolValue(r, "follow"), Timestamps: httputils.BoolValue(r, "timestamps"), Since: since, @@ -446,7 +446,7 @@ func (s *containerRouter) postContainersAttach(ctx context.Context, w http.Respo } } - attachWithLogsConfig := &daemon.ContainerAttachWithLogsConfig{ + attachWithLogsConfig := &backend.ContainerAttachWithLogsConfig{ Hijacker: w.(http.Hijacker), Upgrade: upgrade, UseStdin: httputils.BoolValue(r, "stdin"), @@ -483,7 +483,7 @@ func (s *containerRouter) wsContainersAttach(ctx context.Context, w http.Respons h := websocket.Handler(func(ws *websocket.Conn) { defer ws.Close() - wsAttachWithLogsConfig := &daemon.ContainerWsAttachWithLogsConfig{ + wsAttachWithLogsConfig := &backend.ContainerWsAttachWithLogsConfig{ InStream: ws, OutStream: ws, ErrStream: ws, diff --git a/api/server/router/image/backend.go b/api/server/router/image/backend.go new file mode 100644 index 0000000000..e312307d93 --- /dev/null +++ b/api/server/router/image/backend.go @@ -0,0 +1,44 @@ +package image + +import ( + "io" + + "github.com/docker/docker/reference" + "github.com/docker/engine-api/types" + "github.com/docker/engine-api/types/container" + "github.com/docker/engine-api/types/registry" +) + +// Backend is all the methods that need to be implemented +// to provide image specific functionality. +type Backend interface { + containerBackend + imageBackend + importExportBackend + registryBackend +} + +type containerBackend interface { + Commit(name string, config *types.ContainerCommitConfig) (imageID string, err error) + Exists(containerName string) bool +} + +type imageBackend interface { + ImageDelete(imageRef string, force, prune bool) ([]types.ImageDelete, error) + ImageHistory(imageName string) ([]*types.ImageHistory, error) + Images(filterArgs string, filter string, all bool) ([]*types.Image, error) + LookupImage(name string) (*types.ImageInspect, error) + TagImage(newTag reference.Named, imageName string) error +} + +type importExportBackend interface { + LoadImage(inTar io.ReadCloser, outStream io.Writer) error + ImportImage(src string, newRef reference.Named, msg string, inConfig io.ReadCloser, outStream io.Writer, config *container.Config) error + ExportImage(names []string, outStream io.Writer) error +} + +type registryBackend interface { + PullImage(ref reference.Named, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error + PushImage(ref reference.Named, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error + SearchRegistryForImages(term string, authConfig *types.AuthConfig, metaHeaders map[string][]string) (*registry.SearchResults, error) +} diff --git a/api/server/router/image/image.go b/api/server/router/image/image.go new file mode 100644 index 0000000000..e1b6bed9d7 --- /dev/null +++ b/api/server/router/image/image.go @@ -0,0 +1,44 @@ +package image + +import "github.com/docker/docker/api/server/router" + +// imageRouter is a router to talk with the image controller +type imageRouter struct { + daemon Backend + routes []router.Route +} + +// NewRouter initializes a new image router +func NewRouter(daemon Backend) router.Router { + r := &imageRouter{ + daemon: daemon, + } + r.initRoutes() + return r +} + +// Routes returns the available routes to the image controller +func (r *imageRouter) Routes() []router.Route { + return r.routes +} + +// initRoutes initializes the routes in the image router +func (r *imageRouter) initRoutes() { + r.routes = []router.Route{ + // GET + router.NewGetRoute("/images/json", r.getImagesJSON), + router.NewGetRoute("/images/search", r.getImagesSearch), + router.NewGetRoute("/images/get", r.getImagesGet), + router.NewGetRoute("/images/{name:.*}/get", r.getImagesGet), + router.NewGetRoute("/images/{name:.*}/history", r.getImagesHistory), + router.NewGetRoute("/images/{name:.*}/json", r.getImagesByName), + // POST + router.NewPostRoute("/commit", r.postCommit), + router.NewPostRoute("/images/create", r.postImagesCreate), + router.NewPostRoute("/images/load", r.postImagesLoad), + router.NewPostRoute("/images/{name:.*}/push", r.postImagesPush), + router.NewPostRoute("/images/{name:.*}/tag", r.postImagesTag), + // DELETE + router.NewDeleteRoute("/images/{name:.*}", r.deleteImages), + } +} diff --git a/api/server/router/local/image.go b/api/server/router/image/image_routes.go similarity index 88% rename from api/server/router/local/image.go rename to api/server/router/image/image_routes.go index 3427649f59..bf95d5592f 100644 --- a/api/server/router/local/image.go +++ b/api/server/router/image/image_routes.go @@ -1,4 +1,4 @@ -package local +package image import ( "encoding/base64" @@ -24,7 +24,7 @@ import ( "golang.org/x/net/context" ) -func (s *router) postCommit(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *imageRouter) postCommit(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } @@ -79,7 +79,7 @@ func (s *router) postCommit(ctx context.Context, w http.ResponseWriter, r *http. } // Creates an image from Pull or from Import -func (s *router) postImagesCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } @@ -188,7 +188,7 @@ func (s *router) postImagesCreate(ctx context.Context, w http.ResponseWriter, r return nil } -func (s *router) postImagesPush(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *imageRouter) postImagesPush(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { metaHeaders := map[string][]string{} for k, v := range r.Header { if strings.HasPrefix(k, "X-Meta-") { @@ -243,7 +243,7 @@ func (s *router) postImagesPush(ctx context.Context, w http.ResponseWriter, r *h return nil } -func (s *router) getImagesGet(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *imageRouter) getImagesGet(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } @@ -278,7 +278,7 @@ func (s *router) postImagesLoad(ctx context.Context, w http.ResponseWriter, r *h return s.daemon.LoadImage(r.Body, w, quiet) } -func (s *router) deleteImages(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *imageRouter) deleteImages(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } @@ -300,7 +300,7 @@ func (s *router) deleteImages(ctx context.Context, w http.ResponseWriter, r *htt return httputils.WriteJSON(w, http.StatusOK, list) } -func (s *router) getImagesByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *imageRouter) getImagesByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { imageInspect, err := s.daemon.LookupImage(vars["name"]) if err != nil { return err @@ -309,7 +309,7 @@ func (s *router) getImagesByName(ctx context.Context, w http.ResponseWriter, r * return httputils.WriteJSON(w, http.StatusOK, imageInspect) } -func (s *router) getImagesJSON(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *imageRouter) getImagesJSON(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } @@ -323,7 +323,7 @@ func (s *router) getImagesJSON(ctx context.Context, w http.ResponseWriter, r *ht return httputils.WriteJSON(w, http.StatusOK, images) } -func (s *router) getImagesHistory(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *imageRouter) getImagesHistory(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { name := vars["name"] history, err := s.daemon.ImageHistory(name) if err != nil { @@ -333,7 +333,7 @@ func (s *router) getImagesHistory(ctx context.Context, w http.ResponseWriter, r return httputils.WriteJSON(w, http.StatusOK, history) } -func (s *router) postImagesTag(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *imageRouter) postImagesTag(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } @@ -355,7 +355,7 @@ func (s *router) postImagesTag(ctx context.Context, w http.ResponseWriter, r *ht return nil } -func (s *router) getImagesSearch(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *imageRouter) getImagesSearch(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } diff --git a/api/server/router/local.go b/api/server/router/local.go new file mode 100644 index 0000000000..99db4242b3 --- /dev/null +++ b/api/server/router/local.go @@ -0,0 +1,61 @@ +package router + +import "github.com/docker/docker/api/server/httputils" + +// localRoute defines an individual API route to connect +// with the docker daemon. It implements Route. +type localRoute struct { + method string + path string + handler httputils.APIFunc +} + +// Handler returns the APIFunc to let the server wrap it in middlewares. +func (l localRoute) Handler() httputils.APIFunc { + return l.handler +} + +// Method returns the http method that the route responds to. +func (l localRoute) Method() string { + return l.method +} + +// Path returns the subpath where the route responds to. +func (l localRoute) Path() string { + return l.path +} + +// NewRoute initializes a new local route for the router. +func NewRoute(method, path string, handler httputils.APIFunc) Route { + return localRoute{method, path, handler} +} + +// NewGetRoute initializes a new route with the http method GET. +func NewGetRoute(path string, handler httputils.APIFunc) Route { + return NewRoute("GET", path, handler) +} + +// NewPostRoute initializes a new route with the http method POST. +func NewPostRoute(path string, handler httputils.APIFunc) Route { + return NewRoute("POST", path, handler) +} + +// NewPutRoute initializes a new route with the http method PUT. +func NewPutRoute(path string, handler httputils.APIFunc) Route { + return NewRoute("PUT", path, handler) +} + +// NewDeleteRoute initializes a new route with the http method DELETE. +func NewDeleteRoute(path string, handler httputils.APIFunc) Route { + return NewRoute("DELETE", path, handler) +} + +// NewOptionsRoute initializes a new route with the http method OPTIONS. +func NewOptionsRoute(path string, handler httputils.APIFunc) Route { + return NewRoute("OPTIONS", path, handler) +} + +// NewHeadRoute initializes a new route with the http method HEAD. +func NewHeadRoute(path string, handler httputils.APIFunc) Route { + return NewRoute("HEAD", path, handler) +} diff --git a/api/server/router/local/local.go b/api/server/router/local/local.go deleted file mode 100644 index ed07f97786..0000000000 --- a/api/server/router/local/local.go +++ /dev/null @@ -1,107 +0,0 @@ -package local - -import ( - "github.com/docker/docker/api/server/httputils" - dkrouter "github.com/docker/docker/api/server/router" - "github.com/docker/docker/daemon" -) - -// router is a docker router that talks with the local docker daemon. -type router struct { - daemon *daemon.Daemon - routes []dkrouter.Route -} - -// localRoute defines an individual API route to connect with the docker daemon. -// It implements router.Route. -type localRoute struct { - method string - path string - handler httputils.APIFunc -} - -// Handler returns the APIFunc to let the server wrap it in middlewares -func (l localRoute) Handler() httputils.APIFunc { - return l.handler -} - -// Method returns the http method that the route responds to. -func (l localRoute) Method() string { - return l.method -} - -// Path returns the subpath where the route responds to. -func (l localRoute) Path() string { - return l.path -} - -// NewRoute initializes a new local router for the reouter -func NewRoute(method, path string, handler httputils.APIFunc) dkrouter.Route { - return localRoute{method, path, handler} -} - -// NewGetRoute initializes a new route with the http method GET. -func NewGetRoute(path string, handler httputils.APIFunc) dkrouter.Route { - return NewRoute("GET", path, handler) -} - -// NewPostRoute initializes a new route with the http method POST. -func NewPostRoute(path string, handler httputils.APIFunc) dkrouter.Route { - return NewRoute("POST", path, handler) -} - -// NewPutRoute initializes a new route with the http method PUT. -func NewPutRoute(path string, handler httputils.APIFunc) dkrouter.Route { - return NewRoute("PUT", path, handler) -} - -// NewDeleteRoute initializes a new route with the http method DELETE. -func NewDeleteRoute(path string, handler httputils.APIFunc) dkrouter.Route { - return NewRoute("DELETE", path, handler) -} - -// NewOptionsRoute initializes a new route with the http method OPTIONS -func NewOptionsRoute(path string, handler httputils.APIFunc) dkrouter.Route { - return NewRoute("OPTIONS", path, handler) -} - -// NewHeadRoute initializes a new route with the http method HEAD. -func NewHeadRoute(path string, handler httputils.APIFunc) dkrouter.Route { - return NewRoute("HEAD", path, handler) -} - -// NewRouter initializes a local router with a new daemon. -func NewRouter(daemon *daemon.Daemon) dkrouter.Router { - r := &router{ - daemon: daemon, - } - r.initRoutes() - return r -} - -// Routes returns the list of routes registered in the router. -func (r *router) Routes() []dkrouter.Route { - return r.routes -} - -// initRoutes initializes the routes in this router -func (r *router) initRoutes() { - r.routes = []dkrouter.Route{ - // OPTIONS - // GET - NewGetRoute("/images/json", r.getImagesJSON), - NewGetRoute("/images/search", r.getImagesSearch), - NewGetRoute("/images/get", r.getImagesGet), - NewGetRoute("/images/{name:.*}/get", r.getImagesGet), - NewGetRoute("/images/{name:.*}/history", r.getImagesHistory), - NewGetRoute("/images/{name:.*}/json", r.getImagesByName), - // POST - NewPostRoute("/commit", r.postCommit), - NewPostRoute("/images/create", r.postImagesCreate), - NewPostRoute("/images/load", r.postImagesLoad), - NewPostRoute("/images/{name:.*}/push", r.postImagesPush), - NewPostRoute("/images/{name:.*}/tag", r.postImagesTag), - // DELETE - NewDeleteRoute("/images/{name:.*}", r.deleteImages), - } -} diff --git a/api/server/router/network/backend.go b/api/server/router/network/backend.go index c6ea0adcf8..113c497ce1 100644 --- a/api/server/router/network/backend.go +++ b/api/server/router/network/backend.go @@ -5,18 +5,17 @@ import ( "github.com/docker/libnetwork" ) -// Backend is all the methods that need to be implemented to provide -// network specific functionality +// Backend is all the methods that need to be implemented +// to provide network specific functionality. type Backend interface { + NetworkControllerEnabled() bool + FindNetwork(idName string) (libnetwork.Network, error) - GetNetwork(idName string, by int) (libnetwork.Network, error) + GetNetworkByName(idName string) (libnetwork.Network, error) GetNetworksByID(partialID string) []libnetwork.Network GetAllNetworks() []libnetwork.Network - CreateNetwork(name, driver string, ipam network.IPAM, - options map[string]string, internal bool) (libnetwork.Network, error) + CreateNetwork(name, driver string, ipam network.IPAM, options map[string]string, internal bool) (libnetwork.Network, error) ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error - DisconnectContainerFromNetwork(containerName string, - network libnetwork.Network, force bool) error - NetworkControllerEnabled() bool + DisconnectContainerFromNetwork(containerName string, network libnetwork.Network, force bool) error DeleteNetwork(name string) error } diff --git a/api/server/router/network/network.go b/api/server/router/network/network.go index 5fcb252c2b..59641bc03b 100644 --- a/api/server/router/network/network.go +++ b/api/server/router/network/network.go @@ -5,7 +5,6 @@ import ( "github.com/docker/docker/api/server/httputils" "github.com/docker/docker/api/server/router" - "github.com/docker/docker/api/server/router/local" "github.com/docker/docker/errors" "golang.org/x/net/context" ) @@ -33,14 +32,14 @@ func (r *networkRouter) Routes() []router.Route { func (r *networkRouter) initRoutes() { r.routes = []router.Route{ // GET - local.NewGetRoute("/networks", r.controllerEnabledMiddleware(r.getNetworksList)), - local.NewGetRoute("/networks/{id:.*}", r.controllerEnabledMiddleware(r.getNetwork)), + router.NewGetRoute("/networks", r.controllerEnabledMiddleware(r.getNetworksList)), + router.NewGetRoute("/networks/{id:.*}", r.controllerEnabledMiddleware(r.getNetwork)), // POST - local.NewPostRoute("/networks/create", r.controllerEnabledMiddleware(r.postNetworkCreate)), - local.NewPostRoute("/networks/{id:.*}/connect", r.controllerEnabledMiddleware(r.postNetworkConnect)), - local.NewPostRoute("/networks/{id:.*}/disconnect", r.controllerEnabledMiddleware(r.postNetworkDisconnect)), + router.NewPostRoute("/networks/create", r.controllerEnabledMiddleware(r.postNetworkCreate)), + router.NewPostRoute("/networks/{id:.*}/connect", r.controllerEnabledMiddleware(r.postNetworkConnect)), + router.NewPostRoute("/networks/{id:.*}/disconnect", r.controllerEnabledMiddleware(r.postNetworkDisconnect)), // DELETE - local.NewDeleteRoute("/networks/{id:.*}", r.controllerEnabledMiddleware(r.deleteNetwork)), + router.NewDeleteRoute("/networks/{id:.*}", r.controllerEnabledMiddleware(r.deleteNetwork)), } } diff --git a/api/server/router/network/network_routes.go b/api/server/router/network/network_routes.go index 9798a0b947..25f0e83ca6 100644 --- a/api/server/router/network/network_routes.go +++ b/api/server/router/network/network_routes.go @@ -8,7 +8,6 @@ import ( "golang.org/x/net/context" "github.com/docker/docker/api/server/httputils" - "github.com/docker/docker/daemon" "github.com/docker/docker/runconfig" "github.com/docker/engine-api/types" "github.com/docker/engine-api/types/filters" @@ -81,7 +80,7 @@ func (n *networkRouter) postNetworkCreate(ctx context.Context, w http.ResponseWr fmt.Sprintf("%s is a pre-defined network and cannot be created", create.Name)) } - nw, err := n.backend.GetNetwork(create.Name, daemon.NetworkByName) + nw, err := n.backend.GetNetworkByName(create.Name) if _, ok := err.(libnetwork.ErrNoSuchNetwork); err != nil && !ok { return err } diff --git a/api/server/router/router.go b/api/server/router/router.go index f3efa82fa6..2de25c27ff 100644 --- a/api/server/router/router.go +++ b/api/server/router/router.go @@ -2,8 +2,9 @@ package router import "github.com/docker/docker/api/server/httputils" -// Router defines an interface to specify a group of routes to add the the docker server. +// Router defines an interface to specify a group of routes to add to the docker server. type Router interface { + // Routes returns the list of routes to add to the docker server. Routes() []Route } diff --git a/api/server/router/system/system.go b/api/server/router/system/system.go index 1bcea2b4f2..76da5c52d5 100644 --- a/api/server/router/system/system.go +++ b/api/server/router/system/system.go @@ -1,37 +1,33 @@ package system -import ( - "github.com/docker/docker/api/server/router" - "github.com/docker/docker/api/server/router/local" -) +import "github.com/docker/docker/api/server/router" -// systemRouter is a Router that provides information about -// the Docker system overall. It gathers information about -// host, daemon and container events. +// systemRouter provides information about the Docker system overall. +// It gathers information about host, daemon and container events. type systemRouter struct { backend Backend routes []router.Route } -// NewRouter initializes a new systemRouter +// NewRouter initializes a new system router func NewRouter(b Backend) router.Router { r := &systemRouter{ backend: b, } r.routes = []router.Route{ - local.NewOptionsRoute("/{anyroute:.*}", optionsHandler), - local.NewGetRoute("/_ping", pingHandler), - local.NewGetRoute("/events", r.getEvents), - local.NewGetRoute("/info", r.getInfo), - local.NewGetRoute("/version", r.getVersion), - local.NewPostRoute("/auth", r.postAuth), + router.NewOptionsRoute("/{anyroute:.*}", optionsHandler), + router.NewGetRoute("/_ping", pingHandler), + router.NewGetRoute("/events", r.getEvents), + router.NewGetRoute("/info", r.getInfo), + router.NewGetRoute("/version", r.getVersion), + router.NewPostRoute("/auth", r.postAuth), } return r } -// Routes return all the API routes dedicated to the docker system. +// Routes returns all the API routes dedicated to the docker system func (s *systemRouter) Routes() []router.Route { return s.routes } diff --git a/api/server/router/volume/volume.go b/api/server/router/volume/volume.go index 8bd5c12906..2683dcec52 100644 --- a/api/server/router/volume/volume.go +++ b/api/server/router/volume/volume.go @@ -1,9 +1,6 @@ package volume -import ( - "github.com/docker/docker/api/server/router" - "github.com/docker/docker/api/server/router/local" -) +import "github.com/docker/docker/api/server/router" // volumeRouter is a router to talk with the volumes controller type volumeRouter struct { @@ -11,7 +8,7 @@ type volumeRouter struct { routes []router.Route } -// NewRouter initializes a new volumeRouter +// NewRouter initializes a new volume router func NewRouter(b Backend) router.Router { r := &volumeRouter{ backend: b, @@ -20,7 +17,7 @@ func NewRouter(b Backend) router.Router { return r } -//Routes returns the available routers to the volumes controller +// Routes returns the available routes to the volumes controller func (r *volumeRouter) Routes() []router.Route { return r.routes } @@ -28,11 +25,11 @@ func (r *volumeRouter) Routes() []router.Route { func (r *volumeRouter) initRoutes() { r.routes = []router.Route{ // GET - local.NewGetRoute("/volumes", r.getVolumesList), - local.NewGetRoute("/volumes/{name:.*}", r.getVolumeByName), + router.NewGetRoute("/volumes", r.getVolumesList), + router.NewGetRoute("/volumes/{name:.*}", r.getVolumeByName), // POST - local.NewPostRoute("/volumes/create", r.postVolumesCreate), + router.NewPostRoute("/volumes/create", r.postVolumesCreate), // DELETE - local.NewDeleteRoute("/volumes/{name:.*}", r.deleteVolumes), + router.NewDeleteRoute("/volumes/{name:.*}", r.deleteVolumes), } } diff --git a/api/server/server.go b/api/server/server.go index a42cd1720b..5e8337a7c2 100644 --- a/api/server/server.go +++ b/api/server/server.go @@ -11,7 +11,7 @@ import ( "github.com/docker/docker/api/server/router" "github.com/docker/docker/api/server/router/build" "github.com/docker/docker/api/server/router/container" - "github.com/docker/docker/api/server/router/local" + "github.com/docker/docker/api/server/router/image" "github.com/docker/docker/api/server/router/network" "github.com/docker/docker/api/server/router/system" "github.com/docker/docker/api/server/router/volume" @@ -177,7 +177,7 @@ func (s *Server) makeHTTPHandler(handler httputils.APIFunc) http.HandlerFunc { // InitRouters initializes a list of routers for the server. func (s *Server) InitRouters(d *daemon.Daemon) { s.addRouter(container.NewRouter(d)) - s.addRouter(local.NewRouter(d)) + s.addRouter(image.NewRouter(d)) s.addRouter(network.NewRouter(d)) s.addRouter(system.NewRouter(d)) s.addRouter(volume.NewRouter(d)) diff --git a/daemon/attach.go b/daemon/attach.go index f0caf16996..aabc77082a 100644 --- a/daemon/attach.go +++ b/daemon/attach.go @@ -3,7 +3,6 @@ package daemon import ( "fmt" "io" - "net/http" "time" "github.com/Sirupsen/logrus" @@ -11,22 +10,11 @@ import ( "github.com/docker/docker/daemon/logger" derr "github.com/docker/docker/errors" "github.com/docker/docker/pkg/stdcopy" + "github.com/docker/engine-api/types/backend" ) -// ContainerAttachWithLogsConfig holds the streams to use when connecting to a container to view logs. -type ContainerAttachWithLogsConfig struct { - Hijacker http.Hijacker - Upgrade bool - UseStdin bool - UseStdout bool - UseStderr bool - Logs bool - Stream bool - DetachKeys []byte -} - // ContainerAttachWithLogs attaches to logs according to the config passed in. See ContainerAttachWithLogsConfig. -func (daemon *Daemon) ContainerAttachWithLogs(prefixOrName string, c *ContainerAttachWithLogsConfig) error { +func (daemon *Daemon) ContainerAttachWithLogs(prefixOrName string, c *backend.ContainerAttachWithLogsConfig) error { if c.Hijacker == nil { return derr.ErrorCodeNoHijackConnection.WithArgs(prefixOrName) } @@ -82,17 +70,8 @@ func (daemon *Daemon) ContainerAttachWithLogs(prefixOrName string, c *ContainerA return nil } -// ContainerWsAttachWithLogsConfig attach with websockets, since all -// stream data is delegated to the websocket to handle there. -type ContainerWsAttachWithLogsConfig struct { - InStream io.ReadCloser - OutStream, ErrStream io.Writer - Logs, Stream bool - DetachKeys []byte -} - // ContainerWsAttachWithLogs websocket connection -func (daemon *Daemon) ContainerWsAttachWithLogs(prefixOrName string, c *ContainerWsAttachWithLogsConfig) error { +func (daemon *Daemon) ContainerWsAttachWithLogs(prefixOrName string, c *backend.ContainerWsAttachWithLogsConfig) error { container, err := daemon.GetContainer(prefixOrName) if err != nil { return err diff --git a/daemon/list.go b/daemon/list.go index c363814cfb..5761ca40c5 100644 --- a/daemon/list.go +++ b/daemon/list.go @@ -10,6 +10,7 @@ import ( "github.com/docker/docker/container" "github.com/docker/docker/image" "github.com/docker/engine-api/types" + "github.com/docker/engine-api/types/backend" "github.com/docker/engine-api/types/filters" networktypes "github.com/docker/engine-api/types/network" "github.com/docker/go-connections/nat" @@ -43,24 +44,8 @@ func (daemon *Daemon) List() []*container.Container { return daemon.containers.List() } -// ContainersConfig is the filtering specified by the user to iterate over containers. -type ContainersConfig struct { - // if true show all containers, otherwise only running containers. - All bool - // show all containers created after this container id - Since string - // show all containers created before this container id - Before string - // number of containers to return at most - Limit int - // if true include the sizes of the containers - Size bool - // return only containers that match filters - Filters string -} - // listContext is the daemon generated filtering to iterate over containers. -// This is created based on the user specification. +// This is created based on the user specification from backend.ContainersConfig. type listContext struct { // idx is the container iteration index for this context idx int @@ -81,16 +66,16 @@ type listContext struct { // this is used for --filter=since= and --since=, the latter is deprecated. sinceFilter *container.Container // ContainersConfig is the filters set by the user - *ContainersConfig + *backend.ContainersConfig } // Containers returns the list of containers to show given the user's filtering. -func (daemon *Daemon) Containers(config *ContainersConfig) ([]*types.Container, error) { +func (daemon *Daemon) Containers(config *backend.ContainersConfig) ([]*types.Container, error) { return daemon.reduceContainers(config, daemon.transformContainer) } -// reduceContainer parses the user filtering and generates the list of containers to return based on a reducer. -func (daemon *Daemon) reduceContainers(config *ContainersConfig, reducer containerReducer) ([]*types.Container, error) { +// reduceContainers parses the user's filtering options and generates the list of containers to return based on a reducer. +func (daemon *Daemon) reduceContainers(config *backend.ContainersConfig, reducer containerReducer) ([]*types.Container, error) { containers := []*types.Container{} ctx, err := daemon.foldFilter(config) @@ -132,8 +117,8 @@ func (daemon *Daemon) reducePsContainer(container *container.Container, ctx *lis return reducer(container, ctx) } -// foldFilter generates the container filter based in the user's filtering options. -func (daemon *Daemon) foldFilter(config *ContainersConfig) (*listContext, error) { +// foldFilter generates the container filter based on the user's filtering options. +func (daemon *Daemon) foldFilter(config *backend.ContainersConfig) (*listContext, error) { psFilters, err := filters.FromParam(config.Filters) if err != nil { return nil, err diff --git a/daemon/logs.go b/daemon/logs.go index b10f7df769..bb6586f272 100644 --- a/daemon/logs.go +++ b/daemon/logs.go @@ -3,7 +3,6 @@ package daemon import ( "io" "strconv" - "time" "github.com/Sirupsen/logrus" "github.com/docker/docker/container" @@ -11,28 +10,12 @@ import ( "github.com/docker/docker/daemon/logger/jsonfilelog" derr "github.com/docker/docker/errors" "github.com/docker/docker/pkg/stdcopy" + "github.com/docker/engine-api/types/backend" ) -// ContainerLogsConfig holds configs for logging operations. Exists -// for users of the daemon to to pass it a logging configuration. -type ContainerLogsConfig struct { - // if true stream log output - Follow bool - // if true include timestamps for each line of log output - Timestamps bool - // return that many lines of log output from the end - Tail string - // filter logs by returning on those entries after this time - Since time.Time - // whether or not to show stdout and stderr as well as log entries. - UseStdout, UseStderr bool - OutStream io.Writer - Stop <-chan bool -} - // ContainerLogs hooks up a container's stdout and stderr streams // configured with the given struct. -func (daemon *Daemon) ContainerLogs(containerName string, config *ContainerLogsConfig) error { +func (daemon *Daemon) ContainerLogs(containerName string, config *backend.ContainerLogsConfig) error { container, err := daemon.GetContainer(containerName) if err != nil { return derr.ErrorCodeNoSuchContainer.WithArgs(containerName) diff --git a/daemon/network.go b/daemon/network.go index f6a2515202..07d0771f7c 100644 --- a/daemon/network.go +++ b/daemon/network.go @@ -1,7 +1,6 @@ package daemon import ( - "errors" "fmt" "net" "strings" @@ -12,13 +11,6 @@ import ( "github.com/docker/libnetwork" ) -const ( - // NetworkByID represents a constant to find a network by its ID - NetworkByID = iota + 1 - // NetworkByName represents a constant to find a network by its Name - NetworkByName -) - // NetworkControllerEnabled checks if the networking stack is enabled. // This feature depends on OS primitives and it's disabled in systems like Windows. func (daemon *Daemon) NetworkControllerEnabled() bool { @@ -28,8 +20,8 @@ func (daemon *Daemon) NetworkControllerEnabled() bool { // FindNetwork function finds a network for a given string that can represent network name or id func (daemon *Daemon) FindNetwork(idName string) (libnetwork.Network, error) { // Find by Name - n, err := daemon.GetNetwork(idName, NetworkByName) - if _, ok := err.(libnetwork.ErrNoSuchNetwork); err != nil && !ok { + n, err := daemon.GetNetworkByName(idName) + if err != nil && !isNoSuchNetworkError(err) { return nil, err } @@ -38,38 +30,35 @@ func (daemon *Daemon) FindNetwork(idName string) (libnetwork.Network, error) { } // Find by id - n, err = daemon.GetNetwork(idName, NetworkByID) - if err != nil { - return nil, err - } - - return n, nil + return daemon.GetNetworkByID(idName) } -// GetNetwork function returns a network for a given string that represents the network and -// a hint to indicate if the string is an Id or Name of the network -func (daemon *Daemon) GetNetwork(idName string, by int) (libnetwork.Network, error) { - c := daemon.netController - switch by { - case NetworkByID: - list := daemon.GetNetworksByID(idName) +func isNoSuchNetworkError(err error) bool { + _, ok := err.(libnetwork.ErrNoSuchNetwork) + return ok +} - if len(list) == 0 { - return nil, libnetwork.ErrNoSuchNetwork(idName) - } +// GetNetworkByID function returns a network whose ID begins with the given prefix. +// It fails with an error if no matching, or more than one matching, networks are found. +func (daemon *Daemon) GetNetworkByID(partialID string) (libnetwork.Network, error) { + list := daemon.GetNetworksByID(partialID) - if len(list) > 1 { - return nil, libnetwork.ErrInvalidID(idName) - } - - return list[0], nil - case NetworkByName: - if idName == "" { - idName = c.Config().Daemon.DefaultNetwork - } - return c.NetworkByName(idName) + if len(list) == 0 { + return nil, libnetwork.ErrNoSuchNetwork(partialID) } - return nil, errors.New("unexpected selector for GetNetwork") + if len(list) > 1 { + return nil, libnetwork.ErrInvalidID(partialID) + } + return list[0], nil +} + +// GetNetworkByName function returns a network for a given network name. +func (daemon *Daemon) GetNetworkByName(name string) (libnetwork.Network, error) { + c := daemon.netController + if name == "" { + name = c.Config().Daemon.DefaultNetwork + } + return c.NetworkByName(name) } // GetNetworksByID returns a list of networks whose ID partially matches zero or more networks diff --git a/daemon/stats.go b/daemon/stats.go index a3155165e9..a1e41283d8 100644 --- a/daemon/stats.go +++ b/daemon/stats.go @@ -3,30 +3,23 @@ package daemon import ( "encoding/json" "errors" - "io" "runtime" "github.com/docker/docker/daemon/execdriver" "github.com/docker/docker/pkg/version" "github.com/docker/engine-api/types" + "github.com/docker/engine-api/types/backend" "github.com/docker/engine-api/types/versions/v1p20" ) -// ContainerStatsConfig holds information for configuring the runtime -// behavior of a daemon.ContainerStats() call. -type ContainerStatsConfig struct { - Stream bool - OutStream io.Writer - Stop <-chan bool - Version version.Version -} - // ContainerStats writes information about the container to the stream // given in the config object. -func (daemon *Daemon) ContainerStats(prefixOrName string, config *ContainerStatsConfig) error { +func (daemon *Daemon) ContainerStats(prefixOrName string, config *backend.ContainerStatsConfig) error { if runtime.GOOS == "windows" { return errors.New("Windows does not support stats") } + // Remote API version (used for backwards compatibility) + apiVersion := version.Version(config.Version) container, err := daemon.GetContainer(prefixOrName) if err != nil { @@ -72,7 +65,7 @@ func (daemon *Daemon) ContainerStats(prefixOrName string, config *ContainerStats var statsJSON interface{} statsJSONPost120 := getStatJSON(v) - if config.Version.LessThan("1.21") { + if apiVersion.LessThan("1.21") { var ( rxBytes uint64 rxPackets uint64 From 06d8f504f7b1883f490b5deda5a30ef9acd99f95 Mon Sep 17 00:00:00 2001 From: David Calavera Date: Wed, 27 Jan 2016 17:09:42 -0500 Subject: [PATCH 2/2] Move backend types to their own package. - Remove duplicated structs that we already have in engine-api. Signed-off-by: David Calavera --- api/server/router/container/backend.go | 4 +- .../router/container/container_routes.go | 47 ++++++++--------- api/server/router/image/backend.go | 2 +- api/server/router/image/image_routes.go | 2 +- api/types/backend/backend.go | 51 +++++++++++++++++++ daemon/attach.go | 4 +- daemon/list.go | 36 ++++++------- daemon/logs.go | 21 ++++++-- daemon/stats.go | 2 +- 9 files changed, 112 insertions(+), 57 deletions(-) create mode 100644 api/types/backend/backend.go diff --git a/api/server/router/container/backend.go b/api/server/router/container/backend.go index 145a1b7424..bbac65bdce 100644 --- a/api/server/router/container/backend.go +++ b/api/server/router/container/backend.go @@ -4,11 +4,11 @@ import ( "io" "time" + "github.com/docker/docker/api/types/backend" "github.com/docker/docker/daemon/exec" "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/version" "github.com/docker/engine-api/types" - "github.com/docker/engine-api/types/backend" "github.com/docker/engine-api/types/container" ) @@ -55,7 +55,7 @@ type monitorBackend interface { ContainerStats(name string, config *backend.ContainerStatsConfig) error ContainerTop(name string, psArgs string) (*types.ContainerProcessList, error) - Containers(config *backend.ContainersConfig) ([]*types.Container, error) + Containers(config *types.ContainerListOptions) ([]*types.Container, error) } // attachBackend includes function to implement to provide container attaching functionality. diff --git a/api/server/router/container/container_routes.go b/api/server/router/container/container_routes.go index cd429e1d72..4e485a8c63 100644 --- a/api/server/router/container/container_routes.go +++ b/api/server/router/container/container_routes.go @@ -13,6 +13,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/distribution/registry/api/errcode" "github.com/docker/docker/api/server/httputils" + "github.com/docker/docker/api/types/backend" derr "github.com/docker/docker/errors" "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/signal" @@ -20,9 +21,8 @@ import ( "github.com/docker/docker/runconfig" "github.com/docker/docker/utils" "github.com/docker/engine-api/types" - "github.com/docker/engine-api/types/backend" "github.com/docker/engine-api/types/container" - timetypes "github.com/docker/engine-api/types/time" + "github.com/docker/engine-api/types/filters" "golang.org/x/net/context" "golang.org/x/net/websocket" ) @@ -31,13 +31,17 @@ func (s *containerRouter) getContainersJSON(ctx context.Context, w http.Response if err := httputils.ParseForm(r); err != nil { return err } + filter, err := filters.FromParam(r.Form.Get("filters")) + if err != nil { + return err + } - config := &backend.ContainersConfig{ - All: httputils.BoolValue(r, "all"), - Size: httputils.BoolValue(r, "size"), - Since: r.Form.Get("since"), - Before: r.Form.Get("before"), - Filters: r.Form.Get("filters"), + config := &types.ContainerListOptions{ + All: httputils.BoolValue(r, "all"), + Size: httputils.BoolValue(r, "size"), + Since: r.Form.Get("since"), + Before: r.Form.Get("before"), + Filter: filter, } if tmpLimit := r.Form.Get("limit"); tmpLimit != "" { @@ -102,15 +106,6 @@ func (s *containerRouter) getContainersLogs(ctx context.Context, w http.Response return fmt.Errorf("Bad parameters: you must choose at least one stream") } - var since time.Time - if r.Form.Get("since") != "" { - s, n, err := timetypes.ParseTimestamps(r.Form.Get("since"), 0) - if err != nil { - return err - } - since = time.Unix(s, n) - } - var closeNotifier <-chan bool if notifier, ok := w.(http.CloseNotifier); ok { closeNotifier = notifier.CloseNotify() @@ -134,14 +129,16 @@ func (s *containerRouter) getContainersLogs(ctx context.Context, w http.Response defer output.Close() logsConfig := &backend.ContainerLogsConfig{ - Follow: httputils.BoolValue(r, "follow"), - Timestamps: httputils.BoolValue(r, "timestamps"), - Since: since, - Tail: r.Form.Get("tail"), - UseStdout: stdout, - UseStderr: stderr, - OutStream: output, - Stop: closeNotifier, + ContainerLogsOptions: types.ContainerLogsOptions{ + Follow: httputils.BoolValue(r, "follow"), + Timestamps: httputils.BoolValue(r, "timestamps"), + Since: r.Form.Get("since"), + Tail: r.Form.Get("tail"), + ShowStdout: stdout, + ShowStderr: stderr, + }, + OutStream: output, + Stop: closeNotifier, } if err := s.backend.ContainerLogs(containerName, logsConfig); err != nil { diff --git a/api/server/router/image/backend.go b/api/server/router/image/backend.go index e312307d93..73e8216025 100644 --- a/api/server/router/image/backend.go +++ b/api/server/router/image/backend.go @@ -32,7 +32,7 @@ type imageBackend interface { } type importExportBackend interface { - LoadImage(inTar io.ReadCloser, outStream io.Writer) error + LoadImage(inTar io.ReadCloser, outStream io.Writer, quiet bool) error ImportImage(src string, newRef reference.Named, msg string, inConfig io.ReadCloser, outStream io.Writer, config *container.Config) error ExportImage(names []string, outStream io.Writer) error } diff --git a/api/server/router/image/image_routes.go b/api/server/router/image/image_routes.go index bf95d5592f..c84317aec8 100644 --- a/api/server/router/image/image_routes.go +++ b/api/server/router/image/image_routes.go @@ -269,7 +269,7 @@ func (s *imageRouter) getImagesGet(ctx context.Context, w http.ResponseWriter, r return nil } -func (s *router) postImagesLoad(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *imageRouter) postImagesLoad(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } diff --git a/api/types/backend/backend.go b/api/types/backend/backend.go new file mode 100644 index 0000000000..517887014c --- /dev/null +++ b/api/types/backend/backend.go @@ -0,0 +1,51 @@ +// Package backend includes types to send information to server backends. +// TODO(calavera): This package is pending of extraction to engine-api +// when the server package is clean of daemon dependencies. +package backend + +import ( + "io" + "net/http" + + "github.com/docker/engine-api/types" +) + +// ContainerAttachWithLogsConfig holds the streams to use when connecting to a container to view logs. +type ContainerAttachWithLogsConfig struct { + Hijacker http.Hijacker + Upgrade bool + UseStdin bool + UseStdout bool + UseStderr bool + Logs bool + Stream bool + DetachKeys []byte +} + +// ContainerWsAttachWithLogsConfig attach with websockets, since all +// stream data is delegated to the websocket to handle there. +type ContainerWsAttachWithLogsConfig struct { + InStream io.ReadCloser // Reader to attach to stdin of container + OutStream io.Writer // Writer to attach to stdout of container + ErrStream io.Writer // Writer to attach to stderr of container + Logs bool // If true return log output + Stream bool // If true return stream output + DetachKeys []byte +} + +// ContainerLogsConfig holds configs for logging operations. Exists +// for users of the backend to to pass it a logging configuration. +type ContainerLogsConfig struct { + types.ContainerLogsOptions + OutStream io.Writer + Stop <-chan bool +} + +// ContainerStatsConfig holds information for configuring the runtime +// behavior of a backend.ContainerStats() call. +type ContainerStatsConfig struct { + Stream bool + OutStream io.Writer + Stop <-chan bool + Version string +} diff --git a/daemon/attach.go b/daemon/attach.go index aabc77082a..4faa460e37 100644 --- a/daemon/attach.go +++ b/daemon/attach.go @@ -6,11 +6,11 @@ import ( "time" "github.com/Sirupsen/logrus" + "github.com/docker/docker/api/types/backend" "github.com/docker/docker/container" "github.com/docker/docker/daemon/logger" derr "github.com/docker/docker/errors" "github.com/docker/docker/pkg/stdcopy" - "github.com/docker/engine-api/types/backend" ) // ContainerAttachWithLogs attaches to logs according to the config passed in. See ContainerAttachWithLogsConfig. @@ -81,7 +81,7 @@ func (daemon *Daemon) ContainerWsAttachWithLogs(prefixOrName string, c *backend. // ContainerAttachOnBuild attaches streams to the container cID. If stream is true, it streams the output. func (daemon *Daemon) ContainerAttachOnBuild(cID string, stdin io.ReadCloser, stdout, stderr io.Writer, stream bool) error { - return daemon.ContainerWsAttachWithLogs(cID, &ContainerWsAttachWithLogsConfig{ + return daemon.ContainerWsAttachWithLogs(cID, &backend.ContainerWsAttachWithLogsConfig{ InStream: stdin, OutStream: stdout, ErrStream: stderr, diff --git a/daemon/list.go b/daemon/list.go index 5761ca40c5..c674225324 100644 --- a/daemon/list.go +++ b/daemon/list.go @@ -10,7 +10,6 @@ import ( "github.com/docker/docker/container" "github.com/docker/docker/image" "github.com/docker/engine-api/types" - "github.com/docker/engine-api/types/backend" "github.com/docker/engine-api/types/filters" networktypes "github.com/docker/engine-api/types/network" "github.com/docker/go-connections/nat" @@ -45,7 +44,7 @@ func (daemon *Daemon) List() []*container.Container { } // listContext is the daemon generated filtering to iterate over containers. -// This is created based on the user specification from backend.ContainersConfig. +// This is created based on the user specification from types.ContainerListOptions. type listContext struct { // idx is the container iteration index for this context idx int @@ -65,17 +64,17 @@ type listContext struct { // sinceFilter is a filter to stop the filtering when the iterator arrive to the given container // this is used for --filter=since= and --since=, the latter is deprecated. sinceFilter *container.Container - // ContainersConfig is the filters set by the user - *backend.ContainersConfig + // ContainerListOptions is the filters set by the user + *types.ContainerListOptions } // Containers returns the list of containers to show given the user's filtering. -func (daemon *Daemon) Containers(config *backend.ContainersConfig) ([]*types.Container, error) { +func (daemon *Daemon) Containers(config *types.ContainerListOptions) ([]*types.Container, error) { return daemon.reduceContainers(config, daemon.transformContainer) } // reduceContainers parses the user's filtering options and generates the list of containers to return based on a reducer. -func (daemon *Daemon) reduceContainers(config *backend.ContainersConfig, reducer containerReducer) ([]*types.Container, error) { +func (daemon *Daemon) reduceContainers(config *types.ContainerListOptions, reducer containerReducer) ([]*types.Container, error) { containers := []*types.Container{} ctx, err := daemon.foldFilter(config) @@ -118,14 +117,11 @@ func (daemon *Daemon) reducePsContainer(container *container.Container, ctx *lis } // foldFilter generates the container filter based on the user's filtering options. -func (daemon *Daemon) foldFilter(config *backend.ContainersConfig) (*listContext, error) { - psFilters, err := filters.FromParam(config.Filters) - if err != nil { - return nil, err - } +func (daemon *Daemon) foldFilter(config *types.ContainerListOptions) (*listContext, error) { + psFilters := config.Filter var filtExited []int - err = psFilters.WalkValues("exited", func(value string) error { + err := psFilters.WalkValues("exited", func(value string) error { code, err := strconv.Atoi(value) if err != nil { return err @@ -201,14 +197,14 @@ func (daemon *Daemon) foldFilter(config *backend.ContainersConfig) (*listContext } return &listContext{ - filters: psFilters, - ancestorFilter: ancestorFilter, - images: imagesFilter, - exitAllowed: filtExited, - beforeFilter: beforeContFilter, - sinceFilter: sinceContFilter, - ContainersConfig: config, - names: daemon.nameIndex.GetAll(), + filters: psFilters, + ancestorFilter: ancestorFilter, + images: imagesFilter, + exitAllowed: filtExited, + beforeFilter: beforeContFilter, + sinceFilter: sinceContFilter, + ContainerListOptions: config, + names: daemon.nameIndex.GetAll(), }, nil } diff --git a/daemon/logs.go b/daemon/logs.go index bb6586f272..23f9e321d2 100644 --- a/daemon/logs.go +++ b/daemon/logs.go @@ -3,14 +3,16 @@ package daemon import ( "io" "strconv" + "time" "github.com/Sirupsen/logrus" + "github.com/docker/docker/api/types/backend" "github.com/docker/docker/container" "github.com/docker/docker/daemon/logger" "github.com/docker/docker/daemon/logger/jsonfilelog" derr "github.com/docker/docker/errors" "github.com/docker/docker/pkg/stdcopy" - "github.com/docker/engine-api/types/backend" + timetypes "github.com/docker/engine-api/types/time" ) // ContainerLogs hooks up a container's stdout and stderr streams @@ -21,7 +23,7 @@ func (daemon *Daemon) ContainerLogs(containerName string, config *backend.Contai return derr.ErrorCodeNoSuchContainer.WithArgs(containerName) } - if !(config.UseStdout || config.UseStderr) { + if !(config.ShowStdout || config.ShowStderr) { return derr.ErrorCodeNeedStream } @@ -49,8 +51,17 @@ func (daemon *Daemon) ContainerLogs(containerName string, config *backend.Contai } logrus.Debug("logs: begin stream") + + var since time.Time + if config.Since != "" { + s, n, err := timetypes.ParseTimestamps(config.Since, 0) + if err != nil { + return err + } + since = time.Unix(s, n) + } readConfig := logger.ReadConfig{ - Since: config.Since, + Since: since, Tail: tailLines, Follow: follow, } @@ -73,10 +84,10 @@ func (daemon *Daemon) ContainerLogs(containerName string, config *backend.Contai if config.Timestamps { logLine = append([]byte(msg.Timestamp.Format(logger.TimeFormat)+" "), logLine...) } - if msg.Source == "stdout" && config.UseStdout { + if msg.Source == "stdout" && config.ShowStdout { outStream.Write(logLine) } - if msg.Source == "stderr" && config.UseStderr { + if msg.Source == "stderr" && config.ShowStderr { errStream.Write(logLine) } } diff --git a/daemon/stats.go b/daemon/stats.go index a1e41283d8..65933a4f00 100644 --- a/daemon/stats.go +++ b/daemon/stats.go @@ -5,10 +5,10 @@ import ( "errors" "runtime" + "github.com/docker/docker/api/types/backend" "github.com/docker/docker/daemon/execdriver" "github.com/docker/docker/pkg/version" "github.com/docker/engine-api/types" - "github.com/docker/engine-api/types/backend" "github.com/docker/engine-api/types/versions/v1p20" )