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