From 5b97ddd343ca9a1eb0adb4ac467428cda7a43e0c Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Fri, 24 Sep 2021 14:51:35 +0200 Subject: [PATCH] WIP: add size options for volume ls Need to look what the most reasonable approach is; the backend uses functional options, whereas other backends use an option-struct :/ Signed-off-by: Sebastiaan van Stijn --- api/server/router/volume/backend.go | 2 +- api/server/router/volume/volume_routes.go | 9 +++++--- api/types/volume/options.go | 3 +++ client/volume_list.go | 3 +++ volume/service/opts/opts.go | 27 +++++++++++++++++++++++ volume/service/service.go | 15 ++++++++++--- 6 files changed, 52 insertions(+), 7 deletions(-) diff --git a/api/server/router/volume/backend.go b/api/server/router/volume/backend.go index 8de9a84d4b3b4..59b140c417e1f 100644 --- a/api/server/router/volume/backend.go +++ b/api/server/router/volume/backend.go @@ -13,7 +13,7 @@ import ( // Backend is the methods that need to be implemented to provide // volume specific functionality type Backend interface { - List(ctx context.Context, filter filters.Args) ([]*volume.Volume, []string, error) + List(ctx context.Context, opts ...opts.ListOption) ([]*volume.Volume, []string, error) Get(ctx context.Context, name string, opts ...opts.GetOption) (*volume.Volume, error) Create(ctx context.Context, name, driverName string, opts ...opts.CreateOption) (*volume.Volume, error) Remove(ctx context.Context, name string, opts ...opts.RemoveOption) error diff --git a/api/server/router/volume/volume_routes.go b/api/server/router/volume/volume_routes.go index 9bbe13687ffb1..b750858c1600e 100644 --- a/api/server/router/volume/volume_routes.go +++ b/api/server/router/volume/volume_routes.go @@ -27,18 +27,21 @@ func (v *volumeRouter) getVolumesList(ctx context.Context, w http.ResponseWriter return err } - filters, err := filters.FromJSON(r.Form.Get("filters")) + fltrs, err := filters.FromJSON(r.Form.Get("filters")) if err != nil { return errors.Wrap(err, "error reading volume filters") } - volumes, warnings, err := v.backend.List(ctx, filters) + volumes, warnings, err := v.backend.List(ctx, + opts.WithFilters(fltrs), + opts.WithSize(httputils.BoolValue(r, "size")), + ) if err != nil { return err } version := httputils.VersionFromContext(ctx) if versions.GreaterThanOrEqualTo(version, clusterVolumesVersion) && v.cluster.IsManager() { - clusterVolumes, swarmErr := v.cluster.GetVolumes(volume.ListOptions{Filters: filters}) + clusterVolumes, swarmErr := v.cluster.GetVolumes(volume.ListOptions{Filters: fltrs}) if swarmErr != nil { // if there is a swarm error, we may not want to error out right // away. the local list probably worked. instead, let's do what we diff --git a/api/types/volume/options.go b/api/types/volume/options.go index 8b0dd13899866..75c1b1e6f3b0d 100644 --- a/api/types/volume/options.go +++ b/api/types/volume/options.go @@ -5,4 +5,7 @@ import "github.com/docker/docker/api/types/filters" // ListOptions holds parameters to list volumes. type ListOptions struct { Filters filters.Args + + // Size enables calculating the size for each volume. + Size bool } diff --git a/client/volume_list.go b/client/volume_list.go index d5ea9827c72dc..b0c123da44014 100644 --- a/client/volume_list.go +++ b/client/volume_list.go @@ -22,6 +22,9 @@ func (cli *Client) VolumeList(ctx context.Context, options volume.ListOptions) ( } query.Set("filters", filterJSON) } + if options.Size { + query.Set("size", "1") + } resp, err := cli.get(ctx, "/volumes", query, nil) defer ensureReaderClosed(resp) if err != nil { diff --git a/volume/service/opts/opts.go b/volume/service/opts/opts.go index 3b4f63196ac70..6a214bf9fcd74 100644 --- a/volume/service/opts/opts.go +++ b/volume/service/opts/opts.go @@ -1,5 +1,7 @@ package opts +import "github.com/docker/docker/api/types/filters" + // CreateOption is used to pass options in when creating a volume type CreateOption func(*CreateConfig) @@ -97,3 +99,28 @@ func WithPurgeOnError(b bool) RemoveOption { o.PurgeOnError = b } } + +// ListConfig is used by `ListOption` to store config options for listing volumes. +type ListConfig struct { + Filters filters.Args + + // Size enables calculating the size for each volume. + Size bool +} + +// ListOption is passed to the service `List` add extra details on the get request +type ListOption func(*ListConfig) + +// WithFilters applies the given filters to the ListConfig. +func WithFilters(args filters.Args) ListOption { + return func(o *ListConfig) { + o.Filters = args + } +} + +// WithSize enables size calculation for the list response. +func WithSize(enabled bool) ListOption { + return func(o *ListConfig) { + o.Size = enabled + } +} diff --git a/volume/service/service.go b/volume/service/service.go index 7030b2a32bed4..5d6fbaffdb30c 100644 --- a/volume/service/service.go +++ b/volume/service/service.go @@ -256,8 +256,13 @@ func (s *VolumesService) Prune(ctx context.Context, filter filters.Args) (*types // List gets the list of volumes which match the past in filters // If filters is nil or empty all volumes are returned. -func (s *VolumesService) List(ctx context.Context, filter filters.Args) (volumesOut []*volumetypes.Volume, warnings []string, err error) { - by, err := filtersToBy(filter, acceptedListFilters) +func (s *VolumesService) List(ctx context.Context, options ...opts.ListOption) (volumesOut []*volumetypes.Volume, warnings []string, err error) { + var cfg opts.ListConfig + for _, o := range options { + o(&cfg) + } + + by, err := filtersToBy(cfg.Filters, acceptedListFilters) if err != nil { return nil, nil, err } @@ -266,8 +271,12 @@ func (s *VolumesService) List(ctx context.Context, filter filters.Args) (volumes if err != nil { return nil, nil, err } + vOpts := []convertOpt{useCachedPath(true)} + if cfg.Size { + vOpts = append(vOpts, calcSize(true)) + } - return s.volumesToAPI(ctx, volumes, useCachedPath(true)), warnings, nil + return s.volumesToAPI(ctx, volumes, vOpts...), warnings, nil } // Shutdown shuts down the image service and dependencies