adapter.go 4.0 KB

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