Move commit to container backend

Signed-off-by: Daniel Nephin <dnephin@docker.com>
This commit is contained in:
Daniel Nephin 2018-02-07 15:33:20 -05:00
parent 68c3201626
commit e574c5ae73
7 changed files with 48 additions and 56 deletions

View file

@ -68,8 +68,13 @@ type systemBackend interface {
ContainersPrune(ctx context.Context, pruneFilters filters.Args) (*types.ContainersPruneReport, error) ContainersPrune(ctx context.Context, pruneFilters filters.Args) (*types.ContainersPruneReport, error)
} }
type commitBackend interface {
CreateImageFromContainer(name string, config *backend.CreateImageConfig) (imageID string, err error)
}
// Backend is all the methods that need to be implemented to provide container specific functionality. // Backend is all the methods that need to be implemented to provide container specific functionality.
type Backend interface { type Backend interface {
commitBackend
execBackend execBackend
copyBackend copyBackend
stateBackend stateBackend

View file

@ -61,6 +61,7 @@ func (r *containerRouter) initRoutes() {
router.NewPostRoute("/containers/{name:.*}/rename", r.postContainerRename), router.NewPostRoute("/containers/{name:.*}/rename", r.postContainerRename),
router.NewPostRoute("/containers/{name:.*}/update", r.postContainerUpdate), router.NewPostRoute("/containers/{name:.*}/update", r.postContainerUpdate),
router.NewPostRoute("/containers/prune", r.postContainersPrune, router.WithCancel), router.NewPostRoute("/containers/prune", r.postContainersPrune, router.WithCancel),
router.NewPostRoute("/commit", r.postCommit),
// PUT // PUT
router.NewPutRoute("/containers/{name:.*}/archive", r.putContainersArchive), router.NewPutRoute("/containers/{name:.*}/archive", r.putContainersArchive),
// DELETE // DELETE

View file

@ -24,6 +24,45 @@ import (
"golang.org/x/net/websocket" "golang.org/x/net/websocket"
) )
func (s *containerRouter) postCommit(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 := httputils.CheckForJSON(r); err != nil {
return err
}
// TODO: remove pause arg, and always pause in backend
pause := httputils.BoolValue(r, "pause")
version := httputils.VersionFromContext(ctx)
if r.FormValue("pause") == "" && versions.GreaterThanOrEqualTo(version, "1.13") {
pause = true
}
config, _, _, err := s.decoder.DecodeConfig(r.Body)
if err != nil && err != io.EOF { //Do not fail if body is empty.
return err
}
commitCfg := &backend.CreateImageConfig{
Pause: pause,
Repo: r.Form.Get("repo"),
Tag: r.Form.Get("tag"),
Author: r.Form.Get("author"),
Comment: r.Form.Get("comment"),
Config: config,
Changes: r.Form["changes"],
}
imgID, err := s.backend.CreateImageFromContainer(r.Form.Get("container"), commitCfg)
if err != nil {
return err
}
return httputils.WriteJSON(w, http.StatusCreated, &types.IDResponse{ID: imgID})
}
func (s *containerRouter) 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 { if err := httputils.ParseForm(r); err != nil {
return err return err

View file

@ -4,7 +4,6 @@ import (
"io" "io"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/backend"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/image" "github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/registry" "github.com/docker/docker/api/types/registry"
@ -14,16 +13,11 @@ import (
// Backend is all the methods that need to be implemented // Backend is all the methods that need to be implemented
// to provide image specific functionality. // to provide image specific functionality.
type Backend interface { type Backend interface {
containerBackend
imageBackend imageBackend
importExportBackend importExportBackend
registryBackend registryBackend
} }
type containerBackend interface {
CreateImageFromContainer(name string, config *backend.CreateImageConfig) (imageID string, err error)
}
type imageBackend interface { type imageBackend interface {
ImageDelete(imageRef string, force, prune bool) ([]types.ImageDeleteResponseItem, error) ImageDelete(imageRef string, force, prune bool) ([]types.ImageDeleteResponseItem, error)
ImageHistory(imageName string) ([]*image.HistoryResponseItem, error) ImageHistory(imageName string) ([]*image.HistoryResponseItem, error)

View file

@ -1,23 +1,18 @@
package image // import "github.com/docker/docker/api/server/router/image" package image // import "github.com/docker/docker/api/server/router/image"
import ( import (
"github.com/docker/docker/api/server/httputils"
"github.com/docker/docker/api/server/router" "github.com/docker/docker/api/server/router"
) )
// imageRouter is a router to talk with the image controller // imageRouter is a router to talk with the image controller
type imageRouter struct { type imageRouter struct {
backend Backend backend Backend
decoder httputils.ContainerDecoder
routes []router.Route routes []router.Route
} }
// NewRouter initializes a new image router // NewRouter initializes a new image router
func NewRouter(backend Backend, decoder httputils.ContainerDecoder) router.Router { func NewRouter(backend Backend) router.Router {
r := &imageRouter{ r := &imageRouter{backend: backend}
backend: backend,
decoder: decoder,
}
r.initRoutes() r.initRoutes()
return r return r
} }
@ -38,7 +33,6 @@ func (r *imageRouter) initRoutes() {
router.NewGetRoute("/images/{name:.*}/history", r.getImagesHistory), router.NewGetRoute("/images/{name:.*}/history", r.getImagesHistory),
router.NewGetRoute("/images/{name:.*}/json", r.getImagesByName), router.NewGetRoute("/images/{name:.*}/json", r.getImagesByName),
// POST // POST
router.NewPostRoute("/commit", r.postCommit),
router.NewPostRoute("/images/load", r.postImagesLoad), router.NewPostRoute("/images/load", r.postImagesLoad),
router.NewPostRoute("/images/create", r.postImagesCreate, router.WithCancel), router.NewPostRoute("/images/create", r.postImagesCreate, router.WithCancel),
router.NewPostRoute("/images/{name:.*}/push", r.postImagesPush, router.WithCancel), router.NewPostRoute("/images/{name:.*}/push", r.postImagesPush, router.WithCancel),

View file

@ -4,14 +4,12 @@ import (
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
"github.com/docker/docker/api/server/httputils" "github.com/docker/docker/api/server/httputils"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/backend"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/versions" "github.com/docker/docker/api/types/versions"
"github.com/docker/docker/errdefs" "github.com/docker/docker/errdefs"
@ -24,45 +22,6 @@ import (
"golang.org/x/net/context" "golang.org/x/net/context"
) )
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
}
if err := httputils.CheckForJSON(r); err != nil {
return err
}
// TODO: remove pause arg, and always pause in backend
pause := httputils.BoolValue(r, "pause")
version := httputils.VersionFromContext(ctx)
if r.FormValue("pause") == "" && versions.GreaterThanOrEqualTo(version, "1.13") {
pause = true
}
config, _, _, err := s.decoder.DecodeConfig(r.Body)
if err != nil && err != io.EOF { //Do not fail if body is empty.
return err
}
commitCfg := &backend.CreateImageConfig{
Pause: pause,
Repo: r.Form.Get("repo"),
Tag: r.Form.Get("tag"),
Author: r.Form.Get("author"),
Comment: r.Form.Get("comment"),
Config: config,
Changes: r.Form["changes"],
}
imgID, err := s.backend.CreateImageFromContainer(r.Form.Get("container"), commitCfg)
if err != nil {
return err
}
return httputils.WriteJSON(w, http.StatusCreated, &types.IDResponse{ID: imgID})
}
// Creates an image from Pull or from Import // Creates an image from Pull or from Import
func (s *imageRouter) 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 {

View file

@ -514,7 +514,7 @@ func initRouter(opts routerOptions) {
// we need to add the checkpoint router before the container router or the DELETE gets masked // we need to add the checkpoint router before the container router or the DELETE gets masked
checkpointrouter.NewRouter(opts.daemon, decoder), checkpointrouter.NewRouter(opts.daemon, decoder),
container.NewRouter(opts.daemon, decoder), container.NewRouter(opts.daemon, decoder),
image.NewRouter(opts.daemon, decoder), image.NewRouter(opts.daemon),
systemrouter.NewRouter(opts.daemon, opts.cluster, opts.buildCache), systemrouter.NewRouter(opts.daemon, opts.cluster, opts.buildCache),
volume.NewRouter(opts.daemon), volume.NewRouter(opts.daemon),
build.NewRouter(opts.buildBackend, opts.daemon), build.NewRouter(opts.buildBackend, opts.daemon),