github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/volume/drivers/adapter.go (about) 1 package drivers // import "github.com/demonoid81/moby/volume/drivers" 2 3 import ( 4 "errors" 5 "strings" 6 "time" 7 8 "github.com/demonoid81/moby/volume" 9 "github.com/sirupsen/logrus" 10 ) 11 12 var ( 13 errNoSuchVolume = errors.New("no such volume") 14 ) 15 16 type volumeDriverAdapter struct { 17 name string 18 scopePath func(s string) string 19 capabilities *volume.Capability 20 proxy volumeDriver 21 } 22 23 func (a *volumeDriverAdapter) Name() string { 24 return a.name 25 } 26 27 func (a *volumeDriverAdapter) Create(name string, opts map[string]string) (volume.Volume, error) { 28 if err := a.proxy.Create(name, opts); err != nil { 29 return nil, err 30 } 31 return &volumeAdapter{ 32 proxy: a.proxy, 33 name: name, 34 driverName: a.name, 35 scopePath: a.scopePath, 36 }, nil 37 } 38 39 func (a *volumeDriverAdapter) Remove(v volume.Volume) error { 40 return a.proxy.Remove(v.Name()) 41 } 42 43 func (a *volumeDriverAdapter) List() ([]volume.Volume, error) { 44 ls, err := a.proxy.List() 45 if err != nil { 46 return nil, err 47 } 48 49 var out []volume.Volume 50 for _, vp := range ls { 51 out = append(out, &volumeAdapter{ 52 proxy: a.proxy, 53 name: vp.Name, 54 scopePath: a.scopePath, 55 driverName: a.name, 56 eMount: a.scopePath(vp.Mountpoint), 57 }) 58 } 59 return out, nil 60 } 61 62 func (a *volumeDriverAdapter) Get(name string) (volume.Volume, error) { 63 v, err := a.proxy.Get(name) 64 if err != nil { 65 return nil, err 66 } 67 68 // plugin may have returned no volume and no error 69 if v == nil { 70 return nil, errNoSuchVolume 71 } 72 73 return &volumeAdapter{ 74 proxy: a.proxy, 75 name: v.Name, 76 driverName: a.Name(), 77 eMount: v.Mountpoint, 78 createdAt: v.CreatedAt, 79 status: v.Status, 80 scopePath: a.scopePath, 81 }, nil 82 } 83 84 func (a *volumeDriverAdapter) Scope() string { 85 cap := a.getCapabilities() 86 return cap.Scope 87 } 88 89 func (a *volumeDriverAdapter) getCapabilities() volume.Capability { 90 if a.capabilities != nil { 91 return *a.capabilities 92 } 93 cap, err := a.proxy.Capabilities() 94 if err != nil { 95 // `GetCapabilities` is a not a required endpoint. 96 // On error assume it's a local-only driver 97 logrus.WithError(err).WithField("driver", a.name).Debug("Volume driver returned an error while trying to query its capabilities, using default capabilities") 98 return volume.Capability{Scope: volume.LocalScope} 99 } 100 101 // don't spam the warn log below just because the plugin didn't provide a scope 102 if len(cap.Scope) == 0 { 103 cap.Scope = volume.LocalScope 104 } 105 106 cap.Scope = strings.ToLower(cap.Scope) 107 if cap.Scope != volume.LocalScope && cap.Scope != volume.GlobalScope { 108 logrus.WithField("driver", a.Name()).WithField("scope", a.Scope).Warn("Volume driver returned an invalid scope") 109 cap.Scope = volume.LocalScope 110 } 111 112 a.capabilities = &cap 113 return cap 114 } 115 116 type volumeAdapter struct { 117 proxy volumeDriver 118 name string 119 scopePath func(string) string 120 driverName string 121 eMount string // ephemeral host volume path 122 createdAt time.Time // time the directory was created 123 status map[string]interface{} 124 } 125 126 type proxyVolume struct { 127 Name string 128 Mountpoint string 129 CreatedAt time.Time 130 Status map[string]interface{} 131 } 132 133 func (a *volumeAdapter) Name() string { 134 return a.name 135 } 136 137 func (a *volumeAdapter) DriverName() string { 138 return a.driverName 139 } 140 141 func (a *volumeAdapter) Path() string { 142 if len(a.eMount) == 0 { 143 mountpoint, _ := a.proxy.Path(a.name) 144 a.eMount = a.scopePath(mountpoint) 145 } 146 return a.eMount 147 } 148 149 func (a *volumeAdapter) CachedPath() string { 150 return a.eMount 151 } 152 153 func (a *volumeAdapter) Mount(id string) (string, error) { 154 mountpoint, err := a.proxy.Mount(a.name, id) 155 a.eMount = a.scopePath(mountpoint) 156 return a.eMount, err 157 } 158 159 func (a *volumeAdapter) Unmount(id string) error { 160 err := a.proxy.Unmount(a.name, id) 161 if err == nil { 162 a.eMount = "" 163 } 164 return err 165 } 166 167 func (a *volumeAdapter) CreatedAt() (time.Time, error) { 168 return a.createdAt, nil 169 } 170 func (a *volumeAdapter) Status() map[string]interface{} { 171 out := make(map[string]interface{}, len(a.status)) 172 for k, v := range a.status { 173 out[k] = v 174 } 175 return out 176 }