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