diff options
author | Daniel J Walsh <dwalsh@redhat.com> | 2021-01-15 03:49:42 -0500 |
---|---|---|
committer | Daniel J Walsh <dwalsh@redhat.com> | 2021-01-15 13:24:34 -0500 |
commit | cf51c7ed9f955390a0e417f208046e0b8fbadb26 (patch) | |
tree | e20cf39ccab111aa9a86745fc9951f0a5f45ecf8 /pkg/bindings | |
parent | 5a166b297339d547d89fbf14248c3aff129eb960 (diff) | |
download | podman-cf51c7ed9f955390a0e417f208046e0b8fbadb26.tar.gz podman-cf51c7ed9f955390a0e417f208046e0b8fbadb26.tar.bz2 podman-cf51c7ed9f955390a0e417f208046e0b8fbadb26.zip |
Allow podman push to push manifest lists
When doing a podman images, manifests lists look just like images, so
it is logical that users would assume that they can just podman push them
to a registry. The problem is we throw out weird errors when this happens
and users need to somehow figure out this is a manifest list rather then
an image, and frankly the user will not understand the difference.
This PR will make podman push just do the right thing, by failing over and
attempting to push the manifest if it fails to push the image.
Fix up handling of manifest push
Protocol should bring back a digest string, which can either be
printed or stored in a file.
We should not reimplement the manifest push setup code in the tunnel
code but take advantage of the api path, to make sure remote and local
work the same way.
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
Diffstat (limited to 'pkg/bindings')
-rw-r--r-- | pkg/bindings/images/types.go | 2 | ||||
-rw-r--r-- | pkg/bindings/images/types_push_options.go | 16 | ||||
-rw-r--r-- | pkg/bindings/manifests/manifests.go | 13 | ||||
-rw-r--r-- | pkg/bindings/manifests/types.go | 6 | ||||
-rw-r--r-- | pkg/bindings/manifests/types_push_options.go | 104 |
5 files changed, 29 insertions, 112 deletions
diff --git a/pkg/bindings/images/types.go b/pkg/bindings/images/types.go index 3adb4356b..b3799b8c4 100644 --- a/pkg/bindings/images/types.go +++ b/pkg/bindings/images/types.go @@ -99,6 +99,8 @@ type ImportOptions struct { //go:generate go run ../generator/generator.go PushOptions // PushOptions are optional options for importing images type PushOptions struct { + // All indicates whether to push all images related to the image list + All *bool // Authfile is the path to the authentication file. Ignored for remote // calls. Authfile *string diff --git a/pkg/bindings/images/types_push_options.go b/pkg/bindings/images/types_push_options.go index 15210f30b..0c12ce4ac 100644 --- a/pkg/bindings/images/types_push_options.go +++ b/pkg/bindings/images/types_push_options.go @@ -87,6 +87,22 @@ func (o *PushOptions) ToParams() (url.Values, error) { return params, nil } +// WithAll +func (o *PushOptions) WithAll(value bool) *PushOptions { + v := &value + o.All = v + return o +} + +// GetAll +func (o *PushOptions) GetAll() bool { + var all bool + if o.All == nil { + return all + } + return *o.All +} + // WithAuthfile func (o *PushOptions) WithAuthfile(value string) *PushOptions { v := &value diff --git a/pkg/bindings/manifests/manifests.go b/pkg/bindings/manifests/manifests.go index ef4e2a908..b6db64b02 100644 --- a/pkg/bindings/manifests/manifests.go +++ b/pkg/bindings/manifests/manifests.go @@ -5,11 +5,13 @@ import ( "errors" "net/http" "net/url" + "strconv" "strings" "github.com/containers/image/v5/manifest" "github.com/containers/podman/v2/pkg/api/handlers" "github.com/containers/podman/v2/pkg/bindings" + "github.com/containers/podman/v2/pkg/bindings/images" jsoniter "github.com/json-iterator/go" ) @@ -112,12 +114,12 @@ func Remove(ctx context.Context, name, digest string, options *RemoveOptions) (s // 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. -func Push(ctx context.Context, name, destination string, options *PushOptions) (string, error) { +func Push(ctx context.Context, name, destination string, options *images.PushOptions) (string, error) { var ( idr handlers.IDResponse ) if options == nil { - options = new(PushOptions) + options = new(images.PushOptions) } if len(destination) < 1 { destination = name @@ -130,8 +132,15 @@ func Push(ctx context.Context, name, destination string, options *PushOptions) ( 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())) + } params.Set("image", name) params.Set("destination", destination) + params.Set("format", *options.Format) _, err = conn.DoRequest(nil, http.MethodPost, "/manifests/%s/push", params, nil, name) if err != nil { return "", err diff --git a/pkg/bindings/manifests/types.go b/pkg/bindings/manifests/types.go index f5054d424..7f84d69fc 100644 --- a/pkg/bindings/manifests/types.go +++ b/pkg/bindings/manifests/types.go @@ -28,9 +28,3 @@ type AddOptions struct { // RemoveOptions are optional options for removing manifests type RemoveOptions struct { } - -//go:generate go run ../generator/generator.go PushOptions -// RemoveOptions are optional options for pushing manifests -type PushOptions struct { - All *bool -} diff --git a/pkg/bindings/manifests/types_push_options.go b/pkg/bindings/manifests/types_push_options.go deleted file mode 100644 index 1d689f699..000000000 --- a/pkg/bindings/manifests/types_push_options.go +++ /dev/null @@ -1,104 +0,0 @@ -package manifests - -import ( - "net/url" - "reflect" - "strconv" - "strings" - - jsoniter "github.com/json-iterator/go" - "github.com/pkg/errors" -) - -/* -This file is generated automatically by go generate. Do not edit. -*/ - -// Changed -func (o *PushOptions) Changed(fieldName string) bool { - r := reflect.ValueOf(o) - value := reflect.Indirect(r).FieldByName(fieldName) - return !value.IsNil() -} - -// ToParams -func (o *PushOptions) ToParams() (url.Values, error) { - params := url.Values{} - if o == nil { - return params, nil - } - json := jsoniter.ConfigCompatibleWithStandardLibrary - s := reflect.ValueOf(o) - if reflect.Ptr == s.Kind() { - s = s.Elem() - } - sType := s.Type() - for i := 0; i < s.NumField(); i++ { - fieldName := sType.Field(i).Name - if !o.Changed(fieldName) { - continue - } - fieldName = strings.ToLower(fieldName) - f := s.Field(i) - if reflect.Ptr == f.Kind() { - f = f.Elem() - } - switch f.Kind() { - case reflect.Bool: - params.Set(fieldName, strconv.FormatBool(f.Bool())) - case reflect.String: - params.Set(fieldName, f.String()) - case reflect.Int, reflect.Int64: - // f.Int() is always an int64 - params.Set(fieldName, strconv.FormatInt(f.Int(), 10)) - case reflect.Uint, reflect.Uint64: - // f.Uint() is always an uint64 - params.Set(fieldName, strconv.FormatUint(f.Uint(), 10)) - case reflect.Slice: - typ := reflect.TypeOf(f.Interface()).Elem() - switch typ.Kind() { - case reflect.String: - sl := f.Slice(0, f.Len()) - s, ok := sl.Interface().([]string) - if !ok { - return nil, errors.New("failed to convert to string slice") - } - for _, val := range s { - params.Add(fieldName, val) - } - default: - return nil, errors.Errorf("unknown slice type %s", f.Kind().String()) - } - case reflect.Map: - lowerCaseKeys := make(map[string][]string) - iter := f.MapRange() - for iter.Next() { - lowerCaseKeys[iter.Key().Interface().(string)] = iter.Value().Interface().([]string) - - } - s, err := json.MarshalToString(lowerCaseKeys) - if err != nil { - return nil, err - } - - params.Set(fieldName, s) - } - } - return params, nil -} - -// WithAll -func (o *PushOptions) WithAll(value bool) *PushOptions { - v := &value - o.All = v - return o -} - -// GetAll -func (o *PushOptions) GetAll() bool { - var all bool - if o.All == nil { - return all - } - return *o.All -} |