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