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..bbac65bdce 100644 --- a/api/server/router/container/backend.go +++ b/api/server/router/container/backend.go @@ -4,7 +4,7 @@ import ( "io" "time" - "github.com/docker/docker/daemon" + "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" @@ -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 *types.ContainerListOptions) ([]*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..4e485a8c63 100644 --- a/api/server/router/container/container_routes.go +++ b/api/server/router/container/container_routes.go @@ -13,7 +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/daemon" + "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" @@ -22,7 +22,7 @@ import ( "github.com/docker/docker/utils" "github.com/docker/engine-api/types" "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 := &daemon.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 != "" { @@ -77,11 +81,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) @@ -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() @@ -133,15 +128,17 @@ func (s *containerRouter) getContainersLogs(ctx context.Context, w http.Response output := ioutils.NewWriteFlusher(w) defer output.Close() - logsConfig := &daemon.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, + logsConfig := &backend.ContainerLogsConfig{ + 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 { @@ -446,7 +443,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 +480,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..73e8216025 --- /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, 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 +} + +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 87% rename from api/server/router/local/image.go rename to api/server/router/image/image_routes.go index 3427649f59..c84317aec8 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 } @@ -269,7 +269,7 @@ func (s *router) getImagesGet(ctx context.Context, w http.ResponseWriter, r *htt 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 } @@ -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/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 f0caf16996..4faa460e37 100644 --- a/daemon/attach.go +++ b/daemon/attach.go @@ -3,30 +3,18 @@ package daemon import ( "fmt" "io" - "net/http" "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" ) -// 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 @@ -102,7 +81,7 @@ func (daemon *Daemon) ContainerWsAttachWithLogs(prefixOrName string, c *Containe // 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 c363814cfb..c674225324 100644 --- a/daemon/list.go +++ b/daemon/list.go @@ -43,24 +43,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 types.ContainerListOptions. type listContext struct { // idx is the container iteration index for this context idx int @@ -80,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 - *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 *ContainersConfig) ([]*types.Container, error) { +func (daemon *Daemon) Containers(config *types.ContainerListOptions) ([]*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 *types.ContainerListOptions, reducer containerReducer) ([]*types.Container, error) { containers := []*types.Container{} ctx, err := daemon.foldFilter(config) @@ -132,15 +116,12 @@ 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) { - psFilters, err := filters.FromParam(config.Filters) - if err != nil { - return nil, err - } +// foldFilter generates the container filter based on the user's filtering options. +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 @@ -216,14 +197,14 @@ func (daemon *Daemon) foldFilter(config *ContainersConfig) (*listContext, error) } 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 b10f7df769..23f9e321d2 100644 --- a/daemon/logs.go +++ b/daemon/logs.go @@ -6,39 +6,24 @@ import ( "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" + timetypes "github.com/docker/engine-api/types/time" ) -// 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) } - if !(config.UseStdout || config.UseStderr) { + if !(config.ShowStdout || config.ShowStderr) { return derr.ErrorCodeNeedStream } @@ -66,8 +51,17 @@ func (daemon *Daemon) ContainerLogs(containerName string, config *ContainerLogsC } 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, } @@ -90,10 +84,10 @@ func (daemon *Daemon) ContainerLogs(containerName string, config *ContainerLogsC 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/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..65933a4f00 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/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/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