aboutsummaryrefslogtreecommitdiff
path: root/pkg/api
diff options
context:
space:
mode:
authorJhon Honce <jhonce@redhat.com>2021-12-06 16:45:58 -0700
committerJhon Honce <jhonce@redhat.com>2022-01-14 16:13:35 -0700
commit8a7e70919f4bab0757523ae97c170396cb13c83d (patch)
tree0ec2b5aa4e3c1e6574e606a0e7db3638fdeda578 /pkg/api
parentec2b213ab611cb197e86c45d03fb10af667ad95c (diff)
downloadpodman-8a7e70919f4bab0757523ae97c170396cb13c83d.tar.gz
podman-8a7e70919f4bab0757523ae97c170396cb13c83d.tar.bz2
podman-8a7e70919f4bab0757523ae97c170396cb13c83d.zip
Refactor manifest list operations
* Update method/function signatures use the manifest list name and images associated with the operation explicitly, in general func f(ctx context.Context, manifestListName string, ImageNames []string, options *fOptions) * Leverage gorilla/mux Subrouters to support API v3.x and v4.x for manifests * Make manifest API endpoints more RESTful * Add PUT /manifest/{id} to update existing manifests * Add manifests.Annotate to go bindings, uncommented unit test * Add DELETE /manifest/{Id} to remove existing manifest list, use PUT /manifest/{id} to remove images from a list * Deprecated POST /manifest/{id}/add and /manifest/{id}/remove, use PUT /manifest/{id} instead * Corrected swagger godoc and updated to cover API changes * Update podman manifest commands to use registry.Context() * Expose utils.GetVar() to obtain query parameters by name * Unexpose server.registerSwaggerHandlers, not sure why this was ever exposed. * Refactored code to use http.Header instead of map[string]string when operating on HTTP headers. * Add API-Version header support in bindings to allow calling explicate versions of the API. Header is _NOT_ forwarded to the API service. Signed-off-by: Jhon Honce <jhonce@redhat.com>
Diffstat (limited to 'pkg/api')
-rw-r--r--pkg/api/handlers/libpod/manifests.go265
-rw-r--r--pkg/api/handlers/utils/handler.go4
-rw-r--r--pkg/api/server/register_manifest.go177
-rw-r--r--pkg/api/server/register_swagger.go4
-rw-r--r--pkg/api/server/server.go2
5 files changed, 401 insertions, 51 deletions
diff --git a/pkg/api/handlers/libpod/manifests.go b/pkg/api/handlers/libpod/manifests.go
index eb0b6827f..ef0839d1f 100644
--- a/pkg/api/handlers/libpod/manifests.go
+++ b/pkg/api/handlers/libpod/manifests.go
@@ -3,7 +3,11 @@ package libpod
import (
"context"
"encoding/json"
+ "fmt"
+ "io/ioutil"
"net/http"
+ "net/url"
+ "strings"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/manifest"
@@ -15,6 +19,8 @@ import (
"github.com/containers/podman/v3/pkg/auth"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
+ "github.com/containers/podman/v3/pkg/errorhandling"
+ "github.com/gorilla/mux"
"github.com/gorilla/schema"
"github.com/opencontainers/go-digest"
"github.com/pkg/errors"
@@ -24,40 +30,93 @@ func ManifestCreate(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
- Name []string `schema:"name"`
- Image []string `schema:"image"`
- All bool `schema:"all"`
+ Name string `schema:"name"`
+ Images []string `schema:"images"`
+ All bool `schema:"all"`
}{
// Add defaults here once needed.
}
+
+ // Support 3.x API calls, alias image to images
+ if image, ok := r.URL.Query()["image"]; ok {
+ query.Images = image
+ }
+
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
}
- // TODO: (jhonce) When c/image is refactored the roadmap calls for this check to be pushed into that library.
- for _, n := range query.Name {
- if _, err := reference.ParseNormalizedNamed(n); err != nil {
+ // Support 4.x API calls, map query parameter to path
+ if name, ok := mux.Vars(r)["name"]; ok {
+ n, err := url.QueryUnescape(name)
+ if err != nil {
utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
- errors.Wrapf(err, "invalid image name %s", n))
+ errors.Wrapf(err, "failed to parse name parameter %q", name))
return
}
+ query.Name = n
+ }
+
+ if _, err := reference.ParseNormalizedNamed(query.Name); err != nil {
+ utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ errors.Wrapf(err, "invalid image name %s", query.Name))
+ return
}
imageEngine := abi.ImageEngine{Libpod: runtime}
createOptions := entities.ManifestCreateOptions{All: query.All}
- manID, err := imageEngine.ManifestCreate(r.Context(), query.Name, query.Image, createOptions)
+ manID, err := imageEngine.ManifestCreate(r.Context(), query.Name, query.Images, createOptions)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+
+ status := http.StatusOK
+ if _, err := utils.SupportedVersion(r, "< 4.0.0"); err == utils.ErrVersionNotSupported {
+ status = http.StatusCreated
+ }
+
+ buffer, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+
+ // Treat \r\n as empty body
+ if len(buffer) < 3 {
+ utils.WriteResponse(w, status, handlers.IDResponse{ID: manID})
+ return
+ }
+
+ body := new(entities.ManifestModifyOptions)
+ if err := json.Unmarshal(buffer, body); err != nil {
+ utils.InternalServerError(w, errors.Wrap(err, "Decode()"))
+ return
+ }
+
+ // gather all images for manifest list
+ var images []string
+ if len(query.Images) > 0 {
+ images = append(query.Images)
+ }
+ if len(body.Images) > 0 {
+ images = append(body.Images)
+ }
+
+ id, err := imageEngine.ManifestAdd(r.Context(), query.Name, images, body.ManifestAddOptions)
if err != nil {
utils.InternalServerError(w, err)
return
}
- utils.WriteResponse(w, http.StatusOK, handlers.IDResponse{ID: manID})
+
+ utils.WriteResponse(w, status, handlers.IDResponse{ID: id})
}
-// ExistsManifest check if a manifest list exists
-func ExistsManifest(w http.ResponseWriter, r *http.Request) {
+// ManifestExists return true if manifest list exists.
+func ManifestExists(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
name := utils.GetName(r)
@@ -94,10 +153,18 @@ func ManifestInspect(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusOK, schema2List)
}
+// ManifestAdd remove digest from manifest list
+//
+// Deprecated: As of 4.0.0 use ManifestModify instead
func ManifestAdd(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
- var addOptions entities.ManifestAddOptions
- if err := json.NewDecoder(r.Body).Decode(&addOptions); err != nil {
+
+ // Wrapper to support 3.x with 4.x libpod
+ query := struct {
+ entities.ManifestAddOptions
+ Images []string
+ }{}
+ if err := json.NewDecoder(r.Body).Decode(&query); err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
}
@@ -108,15 +175,8 @@ func ManifestAdd(w http.ResponseWriter, r *http.Request) {
return
}
- // FIXME: we really need to clean up the manifest API. Swagger states
- // the arguments were strings not string slices. The use of string
- // slices, mixing lists and images is incredibly confusing.
- if len(addOptions.Images) == 1 {
- addOptions.Images = append(addOptions.Images, name)
- }
-
imageEngine := abi.ImageEngine{Libpod: runtime}
- newID, err := imageEngine.ManifestAdd(r.Context(), addOptions)
+ newID, err := imageEngine.ManifestAdd(r.Context(), name, query.Images, query.ManifestAddOptions)
if err != nil {
utils.InternalServerError(w, err)
return
@@ -124,7 +184,10 @@ func ManifestAdd(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusOK, handlers.IDResponse{ID: newID})
}
-func ManifestRemove(w http.ResponseWriter, r *http.Request) {
+// ManifestRemoveDigest remove digest from manifest list
+//
+// Deprecated: As of 4.0.0 use ManifestModify instead
+func ManifestRemoveDigest(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
@@ -155,7 +218,10 @@ func ManifestRemove(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusOK, handlers.IDResponse{ID: manifestList.ID()})
}
-func ManifestPush(w http.ResponseWriter, r *http.Request) {
+// ManifestPushV3 push image to registry
+//
+// Deprecated: As of 4.0.0 use ManifestPush instead
+func ManifestPushV3(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
@@ -207,3 +273,156 @@ func ManifestPush(w http.ResponseWriter, r *http.Request) {
}
utils.WriteResponse(w, http.StatusOK, digest)
}
+
+// ManifestPush push image to registry
+//
+// As of 4.0.0
+func ManifestPush(w http.ResponseWriter, r *http.Request) {
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
+
+ query := struct {
+ All bool `schema:"all"`
+ TLSVerify bool `schema:"tlsVerify"`
+ }{
+ // 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
+ }
+
+ destination := utils.GetVar(r, "destination")
+ if err := utils.IsRegistryReference(destination); err != nil {
+ utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err)
+ return
+ }
+
+ authconf, authfile, err := auth.GetCredentials(r)
+ if err != nil {
+ utils.Error(w, "failed to retrieve repository credentials", http.StatusBadRequest, errors.Wrapf(err, "failed to parse registry header for %s", r.URL.String()))
+ return
+ }
+ defer auth.RemoveAuthfile(authfile)
+ var username, password string
+ if authconf != nil {
+ username = authconf.Username
+ password = authconf.Password
+ }
+ options := entities.ImagePushOptions{
+ Authfile: authfile,
+ Username: username,
+ Password: password,
+ All: query.All,
+ }
+ if sys := runtime.SystemContext(); sys != nil {
+ options.CertDir = sys.DockerCertPath
+ }
+ if _, found := r.URL.Query()["tlsVerify"]; found {
+ options.SkipTLSVerify = types.NewOptionalBool(!query.TLSVerify)
+ }
+
+ imageEngine := abi.ImageEngine{Libpod: runtime}
+ source := utils.GetName(r)
+ digest, err := imageEngine.ManifestPush(context.Background(), source, destination, options)
+ if err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "error pushing image %q", destination))
+ return
+ }
+ utils.WriteResponse(w, http.StatusOK, handlers.IDResponse{ID: digest})
+}
+
+// ManifestModify efficiently updates the named manifest list
+func ManifestModify(w http.ResponseWriter, r *http.Request) {
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ imageEngine := abi.ImageEngine{Libpod: runtime}
+
+ body := new(entities.ManifestModifyOptions)
+ if err := json.NewDecoder(r.Body).Decode(body); err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
+ return
+ }
+
+ name := utils.GetName(r)
+ if _, err := runtime.LibimageRuntime().LookupManifestList(name); err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusNotFound, err)
+ return
+ }
+
+ var report entities.ManifestModifyReport
+ switch {
+ case strings.EqualFold("update", body.Operation):
+ id, err := imageEngine.ManifestAdd(r.Context(), name, body.Images, body.ManifestAddOptions)
+ if err != nil {
+ report.Errors = append(report.Errors, err)
+ break
+ }
+ report = entities.ManifestModifyReport{
+ ID: id,
+ Images: body.Images,
+ }
+ case strings.EqualFold("remove", body.Operation):
+ for _, image := range body.Images {
+ id, err := imageEngine.ManifestRemoveDigest(r.Context(), name, image)
+ if err != nil {
+ report.Errors = append(report.Errors, err)
+ continue
+ }
+ report.ID = id
+ report.Images = append(report.Images, image)
+ }
+ case strings.EqualFold("annotate", body.Operation):
+ options := entities.ManifestAnnotateOptions{
+ Annotation: body.Annotation,
+ Arch: body.Arch,
+ Features: body.Features,
+ OS: body.OS,
+ OSFeatures: body.OSFeatures,
+ OSVersion: body.OSVersion,
+ Variant: body.Variant,
+ }
+ for _, image := range body.Images {
+ id, err := imageEngine.ManifestAnnotate(r.Context(), name, image, options)
+ if err != nil {
+ report.Errors = append(report.Errors, err)
+ continue
+ }
+ report.ID = id
+ report.Images = append(report.Images, image)
+ }
+ default:
+ utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ fmt.Errorf("illegal operation %q for %q", body.Operation, r.URL.String()))
+ return
+ }
+
+ statusCode := http.StatusOK
+ switch {
+ case len(report.Errors) > 0 && len(report.Images) > 0:
+ statusCode = http.StatusConflict
+ case len(report.Errors) > 0:
+ statusCode = http.StatusInternalServerError
+ }
+ utils.WriteResponse(w, statusCode, report)
+}
+
+// ManifestDelete removes a manifest list from storage
+func ManifestDelete(w http.ResponseWriter, r *http.Request) {
+ runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
+ imageEngine := abi.ImageEngine{Libpod: runtime}
+
+ name := utils.GetName(r)
+ if _, err := runtime.LibimageRuntime().LookupManifestList(name); err != nil {
+ utils.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound, err)
+ return
+ }
+
+ results, errs := imageEngine.ManifestRm(r.Context(), []string{name})
+ errsString := errorhandling.ErrorsToStrings(errs)
+ report := handlers.LibpodImagesRemoveReport{
+ ImageRemoveReport: *results,
+ Errors: errsString,
+ }
+ utils.WriteResponse(w, http.StatusOK, report)
+}
diff --git a/pkg/api/handlers/utils/handler.go b/pkg/api/handlers/utils/handler.go
index 96b7a957c..ee83755a1 100644
--- a/pkg/api/handlers/utils/handler.go
+++ b/pkg/api/handlers/utils/handler.go
@@ -174,7 +174,7 @@ func FilterMapToString(filters map[string][]string) (string, error) {
return string(f), nil
}
-func getVar(r *http.Request, k string) string {
+func GetVar(r *http.Request, k string) string {
val := mux.Vars(r)[k]
safeVal, err := url.PathUnescape(val)
if err != nil {
@@ -186,5 +186,5 @@ func getVar(r *http.Request, k string) string {
// GetName extracts the name from the mux
func GetName(r *http.Request) string {
- return getVar(r, "name")
+ return GetVar(r, "name")
}
diff --git a/pkg/api/server/register_manifest.go b/pkg/api/server/register_manifest.go
index 010d8a79e..8cd3d8b22 100644
--- a/pkg/api/server/register_manifest.go
+++ b/pkg/api/server/register_manifest.go
@@ -8,7 +8,9 @@ import (
)
func (s *APIServer) registerManifestHandlers(r *mux.Router) error {
- // swagger:operation POST /libpod/manifests/create manifests ManifestCreateLibpod
+ v3 := r.PathPrefix("/v{version:[0-3][0-9A-Za-z.-]*}/libpod/manifests").Subrouter()
+ v4 := r.PathPrefix("/v{version:[4-9][0-9A-Za-z.-]*}/libpod/manifests").Subrouter()
+ // swagger:operation POST /libpod/manifests manifests ManifestCreateLibpod
// ---
// summary: Create
// description: Create a manifest list
@@ -18,18 +20,30 @@ func (s *APIServer) registerManifestHandlers(r *mux.Router) error {
// - in: query
// name: name
// type: string
- // description: manifest list name
+ // description: manifest list or index name to create
// required: true
// - in: query
- // name: image
+ // name: images
// type: string
- // description: name of the image
+ // required: true
+ // description: |
+ // One or more names of an image or a manifest list. Repeat parameter as needed.
+ //
+ // Support for multiple images, as of version 4.0.0
+ // Alias of `image` is support for compatibility with < 4.0.0
+ // Response status code is 200 with < 4.0.0 for compatibility
// - in: query
// name: all
// type: boolean
// description: add all contents if given list
+ // - in: body
+ // name: options
+ // description: options for new manifest
+ // required: false
+ // schema:
+ // $ref: "#/definitions/ManifestModifyOptions"
// responses:
- // 200:
+ // 201:
// schema:
// $ref: "#/definitions/IDResponse"
// 400:
@@ -38,17 +52,21 @@ func (s *APIServer) registerManifestHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchImage"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/libpod/manifests/create"), s.APIHandler(libpod.ManifestCreate)).Methods(http.MethodPost)
+ v3.Handle("/create", s.APIHandler(libpod.ManifestCreate)).Methods(http.MethodPost)
+ v4.Handle("/{name:.*}", s.APIHandler(libpod.ManifestCreate)).Methods(http.MethodPost)
// swagger:operation GET /libpod/manifests/{name}/exists manifests ManifestExistsLibpod
// ---
// summary: Exists
- // description: Check if manifest list exists
+ // description: |
+ // Check if manifest list exists
+ //
+ // Note: There is no contract that the manifest list will exist for a follow-on operation
// parameters:
// - in: path
// name: name
// type: string
// required: true
- // description: the name of the manifest list
+ // description: the name or ID of the manifest list
// produces:
// - application/json
// responses:
@@ -58,11 +76,12 @@ func (s *APIServer) registerManifestHandlers(r *mux.Router) error {
// $ref: '#/responses/NoSuchManifest'
// 500:
// $ref: '#/responses/InternalError'
- r.Handle(VersionedPath("/libpod/manifests/{name}/exists"), s.APIHandler(libpod.ExistsManifest)).Methods(http.MethodGet)
+ v3.Handle("/{name:.*}/exists", s.APIHandler(libpod.ManifestExists)).Methods(http.MethodGet)
+ v4.Handle("/{name:.*}/exists", s.APIHandler(libpod.ManifestExists)).Methods(http.MethodGet)
// swagger:operation GET /libpod/manifests/{name}/json manifests ManifestInspectLibpod
// ---
// summary: Inspect
- // description: Display a manifest list
+ // description: Display attributes of given manifest list
// produces:
// - application/json
// parameters:
@@ -70,7 +89,7 @@ func (s *APIServer) registerManifestHandlers(r *mux.Router) error {
// name: name
// type: string
// required: true
- // description: the name or ID of the manifest
+ // description: the name or ID of the manifest list
// responses:
// 200:
// $ref: "#/responses/InspectManifest"
@@ -78,11 +97,53 @@ func (s *APIServer) registerManifestHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchManifest"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/libpod/manifests/{name:.*}/json"), s.APIHandler(libpod.ManifestInspect)).Methods(http.MethodGet)
+ v3.Handle("/{name:.*}/json", s.APIHandler(libpod.ManifestInspect)).Methods(http.MethodGet)
+ v4.Handle("/{name:.*}/json", s.APIHandler(libpod.ManifestInspect)).Methods(http.MethodGet)
+ // swagger:operation PUT /libpod/manifests/{name} manifests ManifestModifyLibpod
+ // ---
+ // summary: Modify manifest list
+ // description: |
+ // Add/Remove an image(s) to a manifest list
+ //
+ // Note: operations are not atomic when multiple Images are provided.
+ //
+ // As of v4.0.0
+ // produces:
+ // - application/json
+ // parameters:
+ // - in: path
+ // name: name
+ // type: string
+ // required: true
+ // description: the name or ID of the manifest
+ // - in: body
+ // name: options
+ // description: options for mutating a manifest
+ // required: true
+ // schema:
+ // $ref: "#/definitions/ManifestModifyOptions"
+ // responses:
+ // 200:
+ // schema:
+ // $ref: "#/definitions/ManifestModifyReport"
+ // 404:
+ // $ref: "#/responses/NoSuchManifest"
+ // 400:
+ // $ref: "#/responses/BadParamError"
+ // 409:
+ // description: Operation had partial success, both Images and Errors may have members
+ // schema:
+ // $ref: "#/definitions/ManifestModifyReport"
+ // 500:
+ // $ref: "#/responses/InternalError"
+ v4.Handle("/{name:.*}", s.APIHandler(libpod.ManifestModify)).Methods(http.MethodPut)
// swagger:operation POST /libpod/manifests/{name}/add manifests ManifestAddLibpod
// ---
// summary: Add image
- // description: Add an image to a manifest list
+ // description: |
+ // Add an image to a manifest list
+ //
+ // Deprecated: As of 4.0.0 use ManifestModifyLibpod instead
// produces:
// - application/json
// parameters:
@@ -95,7 +156,7 @@ func (s *APIServer) registerManifestHandlers(r *mux.Router) error {
// name: options
// description: options for creating a manifest
// schema:
- // $ref: "#/definitions/ManifestAddOpts"
+ // $ref: "#/definitions/ManifestAddOptions"
// responses:
// 200:
// schema:
@@ -106,11 +167,14 @@ func (s *APIServer) registerManifestHandlers(r *mux.Router) error {
// $ref: "#/responses/BadParamError"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/libpod/manifests/{name:.*}/add"), s.APIHandler(libpod.ManifestAdd)).Methods(http.MethodPost)
- // swagger:operation DELETE /libpod/manifests/{name} manifests ManifestDeleteLibpod
+ v3.Handle("/{name:.*}/add", s.APIHandler(libpod.ManifestAdd)).Methods(http.MethodPost)
+ // swagger:operation DELETE /libpod/manifests/{name} manifests ManifestDeleteV3Libpod
// ---
- // summary: Remove
- // description: Remove an image from a manifest list
+ // summary: Remove image from a manifest list
+ // description: |
+ // Remove an image from a manifest list
+ //
+ // Deprecated: As of 4.0.0 use ManifestModifyLibpod instead
// produces:
// - application/json
// parameters:
@@ -133,11 +197,37 @@ func (s *APIServer) registerManifestHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchManifest"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/libpod/manifests/{name:.*}"), s.APIHandler(libpod.ManifestRemove)).Methods(http.MethodDelete)
- // swagger:operation POST /libpod/manifests/{name}/push manifests ManifestPushLibpod
+ v3.Handle("/{name:.*}", s.APIHandler(libpod.ManifestRemoveDigest)).Methods(http.MethodDelete)
+ // swagger:operation DELETE /libpod/manifests/{name} manifests ManifestDeleteLibpod
// ---
- // summary: Push
- // description: Push a manifest list or image index to a registry
+ // summary: Delete manifest list
+ // description: |
+ // Delete named manifest list
+ //
+ // As of v4.0.0
+ // produces:
+ // - application/json
+ // parameters:
+ // - in: path
+ // name: name
+ // type: string
+ // required: true
+ // description: The name or ID of the list to be deleted
+ // responses:
+ // 200:
+ // $ref: "#/responses/DocsLibpodImagesRemoveResponse"
+ // 404:
+ // $ref: "#/responses/NoSuchManifest"
+ // 500:
+ // $ref: "#/responses/InternalError"
+ v4.Handle("/{name:.*}", s.APIHandler(libpod.ManifestDelete)).Methods(http.MethodDelete)
+ // swagger:operation POST /libpod/manifests/{name}/push manifests ManifestPushV3Libpod
+ // ---
+ // summary: Push manifest to registry
+ // description: |
+ // Push a manifest list or image index to a registry
+ //
+ // Deprecated: As of 4.0.0 use ManifestPushLibpod instead
// produces:
// - application/json
// parameters:
@@ -165,6 +255,47 @@ func (s *APIServer) registerManifestHandlers(r *mux.Router) error {
// $ref: "#/responses/NoSuchManifest"
// 500:
// $ref: "#/responses/InternalError"
- r.Handle(VersionedPath("/libpod/manifests/{name}/push"), s.APIHandler(libpod.ManifestPush)).Methods(http.MethodPost)
+ v3.Handle("/{name}/push", s.APIHandler(libpod.ManifestPushV3)).Methods(http.MethodPost)
+ // swagger:operation POST /libpod/manifests/{name}/registry/{destination} manifests ManifestPushLibpod
+ // ---
+ // summary: Push manifest list to registry
+ // description: |
+ // Push a manifest list or image index to the named registry
+ //
+ // As of v4.0.0
+ // produces:
+ // - application/json
+ // parameters:
+ // - in: path
+ // name: name
+ // type: string
+ // required: true
+ // description: the name or ID of the manifest list
+ // - in: path
+ // name: destination
+ // type: string
+ // required: true
+ // description: the registry for the manifest list
+ // - in: query
+ // name: all
+ // description: push all images
+ // type: boolean
+ // default: false
+ // - in: query
+ // name: tlsVerify
+ // type: boolean
+ // default: false
+ // description: skip TLS verification for registries
+ // responses:
+ // 200:
+ // schema:
+ // $ref: "#/definitions/IDResponse"
+ // 400:
+ // $ref: "#/responses/BadParamError"
+ // 404:
+ // $ref: "#/responses/NoSuchManifest"
+ // 500:
+ // $ref: "#/responses/InternalError"
+ v4.Handle("/{name:.*}/registry/{destination:.*}", s.APIHandler(libpod.ManifestPush)).Methods(http.MethodPost)
return nil
}
diff --git a/pkg/api/server/register_swagger.go b/pkg/api/server/register_swagger.go
index dca1df14b..48af7713f 100644
--- a/pkg/api/server/register_swagger.go
+++ b/pkg/api/server/register_swagger.go
@@ -7,8 +7,8 @@ import (
"github.com/gorilla/mux"
)
-// RegisterSwaggerHandlers maps the swagger endpoint for the server
-func (s *APIServer) RegisterSwaggerHandlers(r *mux.Router) error {
+// registerSwaggerHandlers maps the swagger endpoint for the server
+func (s *APIServer) registerSwaggerHandlers(r *mux.Router) error {
// This handler does _*NOT*_ provide an UI rather just a swagger spec that an UI could render
r.HandleFunc(VersionedPath("/libpod/swagger"), s.APIHandler(libpod.ServeSwagger)).Methods(http.MethodGet)
return nil
diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go
index 8c5c7aeeb..65b7e2474 100644
--- a/pkg/api/server/server.go
+++ b/pkg/api/server/server.go
@@ -151,7 +151,7 @@ func newServer(runtime *libpod.Runtime, listener *net.Listener, opts entities.Se
server.registerPluginsHandlers,
server.registerPodsHandlers,
server.registerSecretHandlers,
- server.RegisterSwaggerHandlers,
+ server.registerSwaggerHandlers,
server.registerSwarmHandlers,
server.registerSystemHandlers,
server.registerVersionHandlers,