Add container package for container APIs.

Signed-off-by: Dong Chen <dongluo.chen@docker.com>
This commit is contained in:
Dong Chen 2015-11-04 17:38:05 -08:00 committed by David Calavera
parent a5bf10f37e
commit fa8d96ebe2
9 changed files with 245 additions and 97 deletions

View file

@ -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
}

View file

@ -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
}

View file

@ -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),
}
}

View file

@ -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)
}
})

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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 {

View file

@ -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),
}
}

View file

@ -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()