github.com/docker/docker@v299999999.0.0-20200612211812-aaf470eca7b5+incompatible/volume/drivers/adapter.go (about)

     1  package drivers // import "github.com/docker/docker/volume/drivers"
     2  
     3  import (
     4  	"errors"
     5  	"strings"
     6  	"time"
     7  
     8  	"github.com/docker/docker/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  }