github.com/Shopify/docker@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  }