diff options
Diffstat (limited to 'pkg/bindings/manifests/manifests.go')
-rw-r--r-- | pkg/bindings/manifests/manifests.go | 138 |
1 files changed, 96 insertions, 42 deletions
diff --git a/pkg/bindings/manifests/manifests.go b/pkg/bindings/manifests/manifests.go index 458cb913a..70b3819f5 100644 --- a/pkg/bindings/manifests/manifests.go +++ b/pkg/bindings/manifests/manifests.go @@ -2,20 +2,24 @@ package manifests import ( "context" - "errors" "fmt" + "io/ioutil" "net/http" - "net/url" "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" + "github.com/containers/podman/v4/pkg/auth" "github.com/containers/podman/v4/pkg/bindings" "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" ) // Create creates a manifest for the given name. Optional images to be associated with @@ -93,15 +97,19 @@ func Add(ctx context.Context, name string, options *AddOptions) (string, error) 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, + 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) @@ -118,40 +126,27 @@ func Add(ctx context.Context, name string, options *AddOptions) (string, error) } reader := strings.NewReader(opts) - headers := make(http.Header) - v := version.APIVersion[version.Libpod][version.MinimalAPI] - headers.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", nil, headers, name) + header, err := auth.MakeXRegistryAuthHeader(&imageTypes.SystemContext{AuthFilePath: options.GetAuthfile()}, options.GetUsername(), options.GetPassword()) if err != nil { return "", err } - defer response.Body.Close() - - var idr handlers.IDResponse - return idr.ID, response.Process(&idr) -} - -// Remove deletes a manifest entry from a manifest list. Both name and the digest to be -// removed are mandatory inputs. The ID of the new manifest list is returned as a string. -func Remove(ctx context.Context, name, digest string, _ *RemoveOptions) (string, error) { - if bindings.ServiceVersion(ctx).GTE(semver.MustParse("4.0.0")) { - optionsv4 := new(ModifyOptions).WithOperation("remove") - return Modify(ctx, name, []string{digest}, optionsv4) - } - // API Version < 4.0.0 - conn, err := bindings.GetClient(ctx) + 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())) + } - headers := http.Header{} - headers.Add("API-Version", "3.4.0") + v := version.APIVersion[version.Libpod][version.MinimalAPI] + header.Add("API-Version", + fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)) - params := url.Values{} - params.Set("digest", digest) - response, err := conn.DoRequest(ctx, nil, http.MethodDelete, "/manifests/%s", params, headers, name) + response, err := conn.DoRequest(ctx, reader, http.MethodPost, "/manifests/%s/add", params, header, name) if err != nil { return "", err } @@ -161,6 +156,13 @@ func Remove(ctx context.Context, name, digest string, _ *RemoveOptions) (string, return idr.ID, response.Process(&idr) } +// Remove deletes a manifest entry from a manifest list. Both name and the digest to be +// removed are mandatory inputs. The ID of the new manifest list is returned as a string. +func Remove(ctx context.Context, name, digest string, _ *RemoveOptions) (string, error) { + optionsv4 := new(ModifyOptions).WithOperation("remove") + return Modify(ctx, name, []string{digest}, optionsv4) +} + // Push takes a manifest list and pushes to a destination. If the destination is not specified, // the name will be used instead. If the optional all boolean is specified, all images specified // in the list will be pushed as well. @@ -179,6 +181,14 @@ func Push(ctx context.Context, name, destination string, options *images.PushOpt return "", err } + header, err := auth.MakeXRegistryAuthHeader(&imageTypes.SystemContext{AuthFilePath: options.GetAuthfile()}, options.GetUsername(), options.GetPassword()) + 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 { return "", err @@ -192,18 +202,18 @@ func Push(ctx context.Context, name, destination string, options *images.PushOpt 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, nil, name, destination) + 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, nil, name) + response, err = conn.DoRequest(ctx, nil, http.MethodPost, "/manifests/%s/push", params, header, name) } if err != nil { return "", err } defer response.Body.Close() - return idr.ID, err + return idr.ID, response.Process(&idr) } // Modify modifies the given manifest list using options and the optional list of images @@ -223,14 +233,58 @@ func Modify(ctx context.Context, name string, images []string, options *ModifyOp } reader := strings.NewReader(opts) - response, err := conn.DoRequest(ctx, reader, http.MethodPut, "/manifests/%s", nil, nil, name) + 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())) + } + + response, err := conn.DoRequest(ctx, reader, http.MethodPut, "/manifests/%s", params, header, name) if err != nil { return "", err } defer response.Body.Close() - var idr handlers.IDResponse - return idr.ID, response.Process(&idr) + data, err := ioutil.ReadAll(response.Body) + if err != nil { + return "", errors.Wrap(err, "unable to process API response") + } + + if response.IsSuccess() || response.IsRedirection() { + var report entities.ManifestModifyReport + if err = jsoniter.Unmarshal(data, &report); err != nil { + return "", errors.Wrap(err, "unable to decode API response") + } + + err = errorhandling.JoinErrors(report.Errors) + if err != nil { + errModel := errorhandling.ErrorModel{ + Because: (errors.Cause(err)).Error(), + Message: err.Error(), + ResponseCode: response.StatusCode, + } + return report.ID, &errModel + } + return report.ID, nil + } + + errModel := errorhandling.ErrorModel{ + ResponseCode: response.StatusCode, + } + if err = jsoniter.Unmarshal(data, &errModel); err != nil { + return "", errors.Wrap(err, "unable to decode API response") + } + return "", &errModel } // Annotate modifies the given manifest list using options and the optional list of images |