diff options
-rw-r--r-- | pkg/api/handlers/libpod/manifests.go | 10 | ||||
-rw-r--r-- | pkg/api/server/register_manifest.go | 157 | ||||
-rw-r--r-- | pkg/bindings/manifests/manifests.go | 91 | ||||
-rw-r--r-- | pkg/bindings/test/manifests_test.go | 2 | ||||
-rw-r--r-- | test/apiv2/01-basic.at | 2 | ||||
-rw-r--r-- | version/version.go | 4 |
6 files changed, 113 insertions, 153 deletions
diff --git a/pkg/api/handlers/libpod/manifests.go b/pkg/api/handlers/libpod/manifests.go index 15d4b9f89..8dc7c57d5 100644 --- a/pkg/api/handlers/libpod/manifests.go +++ b/pkg/api/handlers/libpod/manifests.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "net/http" "net/url" + "strconv" "strings" "github.com/containers/image/v5/docker/reference" @@ -372,6 +373,15 @@ func ManifestModify(w http.ResponseWriter, r *http.Request) { return } + if tlsVerify, ok := r.URL.Query()["tlsVerify"]; ok { + tls, err := strconv.ParseBool(tlsVerify[len(tlsVerify)-1]) + if err != nil { + utils.Error(w, http.StatusBadRequest, fmt.Errorf("tlsVerify param is not a bool: %w", err)) + return + } + body.SkipTLSVerify = types.NewOptionalBool(!tls) + } + authconf, authfile, err := auth.GetCredentials(r) if err != nil { utils.Error(w, http.StatusBadRequest, err) diff --git a/pkg/api/server/register_manifest.go b/pkg/api/server/register_manifest.go index 50a49bc1e..3e3a516f4 100644 --- a/pkg/api/server/register_manifest.go +++ b/pkg/api/server/register_manifest.go @@ -10,6 +10,82 @@ import ( func (s *APIServer) registerManifestHandlers(r *mux.Router) error { 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/{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: + // - in: path + // name: name + // type: string + // required: true + // description: the name or ID of the manifest + // - in: query + // name: destination + // type: string + // required: true + // description: the destination for the manifest + // - in: query + // name: all + // description: push all images + // type: boolean + // responses: + // 200: + // schema: + // $ref: "#/definitions/IDResponse" + // 400: + // $ref: "#/responses/BadParamError" + // 404: + // $ref: "#/responses/NoSuchManifest" + // 500: + // $ref: "#/responses/InternalError" + 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) // swagger:operation POST /libpod/manifests manifests ManifestCreateLibpod // --- // summary: Create @@ -116,6 +192,11 @@ func (s *APIServer) registerManifestHandlers(r *mux.Router) error { // type: string // required: true // description: the name or ID of the manifest + // - in: query + // name: tlsVerify + // type: boolean + // default: false + // description: skip TLS verification for registries // - in: body // name: options // description: options for mutating a manifest @@ -221,81 +302,5 @@ func (s *APIServer) registerManifestHandlers(r *mux.Router) error { // 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: - // - in: path - // name: name - // type: string - // required: true - // description: the name or ID of the manifest - // - in: query - // name: destination - // type: string - // required: true - // description: the destination for the manifest - // - in: query - // name: all - // description: push all images - // type: boolean - // responses: - // 200: - // schema: - // $ref: "#/definitions/IDResponse" - // 400: - // $ref: "#/responses/BadParamError" - // 404: - // $ref: "#/responses/NoSuchManifest" - // 500: - // $ref: "#/responses/InternalError" - 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/bindings/manifests/manifests.go b/pkg/bindings/manifests/manifests.go index 70b3819f5..828f4922c 100644 --- a/pkg/bindings/manifests/manifests.go +++ b/pkg/bindings/manifests/manifests.go @@ -2,13 +2,11 @@ package manifests import ( "context" - "fmt" "io/ioutil" "net/http" "strconv" "strings" - "github.com/blang/semver" "github.com/containers/image/v5/manifest" imageTypes "github.com/containers/image/v5/types" "github.com/containers/podman/v4/pkg/api/handlers" @@ -17,7 +15,6 @@ import ( "github.com/containers/podman/v4/pkg/bindings/images" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/errorhandling" - "github.com/containers/podman/v4/version" jsoniter "github.com/json-iterator/go" "github.com/pkg/errors" ) @@ -95,65 +92,23 @@ func Add(ctx context.Context, name string, options *AddOptions) (string, error) options = new(AddOptions) } - if bindings.ServiceVersion(ctx).GTE(semver.MustParse("4.0.0")) { - optionsv4 := ModifyOptions{ - All: options.All, - Annotations: options.Annotation, - Arch: options.Arch, - Features: options.Features, - Images: options.Images, - OS: options.OS, - OSFeatures: nil, - OSVersion: options.OSVersion, - Variant: options.Variant, - Username: options.Username, - Password: options.Password, - Authfile: options.Authfile, - SkipTLSVerify: options.SkipTLSVerify, - } - optionsv4.WithOperation("update") - return Modify(ctx, name, options.Images, &optionsv4) - } - - // API Version < 4.0.0 - conn, err := bindings.GetClient(ctx) - if err != nil { - return "", err - } - opts, err := jsoniter.MarshalToString(options) - if err != nil { - return "", err - } - reader := strings.NewReader(opts) - - header, err := auth.MakeXRegistryAuthHeader(&imageTypes.SystemContext{AuthFilePath: options.GetAuthfile()}, options.GetUsername(), options.GetPassword()) - if err != nil { - return "", err - } - - params, err := options.ToParams() - if err != nil { - return "", err - } - // SkipTLSVerify is special. We need to delete the param added by - // ToParams() and change the key and flip the bool - if options.SkipTLSVerify != nil { - params.Del("SkipTLSVerify") - params.Set("tlsVerify", strconv.FormatBool(!options.GetSkipTLSVerify())) - } - - v := version.APIVersion[version.Libpod][version.MinimalAPI] - header.Add("API-Version", - fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)) - - response, err := conn.DoRequest(ctx, reader, http.MethodPost, "/manifests/%s/add", params, header, name) - if err != nil { - return "", err - } - defer response.Body.Close() - - var idr handlers.IDResponse - return idr.ID, response.Process(&idr) + optionsv4 := ModifyOptions{ + All: options.All, + Annotations: options.Annotation, + Arch: options.Arch, + Features: options.Features, + Images: options.Images, + OS: options.OS, + OSFeatures: nil, + OSVersion: options.OSVersion, + Variant: options.Variant, + Username: options.Username, + Password: options.Password, + Authfile: options.Authfile, + SkipTLSVerify: options.SkipTLSVerify, + } + optionsv4.WithOperation("update") + return Modify(ctx, name, options.Images, &optionsv4) } // Remove deletes a manifest entry from a manifest list. Both name and the digest to be @@ -185,9 +140,6 @@ func Push(ctx context.Context, name, destination string, options *images.PushOpt if err != nil { return "", err } - v := version.APIVersion[version.Libpod][version.MinimalAPI] - header.Add("API-Version", - fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)) params, err := options.ToParams() if err != nil { @@ -200,14 +152,7 @@ func Push(ctx context.Context, name, destination string, options *images.PushOpt params.Set("tlsVerify", strconv.FormatBool(!options.GetSkipTLSVerify())) } - var response *bindings.APIResponse - if bindings.ServiceVersion(ctx).GTE(semver.MustParse("4.0.0")) { - response, err = conn.DoRequest(ctx, nil, http.MethodPost, "/manifests/%s/registry/%s", params, header, name, destination) - } else { - params.Set("image", name) - params.Set("destination", destination) - response, err = conn.DoRequest(ctx, nil, http.MethodPost, "/manifests/%s/push", params, header, name) - } + response, err := conn.DoRequest(ctx, nil, http.MethodPost, "/manifests/%s/registry/%s", params, header, name, destination) if err != nil { return "", err } diff --git a/pkg/bindings/test/manifests_test.go b/pkg/bindings/test/manifests_test.go index 64becda43..e6c93817d 100644 --- a/pkg/bindings/test/manifests_test.go +++ b/pkg/bindings/test/manifests_test.go @@ -96,7 +96,7 @@ var _ = Describe("podman manifest", func() { Expect(err).To(HaveOccurred()) code, _ = bindings.CheckResponseCode(err) - Expect(code).To(BeNumerically("==", http.StatusInternalServerError)) + Expect(code).To(BeNumerically("==", http.StatusBadRequest)) }) It("remove digest", func() { diff --git a/test/apiv2/01-basic.at b/test/apiv2/01-basic.at index 2747ccbd4..e4348a9a7 100644 --- a/test/apiv2/01-basic.at +++ b/test/apiv2/01-basic.at @@ -19,7 +19,7 @@ for i in /version version; do t GET $i 200 \ .Components[0].Name="Podman Engine" \ .Components[0].Details.APIVersion~4[0-9.-]\\+ \ - .Components[0].Details.MinAPIVersion=3.1.0 \ + .Components[0].Details.MinAPIVersion=4.0.0 \ .Components[0].Details.Os=linux \ .ApiVersion=1.40 \ .MinAPIVersion=1.24 \ diff --git a/version/version.go b/version/version.go index c6bd2c239..5b2ca0d74 100644 --- a/version/version.go +++ b/version/version.go @@ -27,7 +27,7 @@ const ( // NOTE: remember to bump the version at the top // of the top-level README.md file when this is // bumped. -var Version = semver.MustParse("4.0.0-dev") +var Version = semver.MustParse("4.1.0-dev") // See https://docs.docker.com/engine/api/v1.40/ // libpod compat handlers are expected to honor docker API versions @@ -38,7 +38,7 @@ var Version = semver.MustParse("4.0.0-dev") var APIVersion = map[Tree]map[Level]semver.Version{ Libpod: { CurrentAPI: Version, - MinimalAPI: semver.MustParse("3.1.0"), + MinimalAPI: semver.MustParse("4.0.0"), }, Compat: { CurrentAPI: semver.MustParse("1.40.0"), |