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  }