mirror of
https://github.com/moby/moby.git
synced 2026-01-11 18:51:37 +00:00
Most of the code in the filters package relates to the unmarshaling, validation and application of filters from client requests. None of this is necessary or particularly useful for Go SDK users. Move the full-fat filters package into daemon/internal and switch all the daemon code to import that package so we are free to iterate upon the code without worrying about source-code interface compatibility. Signed-off-by: Cory Snider <csnider@mirantis.com>
153 lines
3.2 KiB
Go
153 lines
3.2 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/containerd/log"
|
|
volumetypes "github.com/moby/moby/api/types/volume"
|
|
"github.com/moby/moby/v2/daemon/internal/directory"
|
|
"github.com/moby/moby/v2/daemon/internal/filters"
|
|
"github.com/moby/moby/v2/daemon/volume"
|
|
"github.com/moby/moby/v2/errdefs"
|
|
)
|
|
|
|
// convertOpts are used to pass options to `volumeToAPI`
|
|
type convertOpt interface {
|
|
isConvertOpt()
|
|
}
|
|
|
|
type useCachedPath bool
|
|
|
|
func (useCachedPath) isConvertOpt() {}
|
|
|
|
type calcSize bool
|
|
|
|
func (calcSize) isConvertOpt() {}
|
|
|
|
type pathCacher interface {
|
|
CachedPath() string
|
|
}
|
|
|
|
func (s *VolumesService) volumesToAPI(ctx context.Context, volumes []volume.Volume, opts ...convertOpt) []*volumetypes.Volume {
|
|
var (
|
|
out = make([]*volumetypes.Volume, 0, len(volumes))
|
|
getSize bool
|
|
cachedPath bool
|
|
)
|
|
|
|
for _, o := range opts {
|
|
switch t := o.(type) {
|
|
case calcSize:
|
|
getSize = bool(t)
|
|
case useCachedPath:
|
|
cachedPath = bool(t)
|
|
}
|
|
}
|
|
for _, v := range volumes {
|
|
select {
|
|
case <-ctx.Done():
|
|
return nil
|
|
default:
|
|
}
|
|
apiV := volumeToAPIType(v)
|
|
|
|
if cachedPath {
|
|
if vv, ok := v.(pathCacher); ok {
|
|
apiV.Mountpoint = vv.CachedPath()
|
|
}
|
|
} else {
|
|
apiV.Mountpoint = v.Path()
|
|
}
|
|
|
|
if getSize {
|
|
p := v.Path()
|
|
if apiV.Mountpoint == "" {
|
|
apiV.Mountpoint = p
|
|
}
|
|
sz, err := directory.Size(ctx, p)
|
|
if err != nil {
|
|
log.G(ctx).WithError(err).WithField("volume", v.Name()).Warnf("Failed to determine size of volume")
|
|
sz = -1
|
|
}
|
|
apiV.UsageData = &volumetypes.UsageData{Size: sz, RefCount: int64(s.vs.CountReferences(v))}
|
|
}
|
|
|
|
out = append(out, &apiV)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func volumeToAPIType(v volume.Volume) volumetypes.Volume {
|
|
createdAt, _ := v.CreatedAt()
|
|
tv := volumetypes.Volume{
|
|
Name: v.Name(),
|
|
Driver: v.DriverName(),
|
|
CreatedAt: createdAt.Format(time.RFC3339),
|
|
}
|
|
if v, ok := v.(volume.DetailedVolume); ok {
|
|
tv.Labels = v.Labels()
|
|
tv.Options = v.Options()
|
|
tv.Scope = v.Scope()
|
|
}
|
|
if cp, ok := v.(pathCacher); ok {
|
|
tv.Mountpoint = cp.CachedPath()
|
|
}
|
|
return tv
|
|
}
|
|
|
|
func filtersToBy(filter filters.Args, acceptedFilters map[string]bool) (By, error) {
|
|
if err := filter.Validate(acceptedFilters); err != nil {
|
|
return nil, err
|
|
}
|
|
var bys []By
|
|
if drivers := filter.Get("driver"); len(drivers) > 0 {
|
|
bys = append(bys, ByDriver(drivers...))
|
|
}
|
|
if filter.Contains("name") {
|
|
bys = append(bys, CustomFilter(func(v volume.Volume) bool {
|
|
return filter.Match("name", v.Name())
|
|
}))
|
|
}
|
|
bys = append(bys, byLabelFilter(filter))
|
|
|
|
if filter.Contains("dangling") {
|
|
dangling, err := filter.GetBoolOrDefault("dangling", false)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
bys = append(bys, ByReferenced(!dangling))
|
|
}
|
|
|
|
var by By
|
|
switch len(bys) {
|
|
case 0:
|
|
case 1:
|
|
by = bys[0]
|
|
default:
|
|
by = And(bys...)
|
|
}
|
|
return by, nil
|
|
}
|
|
|
|
func withPrune(filter filters.Args) error {
|
|
all := filter.Get("all")
|
|
switch {
|
|
case len(all) > 1:
|
|
return errdefs.InvalidParameter(fmt.Errorf("invalid filter 'all=%s': only one value is expected", all))
|
|
case len(all) == 1:
|
|
ok, err := strconv.ParseBool(all[0])
|
|
if err != nil {
|
|
return errdefs.InvalidParameter(fmt.Errorf("invalid filter 'all': %w", err))
|
|
}
|
|
if ok {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
filter.Add("label", AnonymousLabel)
|
|
return nil
|
|
}
|