Signed-off-by: Daniel Nephin <dnephin@docker.com>
| ... | ... |
@@ -68,8 +68,13 @@ type systemBackend interface {
|
| 68 | 68 |
ContainersPrune(ctx context.Context, pruneFilters filters.Args) (*types.ContainersPruneReport, error) |
| 69 | 69 |
} |
| 70 | 70 |
|
| 71 |
+type commitBackend interface {
|
|
| 72 |
+ CreateImageFromContainer(name string, config *backend.CreateImageConfig) (imageID string, err error) |
|
| 73 |
+} |
|
| 74 |
+ |
|
| 71 | 75 |
// Backend is all the methods that need to be implemented to provide container specific functionality. |
| 72 | 76 |
type Backend interface {
|
| 77 |
+ commitBackend |
|
| 73 | 78 |
execBackend |
| 74 | 79 |
copyBackend |
| 75 | 80 |
stateBackend |
| ... | ... |
@@ -61,6 +61,7 @@ func (r *containerRouter) initRoutes() {
|
| 61 | 61 |
router.NewPostRoute("/containers/{name:.*}/rename", r.postContainerRename),
|
| 62 | 62 |
router.NewPostRoute("/containers/{name:.*}/update", r.postContainerUpdate),
|
| 63 | 63 |
router.NewPostRoute("/containers/prune", r.postContainersPrune, router.WithCancel),
|
| 64 |
+ router.NewPostRoute("/commit", r.postCommit),
|
|
| 64 | 65 |
// PUT |
| 65 | 66 |
router.NewPutRoute("/containers/{name:.*}/archive", r.putContainersArchive),
|
| 66 | 67 |
// DELETE |
| ... | ... |
@@ -24,6 +24,45 @@ import ( |
| 24 | 24 |
"golang.org/x/net/websocket" |
| 25 | 25 |
) |
| 26 | 26 |
|
| 27 |
+func (s *containerRouter) postCommit(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
|
| 28 |
+ if err := httputils.ParseForm(r); err != nil {
|
|
| 29 |
+ return err |
|
| 30 |
+ } |
|
| 31 |
+ |
|
| 32 |
+ if err := httputils.CheckForJSON(r); err != nil {
|
|
| 33 |
+ return err |
|
| 34 |
+ } |
|
| 35 |
+ |
|
| 36 |
+ // TODO: remove pause arg, and always pause in backend |
|
| 37 |
+ pause := httputils.BoolValue(r, "pause") |
|
| 38 |
+ version := httputils.VersionFromContext(ctx) |
|
| 39 |
+ if r.FormValue("pause") == "" && versions.GreaterThanOrEqualTo(version, "1.13") {
|
|
| 40 |
+ pause = true |
|
| 41 |
+ } |
|
| 42 |
+ |
|
| 43 |
+ config, _, _, err := s.decoder.DecodeConfig(r.Body) |
|
| 44 |
+ if err != nil && err != io.EOF { //Do not fail if body is empty.
|
|
| 45 |
+ return err |
|
| 46 |
+ } |
|
| 47 |
+ |
|
| 48 |
+ commitCfg := &backend.CreateImageConfig{
|
|
| 49 |
+ Pause: pause, |
|
| 50 |
+ Repo: r.Form.Get("repo"),
|
|
| 51 |
+ Tag: r.Form.Get("tag"),
|
|
| 52 |
+ Author: r.Form.Get("author"),
|
|
| 53 |
+ Comment: r.Form.Get("comment"),
|
|
| 54 |
+ Config: config, |
|
| 55 |
+ Changes: r.Form["changes"], |
|
| 56 |
+ } |
|
| 57 |
+ |
|
| 58 |
+ imgID, err := s.backend.CreateImageFromContainer(r.Form.Get("container"), commitCfg)
|
|
| 59 |
+ if err != nil {
|
|
| 60 |
+ return err |
|
| 61 |
+ } |
|
| 62 |
+ |
|
| 63 |
+ return httputils.WriteJSON(w, http.StatusCreated, &types.IDResponse{ID: imgID})
|
|
| 64 |
+} |
|
| 65 |
+ |
|
| 27 | 66 |
func (s *containerRouter) getContainersJSON(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
| 28 | 67 |
if err := httputils.ParseForm(r); err != nil {
|
| 29 | 68 |
return err |
| ... | ... |
@@ -4,7 +4,6 @@ import ( |
| 4 | 4 |
"io" |
| 5 | 5 |
|
| 6 | 6 |
"github.com/docker/docker/api/types" |
| 7 |
- "github.com/docker/docker/api/types/backend" |
|
| 8 | 7 |
"github.com/docker/docker/api/types/filters" |
| 9 | 8 |
"github.com/docker/docker/api/types/image" |
| 10 | 9 |
"github.com/docker/docker/api/types/registry" |
| ... | ... |
@@ -14,16 +13,11 @@ import ( |
| 14 | 14 |
// Backend is all the methods that need to be implemented |
| 15 | 15 |
// to provide image specific functionality. |
| 16 | 16 |
type Backend interface {
|
| 17 |
- containerBackend |
|
| 18 | 17 |
imageBackend |
| 19 | 18 |
importExportBackend |
| 20 | 19 |
registryBackend |
| 21 | 20 |
} |
| 22 | 21 |
|
| 23 |
-type containerBackend interface {
|
|
| 24 |
- CreateImageFromContainer(name string, config *backend.CreateImageConfig) (imageID string, err error) |
|
| 25 |
-} |
|
| 26 |
- |
|
| 27 | 22 |
type imageBackend interface {
|
| 28 | 23 |
ImageDelete(imageRef string, force, prune bool) ([]types.ImageDeleteResponseItem, error) |
| 29 | 24 |
ImageHistory(imageName string) ([]*image.HistoryResponseItem, error) |
| ... | ... |
@@ -1,23 +1,18 @@ |
| 1 | 1 |
package image // import "github.com/docker/docker/api/server/router/image" |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
- "github.com/docker/docker/api/server/httputils" |
|
| 5 | 4 |
"github.com/docker/docker/api/server/router" |
| 6 | 5 |
) |
| 7 | 6 |
|
| 8 | 7 |
// imageRouter is a router to talk with the image controller |
| 9 | 8 |
type imageRouter struct {
|
| 10 | 9 |
backend Backend |
| 11 |
- decoder httputils.ContainerDecoder |
|
| 12 | 10 |
routes []router.Route |
| 13 | 11 |
} |
| 14 | 12 |
|
| 15 | 13 |
// NewRouter initializes a new image router |
| 16 |
-func NewRouter(backend Backend, decoder httputils.ContainerDecoder) router.Router {
|
|
| 17 |
- r := &imageRouter{
|
|
| 18 |
- backend: backend, |
|
| 19 |
- decoder: decoder, |
|
| 20 |
- } |
|
| 14 |
+func NewRouter(backend Backend) router.Router {
|
|
| 15 |
+ r := &imageRouter{backend: backend}
|
|
| 21 | 16 |
r.initRoutes() |
| 22 | 17 |
return r |
| 23 | 18 |
} |
| ... | ... |
@@ -38,7 +33,6 @@ func (r *imageRouter) initRoutes() {
|
| 38 | 38 |
router.NewGetRoute("/images/{name:.*}/history", r.getImagesHistory),
|
| 39 | 39 |
router.NewGetRoute("/images/{name:.*}/json", r.getImagesByName),
|
| 40 | 40 |
// POST |
| 41 |
- router.NewPostRoute("/commit", r.postCommit),
|
|
| 42 | 41 |
router.NewPostRoute("/images/load", r.postImagesLoad),
|
| 43 | 42 |
router.NewPostRoute("/images/create", r.postImagesCreate, router.WithCancel),
|
| 44 | 43 |
router.NewPostRoute("/images/{name:.*}/push", r.postImagesPush, router.WithCancel),
|
| ... | ... |
@@ -4,14 +4,12 @@ import ( |
| 4 | 4 |
"encoding/base64" |
| 5 | 5 |
"encoding/json" |
| 6 | 6 |
"fmt" |
| 7 |
- "io" |
|
| 8 | 7 |
"net/http" |
| 9 | 8 |
"strconv" |
| 10 | 9 |
"strings" |
| 11 | 10 |
|
| 12 | 11 |
"github.com/docker/docker/api/server/httputils" |
| 13 | 12 |
"github.com/docker/docker/api/types" |
| 14 |
- "github.com/docker/docker/api/types/backend" |
|
| 15 | 13 |
"github.com/docker/docker/api/types/filters" |
| 16 | 14 |
"github.com/docker/docker/api/types/versions" |
| 17 | 15 |
"github.com/docker/docker/errdefs" |
| ... | ... |
@@ -24,45 +22,6 @@ import ( |
| 24 | 24 |
"golang.org/x/net/context" |
| 25 | 25 |
) |
| 26 | 26 |
|
| 27 |
-func (s *imageRouter) postCommit(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
|
| 28 |
- if err := httputils.ParseForm(r); err != nil {
|
|
| 29 |
- return err |
|
| 30 |
- } |
|
| 31 |
- |
|
| 32 |
- if err := httputils.CheckForJSON(r); err != nil {
|
|
| 33 |
- return err |
|
| 34 |
- } |
|
| 35 |
- |
|
| 36 |
- // TODO: remove pause arg, and always pause in backend |
|
| 37 |
- pause := httputils.BoolValue(r, "pause") |
|
| 38 |
- version := httputils.VersionFromContext(ctx) |
|
| 39 |
- if r.FormValue("pause") == "" && versions.GreaterThanOrEqualTo(version, "1.13") {
|
|
| 40 |
- pause = true |
|
| 41 |
- } |
|
| 42 |
- |
|
| 43 |
- config, _, _, err := s.decoder.DecodeConfig(r.Body) |
|
| 44 |
- if err != nil && err != io.EOF { //Do not fail if body is empty.
|
|
| 45 |
- return err |
|
| 46 |
- } |
|
| 47 |
- |
|
| 48 |
- commitCfg := &backend.CreateImageConfig{
|
|
| 49 |
- Pause: pause, |
|
| 50 |
- Repo: r.Form.Get("repo"),
|
|
| 51 |
- Tag: r.Form.Get("tag"),
|
|
| 52 |
- Author: r.Form.Get("author"),
|
|
| 53 |
- Comment: r.Form.Get("comment"),
|
|
| 54 |
- Config: config, |
|
| 55 |
- Changes: r.Form["changes"], |
|
| 56 |
- } |
|
| 57 |
- |
|
| 58 |
- imgID, err := s.backend.CreateImageFromContainer(r.Form.Get("container"), commitCfg)
|
|
| 59 |
- if err != nil {
|
|
| 60 |
- return err |
|
| 61 |
- } |
|
| 62 |
- |
|
| 63 |
- return httputils.WriteJSON(w, http.StatusCreated, &types.IDResponse{ID: imgID})
|
|
| 64 |
-} |
|
| 65 |
- |
|
| 66 | 27 |
// Creates an image from Pull or from Import |
| 67 | 28 |
func (s *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
| 68 | 29 |
|
| ... | ... |
@@ -514,7 +514,7 @@ func initRouter(opts routerOptions) {
|
| 514 | 514 |
// we need to add the checkpoint router before the container router or the DELETE gets masked |
| 515 | 515 |
checkpointrouter.NewRouter(opts.daemon, decoder), |
| 516 | 516 |
container.NewRouter(opts.daemon, decoder), |
| 517 |
- image.NewRouter(opts.daemon, decoder), |
|
| 517 |
+ image.NewRouter(opts.daemon), |
|
| 518 | 518 |
systemrouter.NewRouter(opts.daemon, opts.cluster, opts.buildCache), |
| 519 | 519 |
volume.NewRouter(opts.daemon), |
| 520 | 520 |
build.NewRouter(opts.buildBackend, opts.daemon), |