From fa8d96ebe21f5bb83e4d2da8e59234e701a8ee70 Mon Sep 17 00:00:00 2001 From: Dong Chen Date: Wed, 4 Nov 2015 17:38:05 -0800 Subject: [PATCH] Add container package for container APIs. Signed-off-by: Dong Chen --- api/server/router/container/backend_unix.go | 56 ++++++++++++ .../router/container/backend_windows.go | 55 ++++++++++++ api/server/router/container/container.go | 65 ++++++++++++++ .../router/container/container_routes.go | 86 +++++++++---------- api/server/router/container/copy.go | 18 ++-- api/server/router/container/exec.go | 20 ++--- api/server/router/container/inspect.go | 10 +-- api/server/router/local/local.go | 30 ------- api/server/server.go | 2 + 9 files changed, 245 insertions(+), 97 deletions(-) create mode 100644 api/server/router/container/backend_unix.go create mode 100644 api/server/router/container/backend_windows.go create mode 100644 api/server/router/container/container.go diff --git a/api/server/router/container/backend_unix.go b/api/server/router/container/backend_unix.go new file mode 100644 index 0000000000..f973f4f22c --- /dev/null +++ b/api/server/router/container/backend_unix.go @@ -0,0 +1,56 @@ +// +build !windows + +package container + +import ( + "io" + "time" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/versions/v1p19" + "github.com/docker/docker/api/types/versions/v1p20" + "github.com/docker/docker/daemon" + "github.com/docker/docker/pkg/archive" + "github.com/docker/docker/runconfig" +) + +// Backend is all the methods that need to be implemented to provide +// container specific functionality +type Backend interface { + ContainerArchivePath(name string, path string) (content io.ReadCloser, stat *types.ContainerPathStat, err error) + ContainerAttachWithLogs(prefixOrName string, c *daemon.ContainerAttachWithLogsConfig) error + ContainerChanges(name string) ([]archive.Change, error) + ContainerCopy(name string, res string) (io.ReadCloser, error) + ContainerCreate(params *daemon.ContainerCreateConfig) (types.ContainerCreateResponse, error) + ContainerExecCreate(config *runconfig.ExecConfig) (string, error) + ContainerExecInspect(id string) (*daemon.ExecConfig, error) + ContainerExecResize(name string, height, width int) error + ContainerExecStart(name string, stdin io.ReadCloser, stdout io.Writer, stderr io.Writer) error + ContainerExport(name string, out io.Writer) error + ContainerExtractToDir(name, path string, noOverwriteDirNonDir bool, content io.Reader) error + ContainerInspect(name string, size bool) (*types.ContainerJSON, error) + ContainerInspect120(name string) (*v1p20.ContainerJSON, error) + // unix version + ContainerInspectPre120(name string) (*v1p19.ContainerJSON, error) + // windows version + //ContainerInspectPre120(name string) (*types.ContainerJSON, error) + ContainerKill(name string, sig uint64) error + ContainerLogs(containerName string, config *daemon.ContainerLogsConfig) error + ContainerPause(name string) error + ContainerRename(oldName, newName string) error + ContainerResize(name string, height, width int) error + ContainerRestart(name string, seconds int) error + ContainerRm(name string, config *daemon.ContainerRmConfig) error + Containers(config *daemon.ContainersConfig) ([]*types.Container, error) + ContainerStart(name string, hostConfig *runconfig.HostConfig) error + ContainerStatPath(name string, path string) (stat *types.ContainerPathStat, err error) + ContainerStats(prefixOrName string, config *daemon.ContainerStatsConfig) error + ContainerStop(name string, seconds int) error + ContainerTop(name string, psArgs string) (*types.ContainerProcessList, error) + ContainerUnpause(name string) error + ContainerWait(name string, timeout time.Duration) (int, error) + ContainerWsAttachWithLogs(prefixOrName string, c *daemon.ContainerWsAttachWithLogsConfig) error + ExecExists(name string) (bool, error) + Exists(id string) bool + IsPaused(id string) bool +} diff --git a/api/server/router/container/backend_windows.go b/api/server/router/container/backend_windows.go new file mode 100644 index 0000000000..7caa16b8e5 --- /dev/null +++ b/api/server/router/container/backend_windows.go @@ -0,0 +1,55 @@ +// +build windows + +package container + +import ( + "io" + "time" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/versions/v1p20" + "github.com/docker/docker/daemon" + "github.com/docker/docker/pkg/archive" + "github.com/docker/docker/runconfig" +) + +// Backend is all the methods that need to be implemented to provide +// container specific functionality +type Backend interface { + ContainerArchivePath(name string, path string) (content io.ReadCloser, stat *types.ContainerPathStat, err error) + ContainerAttachWithLogs(prefixOrName string, c *daemon.ContainerAttachWithLogsConfig) error + ContainerChanges(name string) ([]archive.Change, error) + ContainerCopy(name string, res string) (io.ReadCloser, error) + ContainerCreate(params *daemon.ContainerCreateConfig) (types.ContainerCreateResponse, error) + ContainerExecCreate(config *runconfig.ExecConfig) (string, error) + ContainerExecInspect(id string) (*daemon.ExecConfig, error) + ContainerExecResize(name string, height, width int) error + ContainerExecStart(name string, stdin io.ReadCloser, stdout io.Writer, stderr io.Writer) error + ContainerExport(name string, out io.Writer) error + ContainerExtractToDir(name, path string, noOverwriteDirNonDir bool, content io.Reader) error + ContainerInspect(name string, size bool) (*types.ContainerJSON, error) + ContainerInspect120(name string) (*v1p20.ContainerJSON, error) + // unix version + //ContainerInspectPre120(name string) (*v1p19.ContainerJSON, error) + // windows version + ContainerInspectPre120(name string) (*types.ContainerJSON, error) + ContainerKill(name string, sig uint64) error + ContainerLogs(containerName string, config *daemon.ContainerLogsConfig) error + ContainerPause(name string) error + ContainerRename(oldName, newName string) error + ContainerResize(name string, height, width int) error + ContainerRestart(name string, seconds int) error + ContainerRm(name string, config *daemon.ContainerRmConfig) error + Containers(config *daemon.ContainersConfig) ([]*types.Container, error) + ContainerStart(name string, hostConfig *runconfig.HostConfig) error + ContainerStatPath(name string, path string) (stat *types.ContainerPathStat, err error) + ContainerStats(prefixOrName string, config *daemon.ContainerStatsConfig) error + ContainerStop(name string, seconds int) error + ContainerTop(name string, psArgs string) (*types.ContainerProcessList, error) + ContainerUnpause(name string) error + ContainerWait(name string, timeout time.Duration) (int, error) + ContainerWsAttachWithLogs(prefixOrName string, c *daemon.ContainerWsAttachWithLogsConfig) error + ExecExists(name string) (bool, error) + Exists(id string) bool + IsPaused(id string) bool +} diff --git a/api/server/router/container/container.go b/api/server/router/container/container.go new file mode 100644 index 0000000000..aed0c0b435 --- /dev/null +++ b/api/server/router/container/container.go @@ -0,0 +1,65 @@ +package container + +import ( + "github.com/docker/docker/api/server/router" + "github.com/docker/docker/api/server/router/local" +) + +// containerRouter is a router to talk with the container controller +type containerRouter struct { + backend Backend + routes []router.Route +} + +// NewRouter initializes a new container router +func NewRouter(b Backend) router.Router { + r := &containerRouter{ + backend: b, + } + r.initRoutes() + return r +} + +// Routes returns the available routers to the container controller +func (r *containerRouter) Routes() []router.Route { + return r.routes +} + +// initRoutes initializes the routes in container router +func (r *containerRouter) initRoutes() { + r.routes = []router.Route{ + // HEAD + local.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), + // 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), + // PUT + local.NewPutRoute("/containers/{name:.*}/archive", r.putContainersArchive), + // DELETE + local.NewDeleteRoute("/containers/{name:.*}", r.deleteContainers), + } +} diff --git a/api/server/router/container/container_routes.go b/api/server/router/container/container_routes.go index 1c6a5fce91..a766535b1a 100644 --- a/api/server/router/container/container_routes.go +++ b/api/server/router/container/container_routes.go @@ -1,4 +1,4 @@ -package local +package container import ( "fmt" @@ -24,7 +24,7 @@ import ( "golang.org/x/net/websocket" ) -func (s *router) getContainersJSON(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) getContainersJSON(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } @@ -45,7 +45,7 @@ func (s *router) getContainersJSON(ctx context.Context, w http.ResponseWriter, r config.Limit = limit } - containers, err := s.daemon.Containers(config) + containers, err := s.backend.Containers(config) if err != nil { return err } @@ -53,7 +53,7 @@ func (s *router) getContainersJSON(ctx context.Context, w http.ResponseWriter, r return httputils.WriteJSON(w, http.StatusOK, containers) } -func (s *router) getContainersStats(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) getContainersStats(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } @@ -81,10 +81,10 @@ func (s *router) getContainersStats(ctx context.Context, w http.ResponseWriter, Version: httputils.VersionFromContext(ctx), } - return s.daemon.ContainerStats(vars["name"], config) + return s.backend.ContainerStats(vars["name"], config) } -func (s *router) getContainersLogs(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) getContainersLogs(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } @@ -115,7 +115,7 @@ func (s *router) getContainersLogs(ctx context.Context, w http.ResponseWriter, r containerName := vars["name"] - if !s.daemon.Exists(containerName) { + if !s.backend.Exists(containerName) { return derr.ErrorCodeNoSuchContainer.WithArgs(containerName) } @@ -141,7 +141,7 @@ func (s *router) getContainersLogs(ctx context.Context, w http.ResponseWriter, r Stop: closeNotifier, } - if err := s.daemon.ContainerLogs(containerName, logsConfig); err != nil { + if err := s.backend.ContainerLogs(containerName, logsConfig); err != nil { // The client may be expecting all of the data we're sending to // be multiplexed, so send it through OutStream, which will // have been set up to handle that if needed. @@ -151,11 +151,11 @@ func (s *router) getContainersLogs(ctx context.Context, w http.ResponseWriter, r return nil } -func (s *router) getContainersExport(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - return s.daemon.ContainerExport(vars["name"], w) +func (s *containerRouter) getContainersExport(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { + return s.backend.ContainerExport(vars["name"], w) } -func (s *router) postContainersStart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) postContainersStart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { // If contentLength is -1, we can assumed chunked encoding // or more technically that the length is unknown // https://golang.org/src/pkg/net/http/request.go#L139 @@ -176,21 +176,21 @@ func (s *router) postContainersStart(ctx context.Context, w http.ResponseWriter, hostConfig = c } - if err := s.daemon.ContainerStart(vars["name"], hostConfig); err != nil { + if err := s.backend.ContainerStart(vars["name"], hostConfig); err != nil { return err } w.WriteHeader(http.StatusNoContent) return nil } -func (s *router) postContainersStop(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) postContainersStop(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } seconds, _ := strconv.Atoi(r.Form.Get("t")) - if err := s.daemon.ContainerStop(vars["name"], seconds); err != nil { + if err := s.backend.ContainerStop(vars["name"], seconds); err != nil { return err } w.WriteHeader(http.StatusNoContent) @@ -198,7 +198,7 @@ func (s *router) postContainersStop(ctx context.Context, w http.ResponseWriter, return nil } -func (s *router) postContainersKill(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) postContainersKill(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } @@ -214,7 +214,7 @@ func (s *router) postContainersKill(ctx context.Context, w http.ResponseWriter, } } - if err := s.daemon.ContainerKill(name, uint64(sig)); err != nil { + if err := s.backend.ContainerKill(name, uint64(sig)); err != nil { theErr, isDerr := err.(errcode.ErrorCoder) isStopped := isDerr && theErr.ErrorCode() == derr.ErrorCodeNotRunning @@ -231,14 +231,14 @@ func (s *router) postContainersKill(ctx context.Context, w http.ResponseWriter, return nil } -func (s *router) postContainersRestart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) postContainersRestart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } timeout, _ := strconv.Atoi(r.Form.Get("t")) - if err := s.daemon.ContainerRestart(vars["name"], timeout); err != nil { + if err := s.backend.ContainerRestart(vars["name"], timeout); err != nil { return err } @@ -247,12 +247,12 @@ func (s *router) postContainersRestart(ctx context.Context, w http.ResponseWrite return nil } -func (s *router) postContainersPause(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) postContainersPause(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } - if err := s.daemon.ContainerPause(vars["name"]); err != nil { + if err := s.backend.ContainerPause(vars["name"]); err != nil { return err } @@ -261,12 +261,12 @@ func (s *router) postContainersPause(ctx context.Context, w http.ResponseWriter, return nil } -func (s *router) postContainersUnpause(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) postContainersUnpause(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } - if err := s.daemon.ContainerUnpause(vars["name"]); err != nil { + if err := s.backend.ContainerUnpause(vars["name"]); err != nil { return err } @@ -275,8 +275,8 @@ func (s *router) postContainersUnpause(ctx context.Context, w http.ResponseWrite return nil } -func (s *router) postContainersWait(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - status, err := s.daemon.ContainerWait(vars["name"], -1*time.Second) +func (s *containerRouter) postContainersWait(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { + status, err := s.backend.ContainerWait(vars["name"], -1*time.Second) if err != nil { return err } @@ -286,8 +286,8 @@ func (s *router) postContainersWait(ctx context.Context, w http.ResponseWriter, }) } -func (s *router) getContainersChanges(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - changes, err := s.daemon.ContainerChanges(vars["name"]) +func (s *containerRouter) getContainersChanges(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { + changes, err := s.backend.ContainerChanges(vars["name"]) if err != nil { return err } @@ -295,12 +295,12 @@ func (s *router) getContainersChanges(ctx context.Context, w http.ResponseWriter return httputils.WriteJSON(w, http.StatusOK, changes) } -func (s *router) getContainersTop(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) getContainersTop(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } - procList, err := s.daemon.ContainerTop(vars["name"], r.Form.Get("ps_args")) + procList, err := s.backend.ContainerTop(vars["name"], r.Form.Get("ps_args")) if err != nil { return err } @@ -308,21 +308,21 @@ func (s *router) getContainersTop(ctx context.Context, w http.ResponseWriter, r return httputils.WriteJSON(w, http.StatusOK, procList) } -func (s *router) postContainerRename(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) postContainerRename(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } name := vars["name"] newName := r.Form.Get("name") - if err := s.daemon.ContainerRename(name, newName); err != nil { + if err := s.backend.ContainerRename(name, newName); err != nil { return err } w.WriteHeader(http.StatusNoContent) return nil } -func (s *router) postContainersCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) postContainersCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } @@ -339,7 +339,7 @@ func (s *router) postContainersCreate(ctx context.Context, w http.ResponseWriter version := httputils.VersionFromContext(ctx) adjustCPUShares := version.LessThan("1.19") - ccr, err := s.daemon.ContainerCreate(&daemon.ContainerCreateConfig{ + ccr, err := s.backend.ContainerCreate(&daemon.ContainerCreateConfig{ Name: name, Config: config, HostConfig: hostConfig, @@ -352,7 +352,7 @@ func (s *router) postContainersCreate(ctx context.Context, w http.ResponseWriter return httputils.WriteJSON(w, http.StatusCreated, ccr) } -func (s *router) deleteContainers(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) deleteContainers(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } @@ -364,7 +364,7 @@ func (s *router) deleteContainers(ctx context.Context, w http.ResponseWriter, r RemoveLink: httputils.BoolValue(r, "link"), } - if err := s.daemon.ContainerRm(name, config); err != nil { + if err := s.backend.ContainerRm(name, config); err != nil { // Force a 404 for the empty string if strings.Contains(strings.ToLower(err.Error()), "prefix can't be empty") { return fmt.Errorf("no such id: \"\"") @@ -377,7 +377,7 @@ func (s *router) deleteContainers(ctx context.Context, w http.ResponseWriter, r return nil } -func (s *router) postContainersResize(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) postContainersResize(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } @@ -391,20 +391,20 @@ func (s *router) postContainersResize(ctx context.Context, w http.ResponseWriter return err } - return s.daemon.ContainerResize(vars["name"], height, width) + return s.backend.ContainerResize(vars["name"], height, width) } -func (s *router) postContainersAttach(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) postContainersAttach(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } containerName := vars["name"] - if !s.daemon.Exists(containerName) { + if !s.backend.Exists(containerName) { return derr.ErrorCodeNoSuchContainer.WithArgs(containerName) } - if s.daemon.IsPaused(containerName) { + if s.backend.IsPaused(containerName) { return derr.ErrorCodePausedContainer.WithArgs(containerName) } @@ -430,20 +430,20 @@ func (s *router) postContainersAttach(ctx context.Context, w http.ResponseWriter Stream: httputils.BoolValue(r, "stream"), } - if err := s.daemon.ContainerAttachWithLogs(containerName, attachWithLogsConfig); err != nil { + if err := s.backend.ContainerAttachWithLogs(containerName, attachWithLogsConfig); err != nil { fmt.Fprintf(outStream, "Error attaching: %s\n", err) } return nil } -func (s *router) wsContainersAttach(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) wsContainersAttach(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } containerName := vars["name"] - if !s.daemon.Exists(containerName) { + if !s.backend.Exists(containerName) { return derr.ErrorCodeNoSuchContainer.WithArgs(containerName) } @@ -458,7 +458,7 @@ func (s *router) wsContainersAttach(ctx context.Context, w http.ResponseWriter, Stream: httputils.BoolValue(r, "stream"), } - if err := s.daemon.ContainerWsAttachWithLogs(containerName, wsAttachWithLogsConfig); err != nil { + if err := s.backend.ContainerWsAttachWithLogs(containerName, wsAttachWithLogsConfig); err != nil { logrus.Errorf("Error attaching websocket: %s", err) } }) diff --git a/api/server/router/container/copy.go b/api/server/router/container/copy.go index ff749a02eb..12a4a3c493 100644 --- a/api/server/router/container/copy.go +++ b/api/server/router/container/copy.go @@ -1,4 +1,4 @@ -package local +package container import ( "encoding/base64" @@ -15,7 +15,7 @@ import ( ) // postContainersCopy is deprecated in favor of getContainersArchive. -func (s *router) postContainersCopy(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) postContainersCopy(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.CheckForJSON(r); err != nil { return err } @@ -29,7 +29,7 @@ func (s *router) postContainersCopy(ctx context.Context, w http.ResponseWriter, return fmt.Errorf("Path cannot be empty") } - data, err := s.daemon.ContainerCopy(vars["name"], cfg.Resource) + data, err := s.backend.ContainerCopy(vars["name"], cfg.Resource) if err != nil { if strings.Contains(strings.ToLower(err.Error()), "no such id") { w.WriteHeader(http.StatusNotFound) @@ -65,13 +65,13 @@ func setContainerPathStatHeader(stat *types.ContainerPathStat, header http.Heade return nil } -func (s *router) headContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) headContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { v, err := httputils.ArchiveFormValues(r, vars) if err != nil { return err } - stat, err := s.daemon.ContainerStatPath(v.Name, v.Path) + stat, err := s.backend.ContainerStatPath(v.Name, v.Path) if err != nil { return err } @@ -79,13 +79,13 @@ func (s *router) headContainersArchive(ctx context.Context, w http.ResponseWrite return setContainerPathStatHeader(stat, w.Header()) } -func (s *router) getContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) getContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { v, err := httputils.ArchiveFormValues(r, vars) if err != nil { return err } - tarArchive, stat, err := s.daemon.ContainerArchivePath(v.Name, v.Path) + tarArchive, stat, err := s.backend.ContainerArchivePath(v.Name, v.Path) if err != nil { return err } @@ -101,12 +101,12 @@ func (s *router) getContainersArchive(ctx context.Context, w http.ResponseWriter return err } -func (s *router) putContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) putContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { v, err := httputils.ArchiveFormValues(r, vars) if err != nil { return err } noOverwriteDirNonDir := httputils.BoolValue(r, "noOverwriteDirNonDir") - return s.daemon.ContainerExtractToDir(v.Name, v.Path, noOverwriteDirNonDir, r.Body) + return s.backend.ContainerExtractToDir(v.Name, v.Path, noOverwriteDirNonDir, r.Body) } diff --git a/api/server/router/container/exec.go b/api/server/router/container/exec.go index 14095d8e70..a4b1f700fa 100644 --- a/api/server/router/container/exec.go +++ b/api/server/router/container/exec.go @@ -1,4 +1,4 @@ -package local +package container import ( "encoding/json" @@ -15,8 +15,8 @@ import ( "golang.org/x/net/context" ) -func (s *router) getExecByID(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - eConfig, err := s.daemon.ContainerExecInspect(vars["id"]) +func (s *containerRouter) getExecByID(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { + eConfig, err := s.backend.ContainerExecInspect(vars["id"]) if err != nil { return err } @@ -24,7 +24,7 @@ func (s *router) getExecByID(ctx context.Context, w http.ResponseWriter, r *http return httputils.WriteJSON(w, http.StatusOK, eConfig) } -func (s *router) postContainerExecCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) postContainerExecCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } @@ -44,7 +44,7 @@ func (s *router) postContainerExecCreate(ctx context.Context, w http.ResponseWri } // Register an instance of Exec in container. - id, err := s.daemon.ContainerExecCreate(execConfig) + id, err := s.backend.ContainerExecCreate(execConfig) if err != nil { logrus.Errorf("Error setting up exec command in container %s: %s", name, err) return err @@ -56,7 +56,7 @@ func (s *router) postContainerExecCreate(ctx context.Context, w http.ResponseWri } // TODO(vishh): Refactor the code to avoid having to specify stream config as part of both create and start. -func (s *router) postContainerExecStart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) postContainerExecStart(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) postContainerExecStart(ctx context.Context, w http.ResponseWrit return err } - if exists, err := s.daemon.ExecExists(execName); !exists { + if exists, err := s.backend.ExecExists(execName); !exists { return err } @@ -109,7 +109,7 @@ func (s *router) postContainerExecStart(ctx context.Context, w http.ResponseWrit } // Now run the user process in container. - if err := s.daemon.ContainerExecStart(execName, stdin, stdout, stderr); err != nil { + if err := s.backend.ContainerExecStart(execName, stdin, stdout, stderr); err != nil { if execStartCheck.Detach { return err } @@ -118,7 +118,7 @@ func (s *router) postContainerExecStart(ctx context.Context, w http.ResponseWrit return nil } -func (s *router) postContainerExecResize(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) postContainerExecResize(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := httputils.ParseForm(r); err != nil { return err } @@ -131,5 +131,5 @@ func (s *router) postContainerExecResize(ctx context.Context, w http.ResponseWri return err } - return s.daemon.ContainerExecResize(vars["name"], height, width) + return s.backend.ContainerExecResize(vars["name"], height, width) } diff --git a/api/server/router/container/inspect.go b/api/server/router/container/inspect.go index 8b2a058e1a..51cf1c3460 100644 --- a/api/server/router/container/inspect.go +++ b/api/server/router/container/inspect.go @@ -1,4 +1,4 @@ -package local +package container import ( "net/http" @@ -8,7 +8,7 @@ import ( ) // getContainersByName inspects containers configuration and serializes it as json. -func (s *router) getContainersByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func (s *containerRouter) getContainersByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { displaySize := httputils.BoolValue(r, "size") var json interface{} @@ -18,11 +18,11 @@ func (s *router) getContainersByName(ctx context.Context, w http.ResponseWriter, switch { case version.LessThan("1.20"): - json, err = s.daemon.ContainerInspectPre120(vars["name"]) + json, err = s.backend.ContainerInspectPre120(vars["name"]) case version.Equal("1.20"): - json, err = s.daemon.ContainerInspect120(vars["name"]) + json, err = s.backend.ContainerInspect120(vars["name"]) default: - json, err = s.daemon.ContainerInspect(vars["name"], displaySize) + json, err = s.backend.ContainerInspect(vars["name"], displaySize) } if err != nil { diff --git a/api/server/router/local/local.go b/api/server/router/local/local.go index b27031bd24..b84e410c23 100644 --- a/api/server/router/local/local.go +++ b/api/server/router/local/local.go @@ -91,8 +91,6 @@ func (r *router) Routes() []dkrouter.Route { // initRoutes initializes the routes in this router func (r *router) initRoutes() { r.routes = []dkrouter.Route{ - // HEAD - NewHeadRoute("/containers/{name:.*}/archive", r.headContainersArchive), // OPTIONS NewOptionsRoute("/", optionsHandler), // GET @@ -106,16 +104,6 @@ func (r *router) initRoutes() { NewGetRoute("/images/{name:.*}/get", r.getImagesGet), NewGetRoute("/images/{name:.*}/history", r.getImagesHistory), NewGetRoute("/images/{name:.*}/json", r.getImagesByName), - NewGetRoute("/containers/json", r.getContainersJSON), - NewGetRoute("/containers/{name:.*}/export", r.getContainersExport), - NewGetRoute("/containers/{name:.*}/changes", r.getContainersChanges), - NewGetRoute("/containers/{name:.*}/json", r.getContainersByName), - NewGetRoute("/containers/{name:.*}/top", r.getContainersTop), - NewGetRoute("/containers/{name:.*}/logs", r.getContainersLogs), - NewGetRoute("/containers/{name:.*}/stats", r.getContainersStats), - NewGetRoute("/containers/{name:.*}/attach/ws", r.wsContainersAttach), - NewGetRoute("/exec/{id:.*}/json", r.getExecByID), - NewGetRoute("/containers/{name:.*}/archive", r.getContainersArchive), // POST NewPostRoute("/auth", r.postAuth), NewPostRoute("/commit", r.postCommit), @@ -124,25 +112,7 @@ func (r *router) initRoutes() { NewPostRoute("/images/load", r.postImagesLoad), NewPostRoute("/images/{name:.*}/push", r.postImagesPush), NewPostRoute("/images/{name:.*}/tag", r.postImagesTag), - NewPostRoute("/containers/create", r.postContainersCreate), - NewPostRoute("/containers/{name:.*}/kill", r.postContainersKill), - NewPostRoute("/containers/{name:.*}/pause", r.postContainersPause), - NewPostRoute("/containers/{name:.*}/unpause", r.postContainersUnpause), - NewPostRoute("/containers/{name:.*}/restart", r.postContainersRestart), - NewPostRoute("/containers/{name:.*}/start", r.postContainersStart), - NewPostRoute("/containers/{name:.*}/stop", r.postContainersStop), - NewPostRoute("/containers/{name:.*}/wait", r.postContainersWait), - NewPostRoute("/containers/{name:.*}/resize", r.postContainersResize), - NewPostRoute("/containers/{name:.*}/attach", r.postContainersAttach), - NewPostRoute("/containers/{name:.*}/copy", r.postContainersCopy), - NewPostRoute("/containers/{name:.*}/exec", r.postContainerExecCreate), - NewPostRoute("/exec/{name:.*}/start", r.postContainerExecStart), - NewPostRoute("/exec/{name:.*}/resize", r.postContainerExecResize), - NewPostRoute("/containers/{name:.*}/rename", r.postContainerRename), - // PUT - NewPutRoute("/containers/{name:.*}/archive", r.putContainersArchive), // DELETE - NewDeleteRoute("/containers/{name:.*}", r.deleteContainers), NewDeleteRoute("/images/{name:.*}", r.deleteImages), } } diff --git a/api/server/server.go b/api/server/server.go index b90d704c36..5100d5e35c 100644 --- a/api/server/server.go +++ b/api/server/server.go @@ -10,6 +10,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/docker/api/server/httputils" "github.com/docker/docker/api/server/router" + "github.com/docker/docker/api/server/router/container" "github.com/docker/docker/api/server/router/local" "github.com/docker/docker/api/server/router/network" "github.com/docker/docker/api/server/router/volume" @@ -172,6 +173,7 @@ func (s *Server) InitRouters(d *daemon.Daemon) { s.addRouter(local.NewRouter(d)) s.addRouter(network.NewRouter(d)) s.addRouter(volume.NewRouter(d)) + s.addRouter(container.NewRouter(d)) for _, srv := range s.servers { srv.srv.Handler = s.CreateMux()