diff options
author | baude <bbaude@redhat.com> | 2020-12-14 11:33:25 -0600 |
---|---|---|
committer | baude <bbaude@redhat.com> | 2020-12-17 09:40:51 -0600 |
commit | 86335aa4ae01dadecd36468409d742e68b76925d (patch) | |
tree | fd6e5bfeb924db9020073685d0133b2fa38622c1 /pkg/bindings | |
parent | c38ae47a1adf3235d8b01d724e7327e608dd8078 (diff) | |
download | podman-86335aa4ae01dadecd36468409d742e68b76925d.tar.gz podman-86335aa4ae01dadecd36468409d742e68b76925d.tar.bz2 podman-86335aa4ae01dadecd36468409d742e68b76925d.zip |
misc bindings to podman v3
manifest, system, info, volumes, play, and generate bindings are
updated to always have binding options.
Signed-off-by: baude <bbaude@redhat.com>
Diffstat (limited to 'pkg/bindings')
58 files changed, 3510 insertions, 221 deletions
diff --git a/pkg/bindings/generate/generate.go b/pkg/bindings/generate/generate.go index 8d0146ec1..29eb39557 100644 --- a/pkg/bindings/generate/generate.go +++ b/pkg/bindings/generate/generate.go @@ -4,31 +4,23 @@ import ( "context" "errors" "net/http" - "net/url" - "strconv" "github.com/containers/podman/v2/pkg/bindings" "github.com/containers/podman/v2/pkg/domain/entities" ) -func Systemd(ctx context.Context, nameOrID string, options entities.GenerateSystemdOptions) (*entities.GenerateSystemdReport, error) { +func Systemd(ctx context.Context, nameOrID string, options *SystemdOptions) (*entities.GenerateSystemdReport, error) { + if options == nil { + options = new(SystemdOptions) + } conn, err := bindings.GetClient(ctx) if err != nil { return nil, err } - params := url.Values{} - - params.Set("useName", strconv.FormatBool(options.Name)) - params.Set("new", strconv.FormatBool(options.New)) - if options.RestartPolicy != "" { - params.Set("restartPolicy", options.RestartPolicy) - } - if options.StopTimeout != nil { - params.Set("stopTimeout", strconv.FormatUint(uint64(*options.StopTimeout), 10)) + params, err := options.ToParams() + if err != nil { + return nil, err } - params.Set("containerPrefix", options.ContainerPrefix) - params.Set("podPrefix", options.PodPrefix) - params.Set("separator", options.Separator) response, err := conn.DoRequest(nil, http.MethodGet, "/generate/%s/systemd", params, nil, nameOrID) if err != nil { @@ -38,7 +30,10 @@ func Systemd(ctx context.Context, nameOrID string, options entities.GenerateSyst return report, response.Process(&report.Units) } -func Kube(ctx context.Context, nameOrIDs []string, options entities.GenerateKubeOptions) (*entities.GenerateKubeReport, error) { +func Kube(ctx context.Context, nameOrIDs []string, options *KubeOptions) (*entities.GenerateKubeReport, error) { + if options == nil { + options = new(KubeOptions) + } conn, err := bindings.GetClient(ctx) if err != nil { return nil, err @@ -46,12 +41,14 @@ func Kube(ctx context.Context, nameOrIDs []string, options entities.GenerateKube if len(nameOrIDs) < 1 { return nil, errors.New("must provide the name or ID of one container or pod") } - params := url.Values{} + + params, err := options.ToParams() + if err != nil { + return nil, err + } for _, name := range nameOrIDs { params.Add("names", name) } - params.Set("service", strconv.FormatBool(options.Service)) - response, err := conn.DoRequest(nil, http.MethodGet, "/generate/kube", params, nil) if err != nil { return nil, err diff --git a/pkg/bindings/generate/types.go b/pkg/bindings/generate/types.go new file mode 100644 index 000000000..2edf58768 --- /dev/null +++ b/pkg/bindings/generate/types.go @@ -0,0 +1,27 @@ +package generate + +//go:generate go run ../generator/generator.go KubeOptions +// KubeOptions are optional options for generating kube YAML files +type KubeOptions struct { + // Service - generate YAML for a Kubernetes _service_ object. + Service *bool +} + +//go:generate go run ../generator/generator.go SystemdOptions +// SystemdOptions are optional options for generating ssytemd files +type SystemdOptions struct { + // Name - use container/pod name instead of its ID. + UseName *bool + // New - create a new container instead of starting a new one. + New *bool + // RestartPolicy - systemd restart policy. + RestartPolicy *string + // StopTimeout - time when stopping the container. + StopTimeout *uint + // ContainerPrefix - systemd unit name prefix for containers + ContainerPrefix *string + // PodPrefix - systemd unit name prefix for pods + PodPrefix *string + // Separator - systemd unit name separator between name/id and prefix + Separator *string +} diff --git a/pkg/bindings/generate/types_kube_options.go b/pkg/bindings/generate/types_kube_options.go new file mode 100644 index 000000000..fbb26f554 --- /dev/null +++ b/pkg/bindings/generate/types_kube_options.go @@ -0,0 +1,104 @@ +package generate + +import ( + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-17 09:35:23.528143172 -0600 CST m=+0.000203394 +*/ + +// Changed +func (o *KubeOptions) Changed(fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +// ToParams +func (o *KubeOptions) 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 +} + +// WithService +func (o *KubeOptions) WithService(value bool) *KubeOptions { + v := &value + o.Service = v + return o +} + +// GetService +func (o *KubeOptions) GetService() bool { + var service bool + if o.Service == nil { + return service + } + return *o.Service +} diff --git a/pkg/bindings/generate/types_systemd_options.go b/pkg/bindings/generate/types_systemd_options.go new file mode 100644 index 000000000..20e032f5a --- /dev/null +++ b/pkg/bindings/generate/types_systemd_options.go @@ -0,0 +1,200 @@ +package generate + +import ( + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-17 09:35:23.663318384 -0600 CST m=+0.000158454 +*/ + +// Changed +func (o *SystemdOptions) Changed(fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +// ToParams +func (o *SystemdOptions) 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 +} + +// WithUseName +func (o *SystemdOptions) WithUseName(value bool) *SystemdOptions { + v := &value + o.UseName = v + return o +} + +// GetUseName +func (o *SystemdOptions) GetUseName() bool { + var useName bool + if o.UseName == nil { + return useName + } + return *o.UseName +} + +// WithNew +func (o *SystemdOptions) WithNew(value bool) *SystemdOptions { + v := &value + o.New = v + return o +} + +// GetNew +func (o *SystemdOptions) GetNew() bool { + var new bool + if o.New == nil { + return new + } + return *o.New +} + +// WithRestartPolicy +func (o *SystemdOptions) WithRestartPolicy(value string) *SystemdOptions { + v := &value + o.RestartPolicy = v + return o +} + +// GetRestartPolicy +func (o *SystemdOptions) GetRestartPolicy() string { + var restartPolicy string + if o.RestartPolicy == nil { + return restartPolicy + } + return *o.RestartPolicy +} + +// WithStopTimeout +func (o *SystemdOptions) WithStopTimeout(value uint) *SystemdOptions { + v := &value + o.StopTimeout = v + return o +} + +// GetStopTimeout +func (o *SystemdOptions) GetStopTimeout() uint { + var stopTimeout uint + if o.StopTimeout == nil { + return stopTimeout + } + return *o.StopTimeout +} + +// WithContainerPrefix +func (o *SystemdOptions) WithContainerPrefix(value string) *SystemdOptions { + v := &value + o.ContainerPrefix = v + return o +} + +// GetContainerPrefix +func (o *SystemdOptions) GetContainerPrefix() string { + var containerPrefix string + if o.ContainerPrefix == nil { + return containerPrefix + } + return *o.ContainerPrefix +} + +// WithPodPrefix +func (o *SystemdOptions) WithPodPrefix(value string) *SystemdOptions { + v := &value + o.PodPrefix = v + return o +} + +// GetPodPrefix +func (o *SystemdOptions) GetPodPrefix() string { + var podPrefix string + if o.PodPrefix == nil { + return podPrefix + } + return *o.PodPrefix +} + +// WithSeparator +func (o *SystemdOptions) WithSeparator(value string) *SystemdOptions { + v := &value + o.Separator = v + return o +} + +// GetSeparator +func (o *SystemdOptions) GetSeparator() string { + var separator string + if o.Separator == nil { + return separator + } + return *o.Separator +} diff --git a/pkg/bindings/generator/generator.go b/pkg/bindings/generator/generator.go index 2ebe35282..1fd428451 100644 --- a/pkg/bindings/generator/generator.go +++ b/pkg/bindings/generator/generator.go @@ -64,6 +64,9 @@ func (o *{{.StructName}}) ToParams() (url.Values, error) { 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() slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) @@ -92,8 +95,6 @@ func (o *{{.StructName}}) ToParams() (url.Values, error) { } params.Set(fieldName, s) - default: - return nil, errors.Errorf("unknown type %s", f.Kind().String()) } } return params, nil diff --git a/pkg/bindings/images/types.go b/pkg/bindings/images/types.go index c436413c3..e389ac9d6 100644 --- a/pkg/bindings/images/types.go +++ b/pkg/bindings/images/types.go @@ -79,7 +79,7 @@ type TagOptions struct { } //go:generate go run ../generator/generator.go UntagOptions -// UntagOptions are optional options for tagging images +// UntagOptions are optional options for untagging images type UntagOptions struct { } diff --git a/pkg/bindings/images/types_diff_options.go b/pkg/bindings/images/types_diff_options.go index 45e548056..e3ec8ea3d 100644 --- a/pkg/bindings/images/types_diff_options.go +++ b/pkg/bindings/images/types_diff_options.go @@ -12,7 +12,7 @@ import ( /* This file is generated automatically by go generate. Do not edit. -Created 2020-12-15 15:22:46.528172042 -0600 CST m=+0.000279712 +Created 2020-12-16 11:47:07.253097326 -0600 CST m=+0.000283385 */ // Changed @@ -51,6 +51,9 @@ func (o *DiffOptions) ToParams() (url.Values, error) { 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() slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) @@ -79,8 +82,6 @@ func (o *DiffOptions) ToParams() (url.Values, error) { } params.Set(fieldName, s) - default: - return nil, errors.Errorf("unknown type %s", f.Kind().String()) } } return params, nil diff --git a/pkg/bindings/images/types_export_options.go b/pkg/bindings/images/types_export_options.go index ae585ae3e..a14f9d267 100644 --- a/pkg/bindings/images/types_export_options.go +++ b/pkg/bindings/images/types_export_options.go @@ -12,7 +12,7 @@ import ( /* This file is generated automatically by go generate. Do not edit. -Created 2020-12-15 15:22:47.379804635 -0600 CST m=+0.000257609 +Created 2020-12-16 11:47:08.103165436 -0600 CST m=+0.000245546 */ // Changed @@ -51,6 +51,9 @@ func (o *ExportOptions) ToParams() (url.Values, error) { 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() slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) @@ -79,8 +82,6 @@ func (o *ExportOptions) ToParams() (url.Values, error) { } params.Set(fieldName, s) - default: - return nil, errors.Errorf("unknown type %s", f.Kind().String()) } } return params, nil diff --git a/pkg/bindings/images/types_get_options.go b/pkg/bindings/images/types_get_options.go index b7b45259d..a1c0f9b09 100644 --- a/pkg/bindings/images/types_get_options.go +++ b/pkg/bindings/images/types_get_options.go @@ -12,7 +12,7 @@ import ( /* This file is generated automatically by go generate. Do not edit. -Created 2020-12-15 15:22:46.81312808 -0600 CST m=+0.000257734 +Created 2020-12-16 11:47:07.536472335 -0600 CST m=+0.000251379 */ // Changed @@ -51,6 +51,9 @@ func (o *GetOptions) ToParams() (url.Values, error) { 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() slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) @@ -79,8 +82,6 @@ func (o *GetOptions) ToParams() (url.Values, error) { } params.Set(fieldName, s) - default: - return nil, errors.Errorf("unknown type %s", f.Kind().String()) } } return params, nil diff --git a/pkg/bindings/images/types_history_options.go b/pkg/bindings/images/types_history_options.go index 0fe73a990..7b3d82097 100644 --- a/pkg/bindings/images/types_history_options.go +++ b/pkg/bindings/images/types_history_options.go @@ -12,7 +12,7 @@ import ( /* This file is generated automatically by go generate. Do not edit. -Created 2020-12-15 15:22:47.095693605 -0600 CST m=+0.000243849 +Created 2020-12-16 11:47:07.818738329 -0600 CST m=+0.000253937 */ // Changed @@ -51,6 +51,9 @@ func (o *HistoryOptions) ToParams() (url.Values, error) { 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() slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) @@ -79,8 +82,6 @@ func (o *HistoryOptions) ToParams() (url.Values, error) { } params.Set(fieldName, s) - default: - return nil, errors.Errorf("unknown type %s", f.Kind().String()) } } return params, nil diff --git a/pkg/bindings/images/types_import_options.go b/pkg/bindings/images/types_import_options.go index 002f1cfa5..6552d63bd 100644 --- a/pkg/bindings/images/types_import_options.go +++ b/pkg/bindings/images/types_import_options.go @@ -12,7 +12,7 @@ import ( /* This file is generated automatically by go generate. Do not edit. -Created 2020-12-15 15:22:47.943587389 -0600 CST m=+0.000238222 +Created 2020-12-16 11:47:08.67072755 -0600 CST m=+0.000238081 */ // Changed @@ -51,6 +51,9 @@ func (o *ImportOptions) ToParams() (url.Values, error) { 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() slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) @@ -79,8 +82,6 @@ func (o *ImportOptions) ToParams() (url.Values, error) { } params.Set(fieldName, s) - default: - return nil, errors.Errorf("unknown type %s", f.Kind().String()) } } return params, nil diff --git a/pkg/bindings/images/types_list_options.go b/pkg/bindings/images/types_list_options.go index 0cdb243fa..0365d0e71 100644 --- a/pkg/bindings/images/types_list_options.go +++ b/pkg/bindings/images/types_list_options.go @@ -12,7 +12,7 @@ import ( /* This file is generated automatically by go generate. Do not edit. -Created 2020-12-15 15:22:46.671238196 -0600 CST m=+0.000266757 +Created 2020-12-16 11:47:07.39332655 -0600 CST m=+0.000275349 */ // Changed @@ -51,6 +51,9 @@ func (o *ListOptions) ToParams() (url.Values, error) { 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() slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) @@ -79,8 +82,6 @@ func (o *ListOptions) ToParams() (url.Values, error) { } params.Set(fieldName, s) - default: - return nil, errors.Errorf("unknown type %s", f.Kind().String()) } } return params, nil diff --git a/pkg/bindings/images/types_load_options.go b/pkg/bindings/images/types_load_options.go index a82521749..ffba08fcc 100644 --- a/pkg/bindings/images/types_load_options.go +++ b/pkg/bindings/images/types_load_options.go @@ -12,7 +12,7 @@ import ( /* This file is generated automatically by go generate. Do not edit. -Created 2020-12-15 15:22:47.237599061 -0600 CST m=+0.000247138 +Created 2020-12-16 11:47:07.961817946 -0600 CST m=+0.000243444 */ // Changed @@ -51,6 +51,9 @@ func (o *LoadOptions) ToParams() (url.Values, error) { 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() slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) @@ -79,8 +82,6 @@ func (o *LoadOptions) ToParams() (url.Values, error) { } params.Set(fieldName, s) - default: - return nil, errors.Errorf("unknown type %s", f.Kind().String()) } } return params, nil diff --git a/pkg/bindings/images/types_prune_options.go b/pkg/bindings/images/types_prune_options.go index 25da5e815..1f7f2cd8b 100644 --- a/pkg/bindings/images/types_prune_options.go +++ b/pkg/bindings/images/types_prune_options.go @@ -12,7 +12,7 @@ import ( /* This file is generated automatically by go generate. Do not edit. -Created 2020-12-15 15:22:47.521471344 -0600 CST m=+0.000250491 +Created 2020-12-16 11:47:08.24781882 -0600 CST m=+0.000244039 */ // Changed @@ -51,6 +51,9 @@ func (o *PruneOptions) ToParams() (url.Values, error) { 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() slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) @@ -79,8 +82,6 @@ func (o *PruneOptions) ToParams() (url.Values, error) { } params.Set(fieldName, s) - default: - return nil, errors.Errorf("unknown type %s", f.Kind().String()) } } return params, nil diff --git a/pkg/bindings/images/types_pull_options.go b/pkg/bindings/images/types_pull_options.go index 10d0c53e8..f22517d9e 100644 --- a/pkg/bindings/images/types_pull_options.go +++ b/pkg/bindings/images/types_pull_options.go @@ -13,7 +13,7 @@ import ( /* This file is generated automatically by go generate. Do not edit. -Created 2020-12-15 15:22:48.373345229 -0600 CST m=+0.000247562 +Created 2020-12-16 11:47:09.104988433 -0600 CST m=+0.000274515 */ // Changed @@ -52,6 +52,9 @@ func (o *PullOptions) ToParams() (url.Values, error) { 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() slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) @@ -80,8 +83,6 @@ func (o *PullOptions) ToParams() (url.Values, error) { } params.Set(fieldName, s) - default: - return nil, errors.Errorf("unknown type %s", f.Kind().String()) } } return params, nil diff --git a/pkg/bindings/images/types_push_options.go b/pkg/bindings/images/types_push_options.go index 2440d4c0f..b1d6b78fe 100644 --- a/pkg/bindings/images/types_push_options.go +++ b/pkg/bindings/images/types_push_options.go @@ -12,7 +12,7 @@ import ( /* This file is generated automatically by go generate. Do not edit. -Created 2020-12-15 15:22:48.08540302 -0600 CST m=+0.000302026 +Created 2020-12-16 11:47:08.817442617 -0600 CST m=+0.000259111 */ // Changed @@ -51,6 +51,9 @@ func (o *PushOptions) ToParams() (url.Values, error) { 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() slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) @@ -79,8 +82,6 @@ func (o *PushOptions) ToParams() (url.Values, error) { } params.Set(fieldName, s) - default: - return nil, errors.Errorf("unknown type %s", f.Kind().String()) } } return params, nil diff --git a/pkg/bindings/images/types_remove_options.go b/pkg/bindings/images/types_remove_options.go index 164ea1b3e..1245aec64 100644 --- a/pkg/bindings/images/types_remove_options.go +++ b/pkg/bindings/images/types_remove_options.go @@ -12,7 +12,7 @@ import ( /* This file is generated automatically by go generate. Do not edit. -Created 2020-12-15 15:22:46.378166859 -0600 CST m=+0.000249384 +Created 2020-12-16 11:47:07.115421951 -0600 CST m=+0.000310512 */ // Changed @@ -51,6 +51,9 @@ func (o *RemoveOptions) ToParams() (url.Values, error) { 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() slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) @@ -79,8 +82,6 @@ func (o *RemoveOptions) ToParams() (url.Values, error) { } params.Set(fieldName, s) - default: - return nil, errors.Errorf("unknown type %s", f.Kind().String()) } } return params, nil diff --git a/pkg/bindings/images/types_search_options.go b/pkg/bindings/images/types_search_options.go index b0b413a6c..3b89f7acc 100644 --- a/pkg/bindings/images/types_search_options.go +++ b/pkg/bindings/images/types_search_options.go @@ -12,7 +12,7 @@ import ( /* This file is generated automatically by go generate. Do not edit. -Created 2020-12-15 15:22:48.229349981 -0600 CST m=+0.000244343 +Created 2020-12-16 11:47:08.958897824 -0600 CST m=+0.000238136 */ // Changed @@ -51,6 +51,9 @@ func (o *SearchOptions) ToParams() (url.Values, error) { 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() slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) @@ -79,8 +82,6 @@ func (o *SearchOptions) ToParams() (url.Values, error) { } params.Set(fieldName, s) - default: - return nil, errors.Errorf("unknown type %s", f.Kind().String()) } } return params, nil diff --git a/pkg/bindings/images/types_tag_options.go b/pkg/bindings/images/types_tag_options.go index 5efc6462e..8d1070750 100644 --- a/pkg/bindings/images/types_tag_options.go +++ b/pkg/bindings/images/types_tag_options.go @@ -12,7 +12,7 @@ import ( /* This file is generated automatically by go generate. Do not edit. -Created 2020-12-15 15:22:47.66229668 -0600 CST m=+0.000246630 +Created 2020-12-16 11:47:08.388404224 -0600 CST m=+0.000253809 */ // Changed @@ -51,6 +51,9 @@ func (o *TagOptions) ToParams() (url.Values, error) { 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() slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) @@ -79,8 +82,6 @@ func (o *TagOptions) ToParams() (url.Values, error) { } params.Set(fieldName, s) - default: - return nil, errors.Errorf("unknown type %s", f.Kind().String()) } } return params, nil diff --git a/pkg/bindings/images/types_tree_options.go b/pkg/bindings/images/types_tree_options.go index cca663c67..765f99e83 100644 --- a/pkg/bindings/images/types_tree_options.go +++ b/pkg/bindings/images/types_tree_options.go @@ -12,7 +12,7 @@ import ( /* This file is generated automatically by go generate. Do not edit. -Created 2020-12-15 15:22:46.954579136 -0600 CST m=+0.000248704 +Created 2020-12-16 11:47:07.676177228 -0600 CST m=+0.000254279 */ // Changed @@ -51,6 +51,9 @@ func (o *TreeOptions) ToParams() (url.Values, error) { 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() slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) @@ -79,8 +82,6 @@ func (o *TreeOptions) ToParams() (url.Values, error) { } params.Set(fieldName, s) - default: - return nil, errors.Errorf("unknown type %s", f.Kind().String()) } } return params, nil diff --git a/pkg/bindings/images/types_untag_options.go b/pkg/bindings/images/types_untag_options.go index d960f6b40..d6ce1f1c7 100644 --- a/pkg/bindings/images/types_untag_options.go +++ b/pkg/bindings/images/types_untag_options.go @@ -12,7 +12,7 @@ import ( /* This file is generated automatically by go generate. Do not edit. -Created 2020-12-15 15:22:47.802372989 -0600 CST m=+0.000239766 +Created 2020-12-16 11:47:08.530676487 -0600 CST m=+0.000238259 */ // Changed @@ -51,6 +51,9 @@ func (o *UntagOptions) ToParams() (url.Values, error) { 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() slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) @@ -79,8 +82,6 @@ func (o *UntagOptions) ToParams() (url.Values, error) { } params.Set(fieldName, s) - default: - return nil, errors.Errorf("unknown type %s", f.Kind().String()) } } return params, nil diff --git a/pkg/bindings/manifests/manifests.go b/pkg/bindings/manifests/manifests.go index 0330b13e2..ef4e2a908 100644 --- a/pkg/bindings/manifests/manifests.go +++ b/pkg/bindings/manifests/manifests.go @@ -5,11 +5,9 @@ import ( "errors" "net/http" "net/url" - "strconv" "strings" "github.com/containers/image/v5/manifest" - "github.com/containers/podman/v2/libpod/image" "github.com/containers/podman/v2/pkg/api/handlers" "github.com/containers/podman/v2/pkg/bindings" jsoniter "github.com/json-iterator/go" @@ -19,8 +17,11 @@ import ( // the new manifest can also be specified. The all boolean specifies to add all entries // of a list if the name provided is a manifest list. The ID of the new manifest list // is returned as a string. -func Create(ctx context.Context, names, images []string, all *bool) (string, error) { +func Create(ctx context.Context, names, images []string, options *CreateOptions) (string, error) { var idr handlers.IDResponse + if options == nil { + options = new(CreateOptions) + } conn, err := bindings.GetClient(ctx) if err != nil { return "", err @@ -28,9 +29,9 @@ func Create(ctx context.Context, names, images []string, all *bool) (string, err if len(names) < 1 { return "", errors.New("creating a manifest requires at least one name argument") } - params := url.Values{} - if all != nil { - params.Set("all", strconv.FormatBool(*all)) + params, err := options.ToParams() + if err != nil { + return "", err } for _, name := range names { params.Add("name", name) @@ -47,8 +48,12 @@ func Create(ctx context.Context, names, images []string, all *bool) (string, err } // Inspect returns a manifest list for a given name. -func Inspect(ctx context.Context, name string) (*manifest.Schema2List, error) { +func Inspect(ctx context.Context, name string, options *InspectOptions) (*manifest.Schema2List, error) { var list manifest.Schema2List + if options == nil { + options = new(InspectOptions) + } + _ = options conn, err := bindings.GetClient(ctx) if err != nil { return nil, err @@ -62,8 +67,11 @@ func Inspect(ctx context.Context, name string) (*manifest.Schema2List, error) { // Add adds a manifest to a given manifest list. Additional options for the manifest // can also be specified. The ID of the new manifest list is returned as a string -func Add(ctx context.Context, name string, options image.ManifestAddOpts) (string, error) { +func Add(ctx context.Context, name string, options *AddOptions) (string, error) { var idr handlers.IDResponse + if options == nil { + options = new(AddOptions) + } conn, err := bindings.GetClient(ctx) if err != nil { return "", err @@ -82,8 +90,12 @@ func Add(ctx context.Context, name string, options image.ManifestAddOpts) (strin // 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) (string, error) { +func Remove(ctx context.Context, name, digest string, options *RemoveOptions) (string, error) { var idr handlers.IDResponse + if options == nil { + options = new(RemoveOptions) + } + _ = options conn, err := bindings.GetClient(ctx) if err != nil { return "", err @@ -100,24 +112,26 @@ func Remove(ctx context.Context, name, digest string) (string, error) { // 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 string, destination *string, all *bool) (string, error) { +func Push(ctx context.Context, name, destination string, options *PushOptions) (string, error) { var ( idr handlers.IDResponse ) - dest := name + if options == nil { + options = new(PushOptions) + } + if len(destination) < 1 { + destination = name + } conn, err := bindings.GetClient(ctx) if err != nil { return "", err } - params := url.Values{} - params.Set("image", name) - if destination != nil { - dest = *destination - } - params.Set("destination", dest) - if all != nil { - params.Set("all", strconv.FormatBool(*all)) + params, err := options.ToParams() + if err != nil { + return "", err } + params.Set("image", name) + params.Set("destination", destination) _, 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 new file mode 100644 index 000000000..f5054d424 --- /dev/null +++ b/pkg/bindings/manifests/types.go @@ -0,0 +1,36 @@ +package manifests + +//go:generate go run ../generator/generator.go InspectOptions +// InspectOptions are optional options for inspecting manifests +type InspectOptions struct { +} + +//go:generate go run ../generator/generator.go CreateOptions +// CreateOptions are optional options for creating manifests +type CreateOptions struct { + All *bool +} + +//go:generate go run ../generator/generator.go AddOptions +// AddOptions are optional options for adding manifests +type AddOptions struct { + All *bool + Annotation map[string]string + Arch *string + Features []string + Images []string + OS *string + OSVersion *string + Variant *string +} + +//go:generate go run ../generator/generator.go RemoveOptions +// 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_add_options.go b/pkg/bindings/manifests/types_add_options.go new file mode 100644 index 000000000..304779f6e --- /dev/null +++ b/pkg/bindings/manifests/types_add_options.go @@ -0,0 +1,216 @@ +package manifests + +import ( + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-16 11:58:59.192715649 -0600 CST m=+0.000150326 +*/ + +// Changed +func (o *AddOptions) Changed(fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +// ToParams +func (o *AddOptions) 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 *AddOptions) WithAll(value bool) *AddOptions { + v := &value + o.All = v + return o +} + +// GetAll +func (o *AddOptions) GetAll() bool { + var all bool + if o.All == nil { + return all + } + return *o.All +} + +// WithAnnotation +func (o *AddOptions) WithAnnotation(value map[string]string) *AddOptions { + v := value + o.Annotation = v + return o +} + +// GetAnnotation +func (o *AddOptions) GetAnnotation() map[string]string { + var annotation map[string]string + if o.Annotation == nil { + return annotation + } + return o.Annotation +} + +// WithArch +func (o *AddOptions) WithArch(value string) *AddOptions { + v := &value + o.Arch = v + return o +} + +// GetArch +func (o *AddOptions) GetArch() string { + var arch string + if o.Arch == nil { + return arch + } + return *o.Arch +} + +// WithFeatures +func (o *AddOptions) WithFeatures(value []string) *AddOptions { + v := value + o.Features = v + return o +} + +// GetFeatures +func (o *AddOptions) GetFeatures() []string { + var features []string + if o.Features == nil { + return features + } + return o.Features +} + +// WithImages +func (o *AddOptions) WithImages(value []string) *AddOptions { + v := value + o.Images = v + return o +} + +// GetImages +func (o *AddOptions) GetImages() []string { + var images []string + if o.Images == nil { + return images + } + return o.Images +} + +// WithOS +func (o *AddOptions) WithOS(value string) *AddOptions { + v := &value + o.OS = v + return o +} + +// GetOS +func (o *AddOptions) GetOS() string { + var oS string + if o.OS == nil { + return oS + } + return *o.OS +} + +// WithOSVersion +func (o *AddOptions) WithOSVersion(value string) *AddOptions { + v := &value + o.OSVersion = v + return o +} + +// GetOSVersion +func (o *AddOptions) GetOSVersion() string { + var oSVersion string + if o.OSVersion == nil { + return oSVersion + } + return *o.OSVersion +} + +// WithVariant +func (o *AddOptions) WithVariant(value string) *AddOptions { + v := &value + o.Variant = v + return o +} + +// GetVariant +func (o *AddOptions) GetVariant() string { + var variant string + if o.Variant == nil { + return variant + } + return *o.Variant +} diff --git a/pkg/bindings/manifests/types_create_options.go b/pkg/bindings/manifests/types_create_options.go new file mode 100644 index 000000000..6fccc08b6 --- /dev/null +++ b/pkg/bindings/manifests/types_create_options.go @@ -0,0 +1,104 @@ +package manifests + +import ( + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-16 11:58:59.053719568 -0600 CST m=+0.000144061 +*/ + +// Changed +func (o *CreateOptions) Changed(fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +// ToParams +func (o *CreateOptions) 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 *CreateOptions) WithAll(value bool) *CreateOptions { + v := &value + o.All = v + return o +} + +// GetAll +func (o *CreateOptions) GetAll() bool { + var all bool + if o.All == nil { + return all + } + return *o.All +} diff --git a/pkg/bindings/manifests/types_inspect_options.go b/pkg/bindings/manifests/types_inspect_options.go new file mode 100644 index 000000000..8cbcbf376 --- /dev/null +++ b/pkg/bindings/manifests/types_inspect_options.go @@ -0,0 +1,88 @@ +package manifests + +import ( + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-16 11:58:58.908440858 -0600 CST m=+0.000142730 +*/ + +// Changed +func (o *InspectOptions) Changed(fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +// ToParams +func (o *InspectOptions) 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 +} diff --git a/pkg/bindings/manifests/types_push_options.go b/pkg/bindings/manifests/types_push_options.go new file mode 100644 index 000000000..a56b29049 --- /dev/null +++ b/pkg/bindings/manifests/types_push_options.go @@ -0,0 +1,104 @@ +package manifests + +import ( + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-16 11:58:59.466796313 -0600 CST m=+0.000143189 +*/ + +// 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 +} diff --git a/pkg/bindings/manifests/types_remove_options.go b/pkg/bindings/manifests/types_remove_options.go new file mode 100644 index 000000000..4f8ca9e95 --- /dev/null +++ b/pkg/bindings/manifests/types_remove_options.go @@ -0,0 +1,88 @@ +package manifests + +import ( + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-16 11:58:59.33119706 -0600 CST m=+0.000143915 +*/ + +// Changed +func (o *RemoveOptions) Changed(fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +// ToParams +func (o *RemoveOptions) 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 +} diff --git a/pkg/bindings/network/network.go b/pkg/bindings/network/network.go index 347f97703..7cd251b0e 100644 --- a/pkg/bindings/network/network.go +++ b/pkg/bindings/network/network.go @@ -2,10 +2,8 @@ package network import ( "context" - "encoding/json" "net/http" "net/url" - "strconv" "strings" "github.com/containers/podman/v2/pkg/bindings" @@ -14,15 +12,18 @@ import ( ) // Create makes a new CNI network configuration -func Create(ctx context.Context, options entities.NetworkCreateOptions, name *string) (*entities.NetworkCreateReport, error) { +func Create(ctx context.Context, options *CreateOptions) (*entities.NetworkCreateReport, error) { var report entities.NetworkCreateReport + if options == nil { + options = new(CreateOptions) + } conn, err := bindings.GetClient(ctx) if err != nil { return nil, err } params := url.Values{} - if name != nil { - params.Set("name", *name) + if options.Name != nil { + params.Set("name", options.GetName()) } networkConfig, err := jsoniter.MarshalToString(options) if err != nil { @@ -37,8 +38,12 @@ func Create(ctx context.Context, options entities.NetworkCreateOptions, name *st } // Inspect returns low level information about a CNI network configuration -func Inspect(ctx context.Context, nameOrID string) ([]entities.NetworkInspectReport, error) { +func Inspect(ctx context.Context, nameOrID string, options *InspectOptions) ([]entities.NetworkInspectReport, error) { var reports []entities.NetworkInspectReport + if options == nil { + options = new(InspectOptions) + } + _ = options conn, err := bindings.GetClient(ctx) if err != nil { return nil, err @@ -53,15 +58,18 @@ func Inspect(ctx context.Context, nameOrID string) ([]entities.NetworkInspectRep // Remove deletes a defined CNI network configuration by name. The optional force boolean // will remove all containers associated with the network when set to true. A slice // of NetworkRemoveReports are returned. -func Remove(ctx context.Context, nameOrID string, force *bool) ([]*entities.NetworkRmReport, error) { +func Remove(ctx context.Context, nameOrID string, options *RemoveOptions) ([]*entities.NetworkRmReport, error) { var reports []*entities.NetworkRmReport + if options == nil { + options = new(RemoveOptions) + } conn, err := bindings.GetClient(ctx) if err != nil { return nil, err } - params := url.Values{} - if force != nil { - params.Set("force", strconv.FormatBool(*force)) + params, err := options.ToParams() + if err != nil { + return nil, err } response, err := conn.DoRequest(nil, http.MethodDelete, "/networks/%s", params, nil, nameOrID) if err != nil { @@ -71,21 +79,20 @@ func Remove(ctx context.Context, nameOrID string, force *bool) ([]*entities.Netw } // List returns a summary of all CNI network configurations -func List(ctx context.Context, options entities.NetworkListOptions) ([]*entities.NetworkListReport, error) { +func List(ctx context.Context, options *ListOptions) ([]*entities.NetworkListReport, error) { var ( netList []*entities.NetworkListReport ) + if options == nil { + options = new(ListOptions) + } conn, err := bindings.GetClient(ctx) if err != nil { return nil, err } - params := url.Values{} - if options.Filters != nil { - b, err := json.Marshal(options.Filters) - if err != nil { - return nil, err - } - params.Set("filters", string(b)) + params, err := options.ToParams() + if err != nil { + return nil, err } response, err := conn.DoRequest(nil, http.MethodGet, "/networks/json", params, nil) if err != nil { @@ -95,13 +102,28 @@ func List(ctx context.Context, options entities.NetworkListOptions) ([]*entities } // Disconnect removes a container from a given network -func Disconnect(ctx context.Context, networkName string, options entities.NetworkDisconnectOptions) error { +func Disconnect(ctx context.Context, networkName string, ContainerNameOrId string, options *DisconnectOptions) error { + if options == nil { + options = new(DisconnectOptions) + } conn, err := bindings.GetClient(ctx) if err != nil { return err } + // No params are used for disconnect params := url.Values{} - body, err := jsoniter.MarshalToString(options) + // Disconnect sends everything in body + disconnect := struct { + Container string + Force bool + }{ + Container: ContainerNameOrId, + } + if force := options.GetForce(); options.Changed("Force") { + disconnect.Force = force + } + + body, err := jsoniter.MarshalToString(disconnect) if err != nil { return err } @@ -114,13 +136,27 @@ func Disconnect(ctx context.Context, networkName string, options entities.Networ } // Connect adds a container to a network -func Connect(ctx context.Context, networkName string, options entities.NetworkConnectOptions) error { +func Connect(ctx context.Context, networkName string, ContainerNameOrId string, options *ConnectOptions) error { + if options == nil { + options = new(ConnectOptions) + } conn, err := bindings.GetClient(ctx) if err != nil { return err } + // No params are used in connect params := url.Values{} - body, err := jsoniter.MarshalToString(options) + // Connect sends everything in body + connect := struct { + Container string + Aliases []string + }{ + Container: ContainerNameOrId, + } + if aliases := options.GetAliases(); options.Changed("Aliases") { + connect.Aliases = aliases + } + body, err := jsoniter.MarshalToString(connect) if err != nil { return err } diff --git a/pkg/bindings/network/types.go b/pkg/bindings/network/types.go new file mode 100644 index 000000000..2a7e500dd --- /dev/null +++ b/pkg/bindings/network/types.go @@ -0,0 +1,70 @@ +package network + +import "net" + +//go:generate go run ../generator/generator.go CreateOptions +// CreateOptions are optional options for creating networks +type CreateOptions struct { + // DisableDNS turns off use of DNSMasq for name resolution + // on the network + DisableDNS *bool + // Driver is the name of network driver + Driver *string + // Gateway of the network + Gateway *net.IP + // Internal turns off communication outside the networking + // being created + Internal *bool + // Labels are metadata that can be associated with the network + Labels map[string]string + // MacVLAN is the name of the macvlan network to associate with + MacVLAN *string + // Range is the CIDR description of leasable IP addresses + IPRange *net.IPNet `scheme:"range"` + // Subnet to use + Subnet *net.IPNet + // IPv6 means the network is ipv6 capable + IPv6 *bool + // Options are a mapping of driver options and values. + Options map[string]string + // Name of the network + Name *string +} + +//go:generate go run ../generator/generator.go InspectOptions +// InspectOptions are optional options for inspecting networks +type InspectOptions struct { +} + +//go:generate go run ../generator/generator.go RemoveOptions +// RemoveOptions are optional options for inspecting networks +type RemoveOptions struct { + // Force removes the network even if it is being used + Force *bool +} + +//go:generate go run ../generator/generator.go ListOptions +// ListOptions are optional options for listing networks +type ListOptions struct { + // Filters are applied to the list of networks to be more + // specific on the output + Filters map[string][]string +} + +//go:generate go run ../generator/generator.go DisconnectOptions +// DisconnectOptions are optional options for disconnecting +// containers from a network +type DisconnectOptions struct { + // Force indicates to remove the container from + // the network forcibly + Force *bool +} + +//go:generate go run ../generator/generator.go ConnectOptions +// ConnectOptions are optional options for connecting +// containers from a network +type ConnectOptions struct { + // Aliases are names the container will be known as + // when using the dns plugin + Aliases *[]string +} diff --git a/pkg/bindings/network/types_connect_options.go b/pkg/bindings/network/types_connect_options.go new file mode 100644 index 000000000..22d1905e4 --- /dev/null +++ b/pkg/bindings/network/types_connect_options.go @@ -0,0 +1,104 @@ +package network + +import ( + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-16 11:59:06.213411549 -0600 CST m=+0.000201795 +*/ + +// Changed +func (o *ConnectOptions) Changed(fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +// ToParams +func (o *ConnectOptions) 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 +} + +// WithAliases +func (o *ConnectOptions) WithAliases(value []string) *ConnectOptions { + v := &value + o.Aliases = v + return o +} + +// GetAliases +func (o *ConnectOptions) GetAliases() []string { + var aliases []string + if o.Aliases == nil { + return aliases + } + return *o.Aliases +} diff --git a/pkg/bindings/network/types_create_options.go b/pkg/bindings/network/types_create_options.go new file mode 100644 index 000000000..6af7929c4 --- /dev/null +++ b/pkg/bindings/network/types_create_options.go @@ -0,0 +1,265 @@ +package network + +import ( + "net" + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-16 11:59:05.523424301 -0600 CST m=+0.000180953 +*/ + +// Changed +func (o *CreateOptions) Changed(fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +// ToParams +func (o *CreateOptions) 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 +} + +// WithDisableDNS +func (o *CreateOptions) WithDisableDNS(value bool) *CreateOptions { + v := &value + o.DisableDNS = v + return o +} + +// GetDisableDNS +func (o *CreateOptions) GetDisableDNS() bool { + var disableDNS bool + if o.DisableDNS == nil { + return disableDNS + } + return *o.DisableDNS +} + +// WithDriver +func (o *CreateOptions) WithDriver(value string) *CreateOptions { + v := &value + o.Driver = v + return o +} + +// GetDriver +func (o *CreateOptions) GetDriver() string { + var driver string + if o.Driver == nil { + return driver + } + return *o.Driver +} + +// WithGateway +func (o *CreateOptions) WithGateway(value net.IP) *CreateOptions { + v := &value + o.Gateway = v + return o +} + +// GetGateway +func (o *CreateOptions) GetGateway() net.IP { + var gateway net.IP + if o.Gateway == nil { + return gateway + } + return *o.Gateway +} + +// WithInternal +func (o *CreateOptions) WithInternal(value bool) *CreateOptions { + v := &value + o.Internal = v + return o +} + +// GetInternal +func (o *CreateOptions) GetInternal() bool { + var internal bool + if o.Internal == nil { + return internal + } + return *o.Internal +} + +// WithLabels +func (o *CreateOptions) WithLabels(value map[string]string) *CreateOptions { + v := value + o.Labels = v + return o +} + +// GetLabels +func (o *CreateOptions) GetLabels() map[string]string { + var labels map[string]string + if o.Labels == nil { + return labels + } + return o.Labels +} + +// WithMacVLAN +func (o *CreateOptions) WithMacVLAN(value string) *CreateOptions { + v := &value + o.MacVLAN = v + return o +} + +// GetMacVLAN +func (o *CreateOptions) GetMacVLAN() string { + var macVLAN string + if o.MacVLAN == nil { + return macVLAN + } + return *o.MacVLAN +} + +// WithIPRange +func (o *CreateOptions) WithIPRange(value net.IPNet) *CreateOptions { + v := &value + o.IPRange = v + return o +} + +// GetIPRange +func (o *CreateOptions) GetIPRange() net.IPNet { + var iPRange net.IPNet + if o.IPRange == nil { + return iPRange + } + return *o.IPRange +} + +// WithSubnet +func (o *CreateOptions) WithSubnet(value net.IPNet) *CreateOptions { + v := &value + o.Subnet = v + return o +} + +// GetSubnet +func (o *CreateOptions) GetSubnet() net.IPNet { + var subnet net.IPNet + if o.Subnet == nil { + return subnet + } + return *o.Subnet +} + +// WithIPv6 +func (o *CreateOptions) WithIPv6(value bool) *CreateOptions { + v := &value + o.IPv6 = v + return o +} + +// GetIPv6 +func (o *CreateOptions) GetIPv6() bool { + var iPv6 bool + if o.IPv6 == nil { + return iPv6 + } + return *o.IPv6 +} + +// WithOptions +func (o *CreateOptions) WithOptions(value map[string]string) *CreateOptions { + v := value + o.Options = v + return o +} + +// GetOptions +func (o *CreateOptions) GetOptions() map[string]string { + var options map[string]string + if o.Options == nil { + return options + } + return o.Options +} + +// WithName +func (o *CreateOptions) WithName(value string) *CreateOptions { + v := &value + o.Name = v + return o +} + +// GetName +func (o *CreateOptions) GetName() string { + var name string + if o.Name == nil { + return name + } + return *o.Name +} diff --git a/pkg/bindings/network/types_disconnect_options.go b/pkg/bindings/network/types_disconnect_options.go new file mode 100644 index 000000000..183032998 --- /dev/null +++ b/pkg/bindings/network/types_disconnect_options.go @@ -0,0 +1,104 @@ +package network + +import ( + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-16 11:59:06.07634068 -0600 CST m=+0.000179587 +*/ + +// Changed +func (o *DisconnectOptions) Changed(fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +// ToParams +func (o *DisconnectOptions) 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 +} + +// WithForce +func (o *DisconnectOptions) WithForce(value bool) *DisconnectOptions { + v := &value + o.Force = v + return o +} + +// GetForce +func (o *DisconnectOptions) GetForce() bool { + var force bool + if o.Force == nil { + return force + } + return *o.Force +} diff --git a/pkg/bindings/network/types_inspect_options.go b/pkg/bindings/network/types_inspect_options.go new file mode 100644 index 000000000..91adac8f4 --- /dev/null +++ b/pkg/bindings/network/types_inspect_options.go @@ -0,0 +1,88 @@ +package network + +import ( + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-16 11:59:05.661597872 -0600 CST m=+0.000168252 +*/ + +// Changed +func (o *InspectOptions) Changed(fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +// ToParams +func (o *InspectOptions) 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 +} diff --git a/pkg/bindings/network/types_list_options.go b/pkg/bindings/network/types_list_options.go new file mode 100644 index 000000000..3f1909ee1 --- /dev/null +++ b/pkg/bindings/network/types_list_options.go @@ -0,0 +1,104 @@ +package network + +import ( + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-16 11:59:05.936262707 -0600 CST m=+0.000172058 +*/ + +// Changed +func (o *ListOptions) Changed(fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +// ToParams +func (o *ListOptions) 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 +} + +// WithFilters +func (o *ListOptions) WithFilters(value map[string][]string) *ListOptions { + v := value + o.Filters = v + return o +} + +// GetFilters +func (o *ListOptions) GetFilters() map[string][]string { + var filters map[string][]string + if o.Filters == nil { + return filters + } + return o.Filters +} diff --git a/pkg/bindings/network/types_remove_options.go b/pkg/bindings/network/types_remove_options.go new file mode 100644 index 000000000..5f3dc70ec --- /dev/null +++ b/pkg/bindings/network/types_remove_options.go @@ -0,0 +1,104 @@ +package network + +import ( + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-16 11:59:05.798818224 -0600 CST m=+0.000173420 +*/ + +// Changed +func (o *RemoveOptions) Changed(fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +// ToParams +func (o *RemoveOptions) 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 +} + +// WithForce +func (o *RemoveOptions) WithForce(value bool) *RemoveOptions { + v := &value + o.Force = v + return o +} + +// GetForce +func (o *RemoveOptions) GetForce() bool { + var force bool + if o.Force == nil { + return force + } + return *o.Force +} diff --git a/pkg/bindings/play/play.go b/pkg/bindings/play/play.go index cfb40d74b..9ee02a093 100644 --- a/pkg/bindings/play/play.go +++ b/pkg/bindings/play/play.go @@ -3,18 +3,19 @@ package play import ( "context" "net/http" - "net/url" "os" "strconv" - "github.com/containers/image/v5/types" "github.com/containers/podman/v2/pkg/auth" "github.com/containers/podman/v2/pkg/bindings" "github.com/containers/podman/v2/pkg/domain/entities" ) -func Kube(ctx context.Context, path string, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) { +func Kube(ctx context.Context, path string, options *KubeOptions) (*entities.PlayKubeReport, error) { var report entities.PlayKubeReport + if options == nil { + options = new(KubeOptions) + } conn, err := bindings.GetClient(ctx) if err != nil { return nil, err @@ -26,18 +27,19 @@ func Kube(ctx context.Context, path string, options entities.PlayKubeOptions) (* } defer f.Close() - params := url.Values{} - params.Set("network", options.Network) - params.Set("logDriver", options.LogDriver) - if options.SkipTLSVerify != types.OptionalBoolUndefined { - params.Set("tlsVerify", strconv.FormatBool(options.SkipTLSVerify != types.OptionalBoolTrue)) + params, err := options.ToParams() + if err != nil { + return nil, err + } + if options.SkipTLSVerify != nil { + params.Set("tlsVerify", strconv.FormatBool(options.GetSkipTLSVerify())) } - if options.Start != types.OptionalBoolUndefined { - params.Set("start", strconv.FormatBool(options.Start == types.OptionalBoolTrue)) + if options.Start != nil { + params.Set("start", strconv.FormatBool(options.GetStart())) } // TODO: have a global system context we can pass around (1st argument) - header, err := auth.Header(nil, auth.XRegistryAuthHeader, options.Authfile, options.Username, options.Password) + header, err := auth.Header(nil, auth.XRegistryAuthHeader, options.GetAuthfile(), options.GetUsername(), options.GetPassword()) if err != nil { return nil, err } diff --git a/pkg/bindings/play/types.go b/pkg/bindings/play/types.go new file mode 100644 index 000000000..5fb9a4d41 --- /dev/null +++ b/pkg/bindings/play/types.go @@ -0,0 +1,32 @@ +package play + +//go:generate go run ../generator/generator.go KubeOptions +// KubeOptions are optional options for replaying kube YAML files +type KubeOptions struct { + // Authfile - path to an authentication file. + Authfile *string + // CertDir - to a directory containing TLS certifications and keys. + CertDir *string + // Username for authenticating against the registry. + Username *string + // Password for authenticating against the registry. + Password *string + // Network - name of the CNI network to connect to. + Network *string + // Quiet - suppress output when pulling images. + Quiet *bool + // SignaturePolicy - path to a signature-policy file. + SignaturePolicy *string + // SkipTLSVerify - skip https and certificate validation when + // contacting container registries. + SkipTLSVerify *bool + // SeccompProfileRoot - path to a directory containing seccomp + // profiles. + SeccompProfileRoot *string + // ConfigMaps - slice of pathnames to kubernetes configmap YAMLs. + ConfigMaps *[]string + // LogDriver for the container. For example: journald + LogDriver *string + // Start - don't start the pod if false + Start *bool +} diff --git a/pkg/bindings/play/types_kube_options.go b/pkg/bindings/play/types_kube_options.go new file mode 100644 index 000000000..29a5fc9b1 --- /dev/null +++ b/pkg/bindings/play/types_kube_options.go @@ -0,0 +1,280 @@ +package play + +import ( + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-16 11:59:11.20490387 -0600 CST m=+0.000181859 +*/ + +// Changed +func (o *KubeOptions) Changed(fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +// ToParams +func (o *KubeOptions) 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 +} + +// WithAuthfile +func (o *KubeOptions) WithAuthfile(value string) *KubeOptions { + v := &value + o.Authfile = v + return o +} + +// GetAuthfile +func (o *KubeOptions) GetAuthfile() string { + var authfile string + if o.Authfile == nil { + return authfile + } + return *o.Authfile +} + +// WithCertDir +func (o *KubeOptions) WithCertDir(value string) *KubeOptions { + v := &value + o.CertDir = v + return o +} + +// GetCertDir +func (o *KubeOptions) GetCertDir() string { + var certDir string + if o.CertDir == nil { + return certDir + } + return *o.CertDir +} + +// WithUsername +func (o *KubeOptions) WithUsername(value string) *KubeOptions { + v := &value + o.Username = v + return o +} + +// GetUsername +func (o *KubeOptions) GetUsername() string { + var username string + if o.Username == nil { + return username + } + return *o.Username +} + +// WithPassword +func (o *KubeOptions) WithPassword(value string) *KubeOptions { + v := &value + o.Password = v + return o +} + +// GetPassword +func (o *KubeOptions) GetPassword() string { + var password string + if o.Password == nil { + return password + } + return *o.Password +} + +// WithNetwork +func (o *KubeOptions) WithNetwork(value string) *KubeOptions { + v := &value + o.Network = v + return o +} + +// GetNetwork +func (o *KubeOptions) GetNetwork() string { + var network string + if o.Network == nil { + return network + } + return *o.Network +} + +// WithQuiet +func (o *KubeOptions) WithQuiet(value bool) *KubeOptions { + v := &value + o.Quiet = v + return o +} + +// GetQuiet +func (o *KubeOptions) GetQuiet() bool { + var quiet bool + if o.Quiet == nil { + return quiet + } + return *o.Quiet +} + +// WithSignaturePolicy +func (o *KubeOptions) WithSignaturePolicy(value string) *KubeOptions { + v := &value + o.SignaturePolicy = v + return o +} + +// GetSignaturePolicy +func (o *KubeOptions) GetSignaturePolicy() string { + var signaturePolicy string + if o.SignaturePolicy == nil { + return signaturePolicy + } + return *o.SignaturePolicy +} + +// WithSkipTLSVerify +func (o *KubeOptions) WithSkipTLSVerify(value bool) *KubeOptions { + v := &value + o.SkipTLSVerify = v + return o +} + +// GetSkipTLSVerify +func (o *KubeOptions) GetSkipTLSVerify() bool { + var skipTLSVerify bool + if o.SkipTLSVerify == nil { + return skipTLSVerify + } + return *o.SkipTLSVerify +} + +// WithSeccompProfileRoot +func (o *KubeOptions) WithSeccompProfileRoot(value string) *KubeOptions { + v := &value + o.SeccompProfileRoot = v + return o +} + +// GetSeccompProfileRoot +func (o *KubeOptions) GetSeccompProfileRoot() string { + var seccompProfileRoot string + if o.SeccompProfileRoot == nil { + return seccompProfileRoot + } + return *o.SeccompProfileRoot +} + +// WithConfigMaps +func (o *KubeOptions) WithConfigMaps(value []string) *KubeOptions { + v := &value + o.ConfigMaps = v + return o +} + +// GetConfigMaps +func (o *KubeOptions) GetConfigMaps() []string { + var configMaps []string + if o.ConfigMaps == nil { + return configMaps + } + return *o.ConfigMaps +} + +// WithLogDriver +func (o *KubeOptions) WithLogDriver(value string) *KubeOptions { + v := &value + o.LogDriver = v + return o +} + +// GetLogDriver +func (o *KubeOptions) GetLogDriver() string { + var logDriver string + if o.LogDriver == nil { + return logDriver + } + return *o.LogDriver +} + +// WithStart +func (o *KubeOptions) WithStart(value bool) *KubeOptions { + v := &value + o.Start = v + return o +} + +// GetStart +func (o *KubeOptions) GetStart() bool { + var start bool + if o.Start == nil { + return start + } + return *o.Start +} diff --git a/pkg/bindings/system/info.go b/pkg/bindings/system/info.go index 79ee5cada..798010333 100644 --- a/pkg/bindings/system/info.go +++ b/pkg/bindings/system/info.go @@ -9,7 +9,11 @@ import ( ) // Info returns information about the libpod environment and its stores -func Info(ctx context.Context) (*define.Info, error) { +func Info(ctx context.Context, options *InfoOptions) (*define.Info, error) { + if options == nil { + options = new(InfoOptions) + } + _ = options info := define.Info{} conn, err := bindings.GetClient(ctx) if err != nil { diff --git a/pkg/bindings/system/system.go b/pkg/bindings/system/system.go index 1203f5c3c..815c967f1 100644 --- a/pkg/bindings/system/system.go +++ b/pkg/bindings/system/system.go @@ -6,8 +6,6 @@ import ( "fmt" "io" "net/http" - "net/url" - "strconv" "time" "github.com/containers/podman/v2/libpod/define" @@ -20,27 +18,14 @@ import ( // Events allows you to monitor libdpod related events like container creation and // removal. The events are then passed to the eventChan provided. The optional cancelChan // can be used to cancel the read of events and close down the HTTP connection. -func Events(ctx context.Context, eventChan chan entities.Event, cancelChan chan bool, since, until *string, filters map[string][]string, stream *bool) error { +func Events(ctx context.Context, eventChan chan entities.Event, cancelChan chan bool, options *EventsOptions) error { conn, err := bindings.GetClient(ctx) if err != nil { return err } - params := url.Values{} - if since != nil { - params.Set("since", *since) - } - if until != nil { - params.Set("until", *until) - } - if stream != nil { - params.Set("stream", strconv.FormatBool(*stream)) - } - if filters != nil { - filterString, err := bindings.FiltersToString(filters) - if err != nil { - return errors.Wrap(err, "invalid filters") - } - params.Set("filters", filterString) + params, err := options.ToParams() + if err != nil { + return err } response, err := conn.DoRequest(nil, http.MethodGet, "/events", params, nil) if err != nil { @@ -74,7 +59,7 @@ func Events(ctx context.Context, eventChan chan entities.Event, cancelChan chan } // Prune removes all unused system data. -func Prune(ctx context.Context, all, volumes *bool) (*entities.SystemPruneReport, error) { +func Prune(ctx context.Context, options *PruneOptions) (*entities.SystemPruneReport, error) { var ( report entities.SystemPruneReport ) @@ -82,12 +67,9 @@ func Prune(ctx context.Context, all, volumes *bool) (*entities.SystemPruneReport if err != nil { return nil, err } - params := url.Values{} - if all != nil { - params.Set("All", strconv.FormatBool(*all)) - } - if volumes != nil { - params.Set("Volumes", strconv.FormatBool(*volumes)) + params, err := options.ToParams() + if err != nil { + return nil, err } response, err := conn.DoRequest(nil, http.MethodPost, "/system/prune", params, nil) if err != nil { @@ -96,10 +78,15 @@ func Prune(ctx context.Context, all, volumes *bool) (*entities.SystemPruneReport return &report, response.Process(&report) } -func Version(ctx context.Context) (*entities.SystemVersionReport, error) { - var report entities.SystemVersionReport - var component entities.ComponentVersion - +func Version(ctx context.Context, options *VersionOptions) (*entities.SystemVersionReport, error) { + var ( + component entities.ComponentVersion + report entities.SystemVersionReport + ) + if options == nil { + options = new(VersionOptions) + } + _ = options version, err := define.GetVersion() if err != nil { return nil, err @@ -140,8 +127,12 @@ func Version(ctx context.Context) (*entities.SystemVersionReport, error) { // DiskUsage returns information about image, container, and volume disk // consumption -func DiskUsage(ctx context.Context) (*entities.SystemDfReport, error) { +func DiskUsage(ctx context.Context, options *DiskOptions) (*entities.SystemDfReport, error) { var report entities.SystemDfReport + if options == nil { + options = new(DiskOptions) + } + _ = options conn, err := bindings.GetClient(ctx) if err != nil { return nil, err diff --git a/pkg/bindings/system/types.go b/pkg/bindings/system/types.go new file mode 100644 index 000000000..16960b817 --- /dev/null +++ b/pkg/bindings/system/types.go @@ -0,0 +1,34 @@ +package system + +//go:generate go run ../generator/generator.go EventsOptions +// EventsOptions are optional options for monitoring events +type EventsOptions struct { + Filters map[string][]string + Since *string + Stream *bool + Until *string +} + +//go:generate go run ../generator/generator.go PruneOptions +// PruneOptions are optional options for pruning +type PruneOptions struct { + All *bool + Filters map[string][]string + Volumes *bool +} + +//go:generate go run ../generator/generator.go VersionOptions +// VersionOptions are optional options for getting version info +type VersionOptions struct { +} + +//go:generate go run ../generator/generator.go DiskOptions +// DiskOptions are optional options for getting storage consumption +type DiskOptions struct { +} + +//go:generate go run ../generator/generator.go InfoOptions +// InfoOptions are optional options for getting info +// about libpod +type InfoOptions struct { +} diff --git a/pkg/bindings/system/types_disk_options.go b/pkg/bindings/system/types_disk_options.go new file mode 100644 index 000000000..2336db19b --- /dev/null +++ b/pkg/bindings/system/types_disk_options.go @@ -0,0 +1,88 @@ +package system + +import ( + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-17 09:13:10.734962166 -0600 CST m=+0.000145336 +*/ + +// Changed +func (o *DiskOptions) Changed(fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +// ToParams +func (o *DiskOptions) 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 +} diff --git a/pkg/bindings/system/types_events_options.go b/pkg/bindings/system/types_events_options.go new file mode 100644 index 000000000..cb4c5eb0e --- /dev/null +++ b/pkg/bindings/system/types_events_options.go @@ -0,0 +1,152 @@ +package system + +import ( + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-17 09:13:10.308724359 -0600 CST m=+0.000145204 +*/ + +// Changed +func (o *EventsOptions) Changed(fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +// ToParams +func (o *EventsOptions) 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 +} + +// WithFilters +func (o *EventsOptions) WithFilters(value map[string][]string) *EventsOptions { + v := value + o.Filters = v + return o +} + +// GetFilters +func (o *EventsOptions) GetFilters() map[string][]string { + var filters map[string][]string + if o.Filters == nil { + return filters + } + return o.Filters +} + +// WithSince +func (o *EventsOptions) WithSince(value string) *EventsOptions { + v := &value + o.Since = v + return o +} + +// GetSince +func (o *EventsOptions) GetSince() string { + var since string + if o.Since == nil { + return since + } + return *o.Since +} + +// WithStream +func (o *EventsOptions) WithStream(value bool) *EventsOptions { + v := &value + o.Stream = v + return o +} + +// GetStream +func (o *EventsOptions) GetStream() bool { + var stream bool + if o.Stream == nil { + return stream + } + return *o.Stream +} + +// WithUntil +func (o *EventsOptions) WithUntil(value string) *EventsOptions { + v := &value + o.Until = v + return o +} + +// GetUntil +func (o *EventsOptions) GetUntil() string { + var until string + if o.Until == nil { + return until + } + return *o.Until +} diff --git a/pkg/bindings/system/types_info_options.go b/pkg/bindings/system/types_info_options.go new file mode 100644 index 000000000..7614e084c --- /dev/null +++ b/pkg/bindings/system/types_info_options.go @@ -0,0 +1,88 @@ +package system + +import ( + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-17 09:13:10.872420889 -0600 CST m=+0.000136023 +*/ + +// Changed +func (o *InfoOptions) Changed(fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +// ToParams +func (o *InfoOptions) 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 +} diff --git a/pkg/bindings/system/types_prune_options.go b/pkg/bindings/system/types_prune_options.go new file mode 100644 index 000000000..6a1e38333 --- /dev/null +++ b/pkg/bindings/system/types_prune_options.go @@ -0,0 +1,136 @@ +package system + +import ( + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-17 09:13:10.456894557 -0600 CST m=+0.000141897 +*/ + +// Changed +func (o *PruneOptions) Changed(fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +// ToParams +func (o *PruneOptions) 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 *PruneOptions) WithAll(value bool) *PruneOptions { + v := &value + o.All = v + return o +} + +// GetAll +func (o *PruneOptions) GetAll() bool { + var all bool + if o.All == nil { + return all + } + return *o.All +} + +// WithFilters +func (o *PruneOptions) WithFilters(value map[string][]string) *PruneOptions { + v := value + o.Filters = v + return o +} + +// GetFilters +func (o *PruneOptions) GetFilters() map[string][]string { + var filters map[string][]string + if o.Filters == nil { + return filters + } + return o.Filters +} + +// WithVolumes +func (o *PruneOptions) WithVolumes(value bool) *PruneOptions { + v := &value + o.Volumes = v + return o +} + +// GetVolumes +func (o *PruneOptions) GetVolumes() bool { + var volumes bool + if o.Volumes == nil { + return volumes + } + return *o.Volumes +} diff --git a/pkg/bindings/system/types_version_options.go b/pkg/bindings/system/types_version_options.go new file mode 100644 index 000000000..fbe29f07c --- /dev/null +++ b/pkg/bindings/system/types_version_options.go @@ -0,0 +1,88 @@ +package system + +import ( + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-17 09:13:10.596882708 -0600 CST m=+0.000141540 +*/ + +// Changed +func (o *VersionOptions) Changed(fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +// ToParams +func (o *VersionOptions) 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 +} diff --git a/pkg/bindings/test/info_test.go b/pkg/bindings/test/info_test.go index 735de25b8..c4473cd19 100644 --- a/pkg/bindings/test/info_test.go +++ b/pkg/bindings/test/info_test.go @@ -34,7 +34,7 @@ var _ = Describe("Podman info", func() { }) It("podman info", func() { - info, err := system.Info(bt.conn) + info, err := system.Info(bt.conn, nil) Expect(err).To(BeNil()) Expect(info.Host.Arch).To(Equal(runtime.GOARCH)) Expect(info.Host.OS).To(Equal(runtime.GOOS)) @@ -62,7 +62,7 @@ var _ = Describe("Podman info", func() { _, err = bt.RunTopContainer(nil, nil, nil) Expect(err).To(BeNil()) - info, err := system.Info(bt.conn) + info, err := system.Info(bt.conn, nil) Expect(err).To(BeNil()) Expect(info.Store.ContainerStore.Number).To(BeNumerically("==", 4)) diff --git a/pkg/bindings/test/manifests_test.go b/pkg/bindings/test/manifests_test.go index 421004b8c..b93f64b4b 100644 --- a/pkg/bindings/test/manifests_test.go +++ b/pkg/bindings/test/manifests_test.go @@ -4,7 +4,6 @@ import ( "net/http" "time" - "github.com/containers/podman/v2/libpod/image" "github.com/containers/podman/v2/pkg/bindings" "github.com/containers/podman/v2/pkg/bindings/images" "github.com/containers/podman/v2/pkg/bindings/manifests" @@ -37,7 +36,7 @@ var _ = Describe("Podman containers ", func() { // create manifest list without images id, err := manifests.Create(bt.conn, []string{"quay.io/libpod/foobar:latest"}, []string{}, nil) Expect(err).To(BeNil()) - list, err := manifests.Inspect(bt.conn, id) + list, err := manifests.Inspect(bt.conn, id, nil) Expect(err).To(BeNil()) Expect(len(list.Manifests)).To(BeZero()) @@ -53,13 +52,13 @@ var _ = Describe("Podman containers ", func() { // create manifest list with images id, err = manifests.Create(bt.conn, []string{"quay.io/libpod/foobar:latest"}, []string{alpine.name}, nil) Expect(err).To(BeNil()) - list, err = manifests.Inspect(bt.conn, id) + list, err = manifests.Inspect(bt.conn, id, nil) Expect(err).To(BeNil()) Expect(len(list.Manifests)).To(BeNumerically("==", 1)) }) It("inspect bogus manifest", func() { - _, err := manifests.Inspect(bt.conn, "larry") + _, err := manifests.Inspect(bt.conn, "larry", nil) Expect(err).ToNot(BeNil()) code, _ := bindings.CheckResponseCode(err) Expect(code).To(BeNumerically("==", http.StatusNotFound)) @@ -67,23 +66,23 @@ var _ = Describe("Podman containers ", func() { It("add manifest", func() { // add to bogus should 404 - _, err := manifests.Add(bt.conn, "foobar", image.ManifestAddOpts{}) + _, err := manifests.Add(bt.conn, "foobar", nil) Expect(err).ToNot(BeNil()) code, _ := bindings.CheckResponseCode(err) Expect(code).To(BeNumerically("==", http.StatusNotFound)) id, err := manifests.Create(bt.conn, []string{"quay.io/libpod/foobar:latest"}, []string{}, nil) Expect(err).To(BeNil()) - opts := image.ManifestAddOpts{Images: []string{alpine.name}} - _, err = manifests.Add(bt.conn, id, opts) + options := new(manifests.AddOptions).WithImages([]string{alpine.name}) + _, err = manifests.Add(bt.conn, id, options) Expect(err).To(BeNil()) - list, err := manifests.Inspect(bt.conn, id) + list, err := manifests.Inspect(bt.conn, id, nil) Expect(err).To(BeNil()) Expect(len(list.Manifests)).To(BeNumerically("==", 1)) // add bogus name to existing list should fail - opts.Images = []string{"larry"} - _, err = manifests.Add(bt.conn, id, opts) + options.WithImages([]string{"larry"}) + _, err = manifests.Add(bt.conn, id, options) Expect(err).ToNot(BeNil()) code, _ = bindings.CheckResponseCode(err) Expect(code).To(BeNumerically("==", http.StatusInternalServerError)) @@ -91,29 +90,29 @@ var _ = Describe("Podman containers ", func() { It("remove manifest", func() { // removal on bogus manifest list should be 404 - _, err := manifests.Remove(bt.conn, "larry", "1234") + _, err := manifests.Remove(bt.conn, "larry", "1234", nil) Expect(err).ToNot(BeNil()) code, _ := bindings.CheckResponseCode(err) Expect(code).To(BeNumerically("==", http.StatusNotFound)) id, err := manifests.Create(bt.conn, []string{"quay.io/libpod/foobar:latest"}, []string{alpine.name}, nil) Expect(err).To(BeNil()) - data, err := manifests.Inspect(bt.conn, id) + data, err := manifests.Inspect(bt.conn, id, nil) Expect(err).To(BeNil()) Expect(len(data.Manifests)).To(BeNumerically("==", 1)) // removal on a good manifest list with a bad digest should be 400 - _, err = manifests.Remove(bt.conn, id, "!234") + _, err = manifests.Remove(bt.conn, id, "!234", nil) Expect(err).ToNot(BeNil()) code, _ = bindings.CheckResponseCode(err) Expect(code).To(BeNumerically("==", http.StatusBadRequest)) digest := data.Manifests[0].Digest.String() - _, err = manifests.Remove(bt.conn, id, digest) + _, err = manifests.Remove(bt.conn, id, digest, nil) Expect(err).To(BeNil()) // removal on good manifest with good digest should work - data, err = manifests.Inspect(bt.conn, id) + data, err = manifests.Inspect(bt.conn, id, nil) Expect(err).To(BeNil()) Expect(len(data.Manifests)).To(BeZero()) }) diff --git a/pkg/bindings/test/system_test.go b/pkg/bindings/test/system_test.go index 82e5c7541..8a8c94d09 100644 --- a/pkg/bindings/test/system_test.go +++ b/pkg/bindings/test/system_test.go @@ -56,8 +56,8 @@ var _ = Describe("Podman system", func() { eventCounter++ } }() - - err = system.Events(bt.conn, binChan, nil, nil, nil, filters, bindings.PFalse) + options := new(system.EventsOptions).WithFilters(filters).WithStream(false) + err = system.Events(bt.conn, binChan, nil, options) Expect(err).To(BeNil()) done.Lock() Expect(eventCounter).To(BeNumerically(">", 0)) @@ -76,7 +76,8 @@ var _ = Describe("Podman system", func() { err = containers.Stop(bt.conn, name, nil) Expect(err).To(BeNil()) - systemPruneResponse, err := system.Prune(bt.conn, bindings.PTrue, bindings.PFalse) + options := new(system.PruneOptions).WithAll(true) + systemPruneResponse, err := system.Prune(bt.conn, options) Expect(err).To(BeNil()) Expect(len(systemPruneResponse.PodPruneReport)).To(Equal(1)) Expect(len(systemPruneResponse.ContainerPruneReport.ID)).To(Equal(1)) @@ -107,10 +108,10 @@ var _ = Describe("Podman system", func() { Expect(err).To(BeNil()) // Adding an unused volume - _, err = volumes.Create(bt.conn, entities.VolumeCreateOptions{}) + _, err = volumes.Create(bt.conn, entities.VolumeCreateOptions{}, nil) Expect(err).To(BeNil()) - - systemPruneResponse, err := system.Prune(bt.conn, bindings.PTrue, bindings.PFalse) + options := new(system.PruneOptions).WithAll(true) + systemPruneResponse, err := system.Prune(bt.conn, options) Expect(err).To(BeNil()) Expect(len(systemPruneResponse.PodPruneReport)).To(Equal(1)) Expect(len(systemPruneResponse.ContainerPruneReport.ID)).To(Equal(1)) @@ -141,10 +142,11 @@ var _ = Describe("Podman system", func() { Expect(err).To(BeNil()) // Adding an unused volume should work - _, err = volumes.Create(bt.conn, entities.VolumeCreateOptions{}) + _, err = volumes.Create(bt.conn, entities.VolumeCreateOptions{}, nil) Expect(err).To(BeNil()) - systemPruneResponse, err := system.Prune(bt.conn, bindings.PTrue, bindings.PTrue) + options := new(system.PruneOptions).WithAll(true).WithVolumes(true) + systemPruneResponse, err := system.Prune(bt.conn, options) Expect(err).To(BeNil()) Expect(len(systemPruneResponse.PodPruneReport)).To(Equal(0)) Expect(len(systemPruneResponse.ContainerPruneReport.ID)).To(Equal(1)) diff --git a/pkg/bindings/test/volumes_test.go b/pkg/bindings/test/volumes_test.go index 861a02441..0664a99e4 100644 --- a/pkg/bindings/test/volumes_test.go +++ b/pkg/bindings/test/volumes_test.go @@ -52,7 +52,7 @@ var _ = Describe("Podman volumes", func() { It("create volume", func() { // create a volume with blank config should work - _, err := volumes.Create(connText, entities.VolumeCreateOptions{}) + _, err := volumes.Create(connText, entities.VolumeCreateOptions{}, nil) Expect(err).To(BeNil()) vcc := entities.VolumeCreateOptions{ @@ -60,21 +60,21 @@ var _ = Describe("Podman volumes", func() { Label: nil, Options: nil, } - vol, err := volumes.Create(connText, vcc) + vol, err := volumes.Create(connText, vcc, nil) Expect(err).To(BeNil()) Expect(vol.Name).To(Equal("foobar")) // create volume with same name should 500 - _, err = volumes.Create(connText, vcc) + _, err = volumes.Create(connText, vcc, nil) Expect(err).ToNot(BeNil()) code, _ := bindings.CheckResponseCode(err) Expect(code).To(BeNumerically("==", http.StatusInternalServerError)) }) It("inspect volume", func() { - vol, err := volumes.Create(connText, entities.VolumeCreateOptions{}) + vol, err := volumes.Create(connText, entities.VolumeCreateOptions{}, nil) Expect(err).To(BeNil()) - data, err := volumes.Inspect(connText, vol.Name) + data, err := volumes.Inspect(connText, vol.Name, nil) Expect(err).To(BeNil()) Expect(data.Name).To(Equal(vol.Name)) }) @@ -86,13 +86,13 @@ var _ = Describe("Podman volumes", func() { Expect(code).To(BeNumerically("==", http.StatusNotFound)) // Removing an unused volume should work - vol, err := volumes.Create(connText, entities.VolumeCreateOptions{}) + vol, err := volumes.Create(connText, entities.VolumeCreateOptions{}, nil) Expect(err).To(BeNil()) err = volumes.Remove(connText, vol.Name, nil) Expect(err).To(BeNil()) // Removing a volume that is being used without force should be 409 - vol, err = volumes.Create(connText, entities.VolumeCreateOptions{}) + vol, err = volumes.Create(connText, entities.VolumeCreateOptions{}, nil) Expect(err).To(BeNil()) session := bt.runPodman([]string{"run", "-dt", "-v", fmt.Sprintf("%s:/foobar", vol.Name), "--name", "vtest", alpine.name, "top"}) session.Wait(45) @@ -105,7 +105,8 @@ var _ = Describe("Podman volumes", func() { zero := uint(0) err = containers.Stop(connText, "vtest", &zero) Expect(err).To(BeNil()) - err = volumes.Remove(connText, vol.Name, bindings.PTrue) + options := new(volumes.RemoveOptions).WithForce(true) + err = volumes.Remove(connText, vol.Name, options) Expect(err).To(BeNil()) }) @@ -118,7 +119,7 @@ var _ = Describe("Podman volumes", func() { // create a bunch of named volumes and make verify with list volNames := []string{"homer", "bart", "lisa", "maggie", "marge"} for i := 0; i < 5; i++ { - _, err = volumes.Create(connText, entities.VolumeCreateOptions{Name: volNames[i]}) + _, err = volumes.Create(connText, entities.VolumeCreateOptions{Name: volNames[i]}, nil) Expect(err).To(BeNil()) } vols, err = volumes.List(connText, nil) @@ -131,14 +132,16 @@ var _ = Describe("Podman volumes", func() { // list with bad filter should be 500 filters := make(map[string][]string) filters["foobar"] = []string{"1234"} - _, err = volumes.List(connText, filters) + options := new(volumes.ListOptions).WithFilters(filters) + _, err = volumes.List(connText, options) Expect(err).ToNot(BeNil()) code, _ := bindings.CheckResponseCode(err) Expect(code).To(BeNumerically("==", http.StatusInternalServerError)) filters = make(map[string][]string) filters["name"] = []string{"homer"} - vols, err = volumes.List(connText, filters) + options = new(volumes.ListOptions).WithFilters(filters) + vols, err = volumes.List(connText, options) Expect(err).To(BeNil()) Expect(len(vols)).To(BeNumerically("==", 1)) Expect(vols[0].Name).To(Equal("homer")) @@ -150,22 +153,22 @@ var _ = Describe("Podman volumes", func() { Expect(err).To(BeNil()) // Removing an unused volume should work - _, err = volumes.Create(connText, entities.VolumeCreateOptions{}) + _, err = volumes.Create(connText, entities.VolumeCreateOptions{}, nil) Expect(err).To(BeNil()) vols, err := volumes.Prune(connText, nil) Expect(err).To(BeNil()) Expect(len(vols)).To(BeNumerically("==", 1)) - _, err = volumes.Create(connText, entities.VolumeCreateOptions{Name: "homer"}) + _, err = volumes.Create(connText, entities.VolumeCreateOptions{Name: "homer"}, nil) Expect(err).To(BeNil()) - _, err = volumes.Create(connText, entities.VolumeCreateOptions{}) + _, err = volumes.Create(connText, entities.VolumeCreateOptions{}, nil) Expect(err).To(BeNil()) session := bt.runPodman([]string{"run", "-dt", "-v", fmt.Sprintf("%s:/homer", "homer"), "--name", "vtest", alpine.name, "top"}) session.Wait(45) vols, err = volumes.Prune(connText, nil) Expect(err).To(BeNil()) Expect(len(vols)).To(BeNumerically("==", 1)) - _, err = volumes.Inspect(connText, "homer") + _, err = volumes.Inspect(connText, "homer", nil) Expect(err).To(BeNil()) // Removing volume with non matching filter shouldn't prune any volumes @@ -173,24 +176,26 @@ var _ = Describe("Podman volumes", func() { filters["label"] = []string{"label1=idontmatch"} _, err = volumes.Create(connText, entities.VolumeCreateOptions{Label: map[string]string{ "label1": "value1", - }}) + }}, nil) Expect(err).To(BeNil()) - vols, err = volumes.Prune(connText, filters) + options := new(volumes.PruneOptions).WithFilters(filters) + vols, err = volumes.Prune(connText, options) Expect(err).To(BeNil()) Expect(len(vols)).To(BeNumerically("==", 0)) vol2, err := volumes.Create(connText, entities.VolumeCreateOptions{Label: map[string]string{ "label1": "value2", - }}) + }}, nil) Expect(err).To(BeNil()) _, err = volumes.Create(connText, entities.VolumeCreateOptions{Label: map[string]string{ "label1": "value3", - }}) + }}, nil) Expect(err).To(BeNil()) // Removing volume with matching filter label and value should remove specific entry filters = make(map[string][]string) filters["label"] = []string{"label1=value2"} - vols, err = volumes.Prune(connText, filters) + options = new(volumes.PruneOptions).WithFilters(filters) + vols, err = volumes.Prune(connText, options) Expect(err).To(BeNil()) Expect(len(vols)).To(BeNumerically("==", 1)) Expect(vols[0].Id).To(Equal(vol2.Name)) @@ -198,7 +203,8 @@ var _ = Describe("Podman volumes", func() { // Removing volumes with matching filter label should remove all matching volumes filters = make(map[string][]string) filters["label"] = []string{"label1"} - vols, err = volumes.Prune(connText, filters) + options = new(volumes.PruneOptions).WithFilters(filters) + vols, err = volumes.Prune(connText, options) Expect(err).To(BeNil()) Expect(len(vols)).To(BeNumerically("==", 2)) }) diff --git a/pkg/bindings/volumes/types.go b/pkg/bindings/volumes/types.go new file mode 100644 index 000000000..379174e33 --- /dev/null +++ b/pkg/bindings/volumes/types.go @@ -0,0 +1,32 @@ +package volumes + +//go:generate go run ../generator/generator.go CreateOptions +// CreateOptions are optional options for creating volumes +type CreateOptions struct { +} + +//go:generate go run ../generator/generator.go InspectOptions +// InspectOptions are optional options for inspecting volumes +type InspectOptions struct { +} + +//go:generate go run ../generator/generator.go ListOptions +// ListOptions are optional options for listing volumes +type ListOptions struct { + // Filters applied to the listing of volumes + Filters map[string][]string +} + +//go:generate go run ../generator/generator.go PruneOptions +// PruneOptions are optional options for pruning volumes +type PruneOptions struct { + // Filters applied to the pruning of volumes + Filters map[string][]string +} + +//go:generate go run ../generator/generator.go RemoveOptions +// RemoveOptions are optional options for removing volumes +type RemoveOptions struct { + // Force removes the volume even if it is being used + Force *bool +} diff --git a/pkg/bindings/volumes/types_create_options.go b/pkg/bindings/volumes/types_create_options.go new file mode 100644 index 000000000..442dedc8a --- /dev/null +++ b/pkg/bindings/volumes/types_create_options.go @@ -0,0 +1,88 @@ +package volumes + +import ( + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-16 11:59:25.536700522 -0600 CST m=+0.000174605 +*/ + +// Changed +func (o *CreateOptions) Changed(fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +// ToParams +func (o *CreateOptions) 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 +} diff --git a/pkg/bindings/volumes/types_inspect_options.go b/pkg/bindings/volumes/types_inspect_options.go new file mode 100644 index 000000000..f9fc9096b --- /dev/null +++ b/pkg/bindings/volumes/types_inspect_options.go @@ -0,0 +1,88 @@ +package volumes + +import ( + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-16 11:59:25.697109241 -0600 CST m=+0.000142064 +*/ + +// Changed +func (o *InspectOptions) Changed(fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +// ToParams +func (o *InspectOptions) 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 +} diff --git a/pkg/bindings/volumes/types_list_options.go b/pkg/bindings/volumes/types_list_options.go new file mode 100644 index 000000000..673643cf1 --- /dev/null +++ b/pkg/bindings/volumes/types_list_options.go @@ -0,0 +1,104 @@ +package volumes + +import ( + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-16 11:59:25.835646604 -0600 CST m=+0.000141801 +*/ + +// Changed +func (o *ListOptions) Changed(fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +// ToParams +func (o *ListOptions) 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 +} + +// WithFilters +func (o *ListOptions) WithFilters(value map[string][]string) *ListOptions { + v := value + o.Filters = v + return o +} + +// GetFilters +func (o *ListOptions) GetFilters() map[string][]string { + var filters map[string][]string + if o.Filters == nil { + return filters + } + return o.Filters +} diff --git a/pkg/bindings/volumes/types_prune_options.go b/pkg/bindings/volumes/types_prune_options.go new file mode 100644 index 000000000..94d81e737 --- /dev/null +++ b/pkg/bindings/volumes/types_prune_options.go @@ -0,0 +1,104 @@ +package volumes + +import ( + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-16 11:59:25.972202545 -0600 CST m=+0.000209541 +*/ + +// Changed +func (o *PruneOptions) Changed(fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +// ToParams +func (o *PruneOptions) 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 +} + +// WithFilters +func (o *PruneOptions) WithFilters(value map[string][]string) *PruneOptions { + v := value + o.Filters = v + return o +} + +// GetFilters +func (o *PruneOptions) GetFilters() map[string][]string { + var filters map[string][]string + if o.Filters == nil { + return filters + } + return o.Filters +} diff --git a/pkg/bindings/volumes/types_remove_options.go b/pkg/bindings/volumes/types_remove_options.go new file mode 100644 index 000000000..499abf0f2 --- /dev/null +++ b/pkg/bindings/volumes/types_remove_options.go @@ -0,0 +1,104 @@ +package volumes + +import ( + "net/url" + "reflect" + "strconv" + + jsoniter "github.com/json-iterator/go" + "github.com/pkg/errors" +) + +/* +This file is generated automatically by go generate. Do not edit. + +Created 2020-12-16 11:59:26.109834902 -0600 CST m=+0.000175439 +*/ + +// Changed +func (o *RemoveOptions) Changed(fieldName string) bool { + r := reflect.ValueOf(o) + value := reflect.Indirect(r).FieldByName(fieldName) + return !value.IsNil() +} + +// ToParams +func (o *RemoveOptions) 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 + } + 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() + slice := reflect.MakeSlice(reflect.SliceOf(typ), f.Len(), f.Cap()) + switch typ.Kind() { + case reflect.String: + s, ok := slice.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 +} + +// WithForce +func (o *RemoveOptions) WithForce(value bool) *RemoveOptions { + v := &value + o.Force = v + return o +} + +// GetForce +func (o *RemoveOptions) GetForce() bool { + var force bool + if o.Force == nil { + return force + } + return *o.Force +} diff --git a/pkg/bindings/volumes/volumes.go b/pkg/bindings/volumes/volumes.go index b1be257b8..626f52d39 100644 --- a/pkg/bindings/volumes/volumes.go +++ b/pkg/bindings/volumes/volumes.go @@ -3,8 +3,6 @@ package volumes import ( "context" "net/http" - "net/url" - "strconv" "strings" "github.com/containers/podman/v2/pkg/bindings" @@ -13,10 +11,14 @@ import ( ) // Create creates a volume given its configuration. -func Create(ctx context.Context, config entities.VolumeCreateOptions) (*entities.VolumeConfigResponse, error) { +func Create(ctx context.Context, config entities.VolumeCreateOptions, options *CreateOptions) (*entities.VolumeConfigResponse, error) { var ( v entities.VolumeConfigResponse ) + if options == nil { + options = new(CreateOptions) + } + _ = options conn, err := bindings.GetClient(ctx) if err != nil { return nil, err @@ -34,10 +36,14 @@ func Create(ctx context.Context, config entities.VolumeCreateOptions) (*entities } // Inspect returns low-level information about a volume. -func Inspect(ctx context.Context, nameOrID string) (*entities.VolumeConfigResponse, error) { +func Inspect(ctx context.Context, nameOrID string, options *InspectOptions) (*entities.VolumeConfigResponse, error) { var ( inspect entities.VolumeConfigResponse ) + if options == nil { + options = new(InspectOptions) + } + _ = options conn, err := bindings.GetClient(ctx) if err != nil { return nil, err @@ -51,7 +57,7 @@ func Inspect(ctx context.Context, nameOrID string) (*entities.VolumeConfigRespon // List returns the configurations for existing volumes in the form of a slice. Optionally, filters // can be used to refine the list of volumes. -func List(ctx context.Context, filters map[string][]string) ([]*entities.VolumeListReport, error) { +func List(ctx context.Context, options *ListOptions) ([]*entities.VolumeListReport, error) { var ( vols []*entities.VolumeListReport ) @@ -59,13 +65,9 @@ func List(ctx context.Context, filters map[string][]string) ([]*entities.VolumeL if err != nil { return nil, err } - params := url.Values{} - if len(filters) > 0 { - strFilters, err := bindings.FiltersToString(filters) - if err != nil { - return nil, err - } - params.Set("filters", strFilters) + params, err := options.ToParams() + if err != nil { + return nil, err } response, err := conn.DoRequest(nil, http.MethodGet, "/volumes/json", params, nil) if err != nil { @@ -75,7 +77,7 @@ func List(ctx context.Context, filters map[string][]string) ([]*entities.VolumeL } // Prune removes unused volumes from the local filesystem. -func Prune(ctx context.Context, filters map[string][]string) ([]*entities.VolumePruneReport, error) { +func Prune(ctx context.Context, options *PruneOptions) ([]*entities.VolumePruneReport, error) { var ( pruned []*entities.VolumePruneReport ) @@ -83,13 +85,9 @@ func Prune(ctx context.Context, filters map[string][]string) ([]*entities.Volume if err != nil { return nil, err } - params := url.Values{} - if len(filters) > 0 { - strFilters, err := bindings.FiltersToString(filters) - if err != nil { - return nil, err - } - params.Set("filters", strFilters) + params, err := options.ToParams() + if err != nil { + return nil, err } response, err := conn.DoRequest(nil, http.MethodPost, "/volumes/prune", params, nil) if err != nil { @@ -100,14 +98,14 @@ func Prune(ctx context.Context, filters map[string][]string) ([]*entities.Volume // Remove deletes the given volume from storage. The optional force parameter // is used to remove a volume even if it is being used by a container. -func Remove(ctx context.Context, nameOrID string, force *bool) error { +func Remove(ctx context.Context, nameOrID string, options *RemoveOptions) error { conn, err := bindings.GetClient(ctx) if err != nil { return err } - params := url.Values{} - if force != nil { - params.Set("force", strconv.FormatBool(*force)) + params, err := options.ToParams() + if err != nil { + return err } response, err := conn.DoRequest(nil, http.MethodDelete, "/volumes/%s", params, nil, nameOrID) if err != nil { |