github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/volume/service/convert.go (about) 1 package service 2 3 import ( 4 "context" 5 "fmt" 6 "strconv" 7 "time" 8 9 "github.com/containerd/log" 10 "github.com/Prakhar-Agarwal-byte/moby/api/types/filters" 11 volumetypes "github.com/Prakhar-Agarwal-byte/moby/api/types/volume" 12 "github.com/Prakhar-Agarwal-byte/moby/errdefs" 13 "github.com/Prakhar-Agarwal-byte/moby/pkg/directory" 14 "github.com/Prakhar-Agarwal-byte/moby/volume" 15 ) 16 17 // convertOpts are used to pass options to `volumeToAPI` 18 type convertOpt interface { 19 isConvertOpt() 20 } 21 22 type useCachedPath bool 23 24 func (useCachedPath) isConvertOpt() {} 25 26 type calcSize bool 27 28 func (calcSize) isConvertOpt() {} 29 30 type pathCacher interface { 31 CachedPath() string 32 } 33 34 func (s *VolumesService) volumesToAPI(ctx context.Context, volumes []volume.Volume, opts ...convertOpt) []*volumetypes.Volume { 35 var ( 36 out = make([]*volumetypes.Volume, 0, len(volumes)) 37 getSize bool 38 cachedPath bool 39 ) 40 41 for _, o := range opts { 42 switch t := o.(type) { 43 case calcSize: 44 getSize = bool(t) 45 case useCachedPath: 46 cachedPath = bool(t) 47 } 48 } 49 for _, v := range volumes { 50 select { 51 case <-ctx.Done(): 52 return nil 53 default: 54 } 55 apiV := volumeToAPIType(v) 56 57 if cachedPath { 58 if vv, ok := v.(pathCacher); ok { 59 apiV.Mountpoint = vv.CachedPath() 60 } 61 } else { 62 apiV.Mountpoint = v.Path() 63 } 64 65 if getSize { 66 p := v.Path() 67 if apiV.Mountpoint == "" { 68 apiV.Mountpoint = p 69 } 70 sz, err := directory.Size(ctx, p) 71 if err != nil { 72 log.G(ctx).WithError(err).WithField("volume", v.Name()).Warnf("Failed to determine size of volume") 73 sz = -1 74 } 75 apiV.UsageData = &volumetypes.UsageData{Size: sz, RefCount: int64(s.vs.CountReferences(v))} 76 } 77 78 out = append(out, &apiV) 79 } 80 return out 81 } 82 83 func volumeToAPIType(v volume.Volume) volumetypes.Volume { 84 createdAt, _ := v.CreatedAt() 85 tv := volumetypes.Volume{ 86 Name: v.Name(), 87 Driver: v.DriverName(), 88 CreatedAt: createdAt.Format(time.RFC3339), 89 } 90 if v, ok := v.(volume.DetailedVolume); ok { 91 tv.Labels = v.Labels() 92 tv.Options = v.Options() 93 tv.Scope = v.Scope() 94 } 95 if cp, ok := v.(pathCacher); ok { 96 tv.Mountpoint = cp.CachedPath() 97 } 98 return tv 99 } 100 101 func filtersToBy(filter filters.Args, acceptedFilters map[string]bool) (By, error) { 102 if err := filter.Validate(acceptedFilters); err != nil { 103 return nil, err 104 } 105 var bys []By 106 if drivers := filter.Get("driver"); len(drivers) > 0 { 107 bys = append(bys, ByDriver(drivers...)) 108 } 109 if filter.Contains("name") { 110 bys = append(bys, CustomFilter(func(v volume.Volume) bool { 111 return filter.Match("name", v.Name()) 112 })) 113 } 114 bys = append(bys, byLabelFilter(filter)) 115 116 if filter.Contains("dangling") { 117 dangling, err := filter.GetBoolOrDefault("dangling", false) 118 if err != nil { 119 return nil, err 120 } 121 bys = append(bys, ByReferenced(!dangling)) 122 } 123 124 var by By 125 switch len(bys) { 126 case 0: 127 case 1: 128 by = bys[0] 129 default: 130 by = And(bys...) 131 } 132 return by, nil 133 } 134 135 func withPrune(filter filters.Args) error { 136 all := filter.Get("all") 137 switch { 138 case len(all) > 1: 139 return errdefs.InvalidParameter(fmt.Errorf("invalid filter 'all=%s': only one value is expected", all)) 140 case len(all) == 1: 141 ok, err := strconv.ParseBool(all[0]) 142 if err != nil { 143 return errdefs.InvalidParameter(fmt.Errorf("invalid filter 'all': %w", err)) 144 } 145 if ok { 146 return nil 147 } 148 } 149 150 filter.Add("label", AnonymousLabel) 151 return nil 152 }