From 76e2a0c5d3365205cb104280d41015d6ab25cd9a Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Tue, 4 Feb 2020 12:48:13 +0100 Subject: v2 api: /libpod/images/pull Implement the /libpod/images/pull endpoint and correct the swagger docs. The reference parameter is mandatory and must either be a c/image/docker/reference or a reference to the "docker://" transport as the pull endpoint is meant to only support pulling images from a registry. Signed-off-by: Valentin Rothberg --- pkg/api/server/register_images.go | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'pkg/api/server') diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go index 4a46b6ee6..98858dac2 100644 --- a/pkg/api/server/register_images.go +++ b/pkg/api/server/register_images.go @@ -691,34 +691,49 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // 500: // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/libpod/images/import"), APIHandler(s.Context, libpod.ImagesImport)).Methods(http.MethodPost) - // swagger:operation GET /libpod/images/pull libpod libpodImagesPull + // swagger:operation POST /libpod/images/pull libpod libpodImagesPull // --- // tags: // - images - // summary: Import image - // description: Import a previosly exported image as a tarball. + // summary: Pull images + // description: Pull one or more images from a container registry. // parameters: // - in: query // name: reference - // description: Mandatory reference to the image (e.g., quay.io/image/name:tag)/ + // description: Mandatory reference to the image (e.g., quay.io/image/name:tag) // type: string // - in: query // name: credentials // description: username:password for the registry. // type: string // - in: query + // name: os + // description: Pull image for the specified operating system. + // type: string + // - in: query + // name: arch + // description: Pull image for the specified architecture. + // type: string + // - in: query // name: tls-verify // description: Require TLS verification. // type: boolean // default: true + // - in: query + // name: all-tags + // description: Pull all tagged images in the repository. + // type: bool // produces: // - application/json // responses: // 200: // $ref: "#/responses/DocsLibpodImagesPullResponse" + // $ref: "#/response/LibpodImagesPullResponse" + // 400: + // $ref: "#/responses/BadParamError" // 500: // $ref: '#/responses/InternalError' - r.Handle(VersionedPath("/libpod/images/pull"), APIHandler(s.Context, libpod.ImagesPull)).Methods(http.MethodPost) + r.Handle(VersionedPath("/libpod/images/pull"), APIHandler(s.Context, libpod.ImagesPull)).Methods(http.MethodPut) // swagger:operation POST /libpod/images/prune libpod libpodPruneImages // --- // tags: -- cgit v1.2.3-54-g00ecf From 926c9f8fbbff6332be4ba97d96ba95a9f09b7f65 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Wed, 5 Feb 2020 14:30:25 +0100 Subject: v2 api: /libpod/images/load Implement the /libpod/images/load endpoint. Tested manually with curl: curl -X POST --data-binary "@image.tar" --header "Content-Type: application/x-tar" Signed-off-by: Valentin Rothberg --- go.sum | 2 ++ pkg/api/handlers/libpod/images.go | 38 ++++++++++++++++++++++++++++++++++++-- pkg/api/handlers/types.go | 3 +-- pkg/api/server/register_images.go | 12 ++++++------ 4 files changed, 45 insertions(+), 10 deletions(-) (limited to 'pkg/api/server') diff --git a/go.sum b/go.sum index 08ae862fe..0b959646c 100644 --- a/go.sum +++ b/go.sum @@ -44,6 +44,7 @@ github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7 github.com/checkpoint-restore/go-criu v0.0.0-20190109184317-bdb7599cd87b h1:T4nWG1TXIxeor8mAu5bFguPJgSIGhZqv/f0z55KCrJM= github.com/checkpoint-restore/go-criu v0.0.0-20190109184317-bdb7599cd87b/go.mod h1:TrMrLQfeENAPYPRsJuq3jsqdlRh3lvi6trTZJG8+tho= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f h1:tSNMc+rJDfmYntojat8lljbt1mgKNpTxUZJsSzJ9Y1s= github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= @@ -194,6 +195,7 @@ github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go index fffcad8ed..668daa377 100644 --- a/pkg/api/handlers/libpod/images.go +++ b/pkg/api/handlers/libpod/images.go @@ -3,6 +3,7 @@ package libpod import ( "context" "fmt" + "io" "io/ioutil" "net/http" "os" @@ -183,8 +184,41 @@ func ExportImage(w http.ResponseWriter, r *http.Request) { } func ImagesLoad(w http.ResponseWriter, r *http.Request) { - //TODO ... - utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.New("/libpod/images/load is not yet implemented")) + runtime := r.Context().Value("runtime").(*libpod.Runtime) + decoder := r.Context().Value("decoder").(*schema.Decoder) + query := struct { + Reference string `schema:"reference"` + }{ + // Add defaults here once needed. + } + + if err := decoder.Decode(&query, r.URL.Query()); err != nil { + utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, + errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + return + } + + tmpfile, err := ioutil.TempFile("", "libpod-images-load.tar") + if err != nil { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile")) + return + } + defer os.Remove(tmpfile.Name()) + defer tmpfile.Close() + + if _, err := io.Copy(tmpfile, r.Body); err != nil && err != io.EOF { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file")) + return + } + + tmpfile.Close() + loadedImage, err := runtime.LoadImage(context.Background(), query.Reference, tmpfile.Name(), os.Stderr, "") + if err != nil { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to load image")) + return + } + + utils.WriteResponse(w, http.StatusOK, []handlers.LibpodImagesLoadReport{{ID: loadedImage}}) } func ImagesImport(w http.ResponseWriter, r *http.Request) { diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go index c19397e60..0a06e080f 100644 --- a/pkg/api/handlers/types.go +++ b/pkg/api/handlers/types.go @@ -34,8 +34,7 @@ type ContainerConfig struct { } type LibpodImagesLoadReport struct { - ID string `json:"id"` - RepoTags []string `json:"repoTags"` + ID string `json:"id"` } type LibpodImagesImportReport struct { diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go index 98858dac2..631d8bde2 100644 --- a/pkg/api/server/register_images.go +++ b/pkg/api/server/register_images.go @@ -640,12 +640,8 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // parameters: // - in: query // name: change - // description: "Apply the following possible instructions to the created image (default []): CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | STOPSIGNAL | USER | VOLUME | WORKDIR. JSON encoded string" - // type: string - // - in: query - // name: message - // description: Set commit message for imported image - // type: string + // description: "Optional Name[:TAG] for the image" + // type: reference // - in: formData // name: upload // description: tarball of container image @@ -656,6 +652,8 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // responses: // 200: // $ref: "#/responses/DocsLibpodImagesLoadResponse" + // 400: + // $ref: "#/responses/BadParamError" // 500: // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/libpod/images/load"), APIHandler(s.Context, libpod.ImagesLoad)).Methods(http.MethodPost) @@ -688,6 +686,8 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // responses: // 200: // $ref: "#/responses/DocsLibpodImagesImportResponse" + // 400: + // $ref: "#/responses/BadParamError" // 500: // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/libpod/images/import"), APIHandler(s.Context, libpod.ImagesImport)).Methods(http.MethodPost) -- cgit v1.2.3-54-g00ecf From 185c82bc80705266f4dc2411d31fb1cb461f89c2 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Mon, 10 Feb 2020 11:46:06 +0100 Subject: v2 api: /libpod/images/import Implement the /libpod/images/import endpoint Tested manually with curl: curl -X POST --data-binary "@image.tar" --header "Content-Type: application/x-tar" Signed-off-by: Valentin Rothberg --- pkg/api/handlers/libpod/images.go | 46 +++++++++++++++++++++++++++++++++++++-- pkg/api/handlers/types.go | 3 +-- pkg/api/server/register_images.go | 16 +++++++++----- 3 files changed, 56 insertions(+), 9 deletions(-) (limited to 'pkg/api/server') diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go index 668daa377..f6459f1eb 100644 --- a/pkg/api/handlers/libpod/images.go +++ b/pkg/api/handlers/libpod/images.go @@ -222,8 +222,50 @@ func ImagesLoad(w http.ResponseWriter, r *http.Request) { } func ImagesImport(w http.ResponseWriter, r *http.Request) { - //TODO ... - utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.New("/libpod/images/import is not yet implemented")) + runtime := r.Context().Value("runtime").(*libpod.Runtime) + decoder := r.Context().Value("decoder").(*schema.Decoder) + query := struct { + Changes []string `schema:"changes"` + Message string `schema:"message"` + Reference string `schema:"reference"` + URL string `schema:"URL"` + }{ + // Add defaults here once needed. + } + + if err := decoder.Decode(&query, r.URL.Query()); err != nil { + utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, + errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + return + } + + // Check if we need to load the image from a URL or from the request's body. + source := query.URL + if len(query.URL) == 0 { + tmpfile, err := ioutil.TempFile("", "libpod-images-import.tar") + if err != nil { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile")) + return + } + defer os.Remove(tmpfile.Name()) + defer tmpfile.Close() + + if _, err := io.Copy(tmpfile, r.Body); err != nil && err != io.EOF { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file")) + return + } + + tmpfile.Close() + source = tmpfile.Name() + } + + importedImage, err := runtime.Import(context.Background(), source, query.Reference, query.Changes, query.Message, true) + if err != nil { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to import image")) + return + } + + utils.WriteResponse(w, http.StatusOK, handlers.LibpodImagesImportReport{ID: importedImage}) } func ImagesPull(w http.ResponseWriter, r *http.Request) { diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go index 0a06e080f..f5d9f9ad5 100644 --- a/pkg/api/handlers/types.go +++ b/pkg/api/handlers/types.go @@ -38,8 +38,7 @@ type LibpodImagesLoadReport struct { } type LibpodImagesImportReport struct { - ID string `json:"id"` - RepoTags []string `json:"repoTags"` + ID string `json:"id"` } type LibpodImagesPullReport struct { diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go index 631d8bde2..8de584b86 100644 --- a/pkg/api/server/register_images.go +++ b/pkg/api/server/register_images.go @@ -665,17 +665,23 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: Import a previously exported tarball as an image. // parameters: // - in: query - // name: change - // description: "Apply the following possible instructions to the created image (default []): CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | STOPSIGNAL | USER | VOLUME | WORKDIR. JSON encoded string" - // type: string + // name: changes + // description: "Apply the following possible instructions to the created image: CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | STOPSIGNAL | USER | VOLUME | WORKDIR. JSON encoded string" + // type: array + // items: + // type: string // - in: query // name: message // description: Set commit message for imported image // type: string // - in: query + // name: change + // description: "Optional Name[:TAG] for the image" + // type: reference + // - in: query // name: url - // description: Specify a URL instead of a tarball - // type: boolean + // description: Load image from the specified URL + // type: string // - in: formData // name: upload // type: file -- cgit v1.2.3-54-g00ecf From 13187607e7efd56809dd806765de872e1ccb1826 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Mon, 10 Feb 2020 12:40:53 +0100 Subject: swagger: fix /libpod/images/{import,load,pull} Signed-off-by: Valentin Rothberg --- pkg/api/server/register_images.go | 61 +++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 31 deletions(-) (limited to 'pkg/api/server') diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go index 8de584b86..f082c5fec 100644 --- a/pkg/api/server/register_images.go +++ b/pkg/api/server/register_images.go @@ -639,9 +639,9 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: Load an image (oci-archive or docker-archive) stream. // parameters: // - in: query - // name: change + // name: reference // description: "Optional Name[:TAG] for the image" - // type: reference + // type: string // - in: formData // name: upload // description: tarball of container image @@ -675,9 +675,9 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: Set commit message for imported image // type: string // - in: query - // name: change + // name: reference // description: "Optional Name[:TAG] for the image" - // type: reference + // type: string // - in: query // name: url // description: Load image from the specified URL @@ -704,42 +704,41 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // summary: Pull images // description: Pull one or more images from a container registry. // parameters: - // - in: query - // name: reference - // description: Mandatory reference to the image (e.g., quay.io/image/name:tag) - // type: string - // - in: query - // name: credentials - // description: username:password for the registry. - // type: string - // - in: query - // name: os - // description: Pull image for the specified operating system. - // type: string - // - in: query - // name: arch - // description: Pull image for the specified architecture. - // type: string - // - in: query - // name: tls-verify - // description: Require TLS verification. - // type: boolean - // default: true - // - in: query - // name: all-tags - // description: Pull all tagged images in the repository. - // type: bool + // - in: query + // name: reference + // description: "Mandatory reference to the image (e.g., quay.io/image/name:tag)" + // type: string + // - in: query + // name: credentials + // description: "username:password for the registry" + // type: string + // - in: query + // name: overrideOS + // description: Pull image for the specified operating system. + // type: string + // - in: query + // name: overrideArch + // description: Pull image for the specified architecture. + // type: string + // - in: query + // name: tlsVerify + // description: Require TLS verification. + // type: boolean + // default: true + // - in: query + // name: allTags + // description: Pull all tagged images in the repository. + // type: boolean // produces: // - application/json // responses: // 200: // $ref: "#/responses/DocsLibpodImagesPullResponse" - // $ref: "#/response/LibpodImagesPullResponse" // 400: // $ref: "#/responses/BadParamError" // 500: // $ref: '#/responses/InternalError' - r.Handle(VersionedPath("/libpod/images/pull"), APIHandler(s.Context, libpod.ImagesPull)).Methods(http.MethodPut) + r.Handle(VersionedPath("/libpod/images/pull"), APIHandler(s.Context, libpod.ImagesPull)).Methods(http.MethodPost) // swagger:operation POST /libpod/images/prune libpod libpodPruneImages // --- // tags: -- cgit v1.2.3-54-g00ecf