123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- package drivers // import "github.com/docker/docker/volume/drivers"
- import (
- "context"
- "errors"
- "strings"
- "time"
- "github.com/containerd/log"
- "github.com/docker/docker/volume"
- )
- var errNoSuchVolume = errors.New("no such volume")
- type volumeDriverAdapter struct {
- name string
- scopePath func(s string) string
- capabilities *volume.Capability
- proxy volumeDriver
- }
- func (a *volumeDriverAdapter) Name() string {
- return a.name
- }
- func (a *volumeDriverAdapter) Create(name string, opts map[string]string) (volume.Volume, error) {
- if err := a.proxy.Create(name, opts); err != nil {
- return nil, err
- }
- return &volumeAdapter{
- proxy: a.proxy,
- name: name,
- driverName: a.name,
- scopePath: a.scopePath,
- }, nil
- }
- func (a *volumeDriverAdapter) Remove(v volume.Volume) error {
- return a.proxy.Remove(v.Name())
- }
- func (a *volumeDriverAdapter) List() ([]volume.Volume, error) {
- ls, err := a.proxy.List()
- if err != nil {
- return nil, err
- }
- var out []volume.Volume
- for _, vp := range ls {
- out = append(out, &volumeAdapter{
- proxy: a.proxy,
- name: vp.Name,
- scopePath: a.scopePath,
- driverName: a.name,
- eMount: a.scopePath(vp.Mountpoint),
- })
- }
- return out, nil
- }
- func (a *volumeDriverAdapter) Get(name string) (volume.Volume, error) {
- v, err := a.proxy.Get(name)
- if err != nil {
- return nil, err
- }
- // plugin may have returned no volume and no error
- if v == nil {
- return nil, errNoSuchVolume
- }
- return &volumeAdapter{
- proxy: a.proxy,
- name: v.Name,
- driverName: a.Name(),
- eMount: v.Mountpoint,
- createdAt: v.CreatedAt,
- status: v.Status,
- scopePath: a.scopePath,
- }, nil
- }
- func (a *volumeDriverAdapter) Scope() string {
- cap := a.getCapabilities()
- return cap.Scope
- }
- func (a *volumeDriverAdapter) getCapabilities() volume.Capability {
- if a.capabilities != nil {
- return *a.capabilities
- }
- cap, err := a.proxy.Capabilities()
- if err != nil {
- // `GetCapabilities` is a not a required endpoint.
- // On error assume it's a local-only driver
- 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")
- return volume.Capability{Scope: volume.LocalScope}
- }
- // don't spam the warn log below just because the plugin didn't provide a scope
- if len(cap.Scope) == 0 {
- cap.Scope = volume.LocalScope
- }
- cap.Scope = strings.ToLower(cap.Scope)
- if cap.Scope != volume.LocalScope && cap.Scope != volume.GlobalScope {
- log.G(context.TODO()).WithField("driver", a.Name()).WithField("scope", a.Scope).Warn("Volume driver returned an invalid scope")
- cap.Scope = volume.LocalScope
- }
- a.capabilities = &cap
- return cap
- }
- type volumeAdapter struct {
- proxy volumeDriver
- name string
- scopePath func(string) string
- driverName string
- eMount string // ephemeral host volume path
- createdAt time.Time // time the directory was created
- status map[string]interface{}
- }
- type proxyVolume struct {
- Name string
- Mountpoint string
- CreatedAt time.Time
- Status map[string]interface{}
- }
- func (a *volumeAdapter) Name() string {
- return a.name
- }
- func (a *volumeAdapter) DriverName() string {
- return a.driverName
- }
- func (a *volumeAdapter) Path() string {
- if len(a.eMount) == 0 {
- mountpoint, _ := a.proxy.Path(a.name)
- a.eMount = a.scopePath(mountpoint)
- }
- return a.eMount
- }
- func (a *volumeAdapter) CachedPath() string {
- return a.eMount
- }
- func (a *volumeAdapter) Mount(id string) (string, error) {
- mountpoint, err := a.proxy.Mount(a.name, id)
- a.eMount = a.scopePath(mountpoint)
- return a.eMount, err
- }
- func (a *volumeAdapter) Unmount(id string) error {
- err := a.proxy.Unmount(a.name, id)
- if err == nil {
- a.eMount = ""
- }
- return err
- }
- func (a *volumeAdapter) CreatedAt() (time.Time, error) {
- return a.createdAt, nil
- }
- func (a *volumeAdapter) Status() map[string]interface{} {
- out := make(map[string]interface{}, len(a.status))
- for k, v := range a.status {
- out[k] = v
- }
- return out
- }
|