plugin.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. package v2
  2. import (
  3. "fmt"
  4. "strings"
  5. "sync"
  6. "github.com/docker/docker/api/types"
  7. "github.com/docker/docker/pkg/plugingetter"
  8. "github.com/docker/docker/pkg/plugins"
  9. "github.com/opencontainers/go-digest"
  10. )
  11. // Plugin represents an individual plugin.
  12. type Plugin struct {
  13. mu sync.RWMutex
  14. PluginObj types.Plugin `json:"plugin"` // todo: embed struct
  15. pClient *plugins.Client
  16. refCount int
  17. PropagatedMount string // TODO: make private
  18. Rootfs string // TODO: make private
  19. Config digest.Digest
  20. Blobsums []digest.Digest
  21. SwarmServiceID string
  22. }
  23. const defaultPluginRuntimeDestination = "/run/docker/plugins"
  24. // ErrInadequateCapability indicates that the plugin did not have the requested capability.
  25. type ErrInadequateCapability struct {
  26. cap string
  27. }
  28. func (e ErrInadequateCapability) Error() string {
  29. return fmt.Sprintf("plugin does not provide %q capability", e.cap)
  30. }
  31. // BasePath returns the path to which all paths returned by the plugin are relative to.
  32. // For Plugin objects this returns the host path of the plugin container's rootfs.
  33. func (p *Plugin) BasePath() string {
  34. return p.Rootfs
  35. }
  36. // Client returns the plugin client.
  37. func (p *Plugin) Client() *plugins.Client {
  38. p.mu.RLock()
  39. defer p.mu.RUnlock()
  40. return p.pClient
  41. }
  42. // SetPClient set the plugin client.
  43. func (p *Plugin) SetPClient(client *plugins.Client) {
  44. p.mu.Lock()
  45. defer p.mu.Unlock()
  46. p.pClient = client
  47. }
  48. // IsV1 returns true for V1 plugins and false otherwise.
  49. func (p *Plugin) IsV1() bool {
  50. return false
  51. }
  52. // Name returns the plugin name.
  53. func (p *Plugin) Name() string {
  54. return p.PluginObj.Name
  55. }
  56. // FilterByCap query the plugin for a given capability.
  57. func (p *Plugin) FilterByCap(capability string) (*Plugin, error) {
  58. capability = strings.ToLower(capability)
  59. for _, typ := range p.PluginObj.Config.Interface.Types {
  60. if typ.Capability == capability && typ.Prefix == "docker" {
  61. return p, nil
  62. }
  63. }
  64. return nil, ErrInadequateCapability{capability}
  65. }
  66. // InitEmptySettings initializes empty settings for a plugin.
  67. func (p *Plugin) InitEmptySettings() {
  68. p.PluginObj.Settings.Mounts = make([]types.PluginMount, len(p.PluginObj.Config.Mounts))
  69. copy(p.PluginObj.Settings.Mounts, p.PluginObj.Config.Mounts)
  70. p.PluginObj.Settings.Devices = make([]types.PluginDevice, len(p.PluginObj.Config.Linux.Devices))
  71. copy(p.PluginObj.Settings.Devices, p.PluginObj.Config.Linux.Devices)
  72. p.PluginObj.Settings.Env = make([]string, 0, len(p.PluginObj.Config.Env))
  73. for _, env := range p.PluginObj.Config.Env {
  74. if env.Value != nil {
  75. p.PluginObj.Settings.Env = append(p.PluginObj.Settings.Env, fmt.Sprintf("%s=%s", env.Name, *env.Value))
  76. }
  77. }
  78. p.PluginObj.Settings.Args = make([]string, len(p.PluginObj.Config.Args.Value))
  79. copy(p.PluginObj.Settings.Args, p.PluginObj.Config.Args.Value)
  80. }
  81. // Set is used to pass arguments to the plugin.
  82. func (p *Plugin) Set(args []string) error {
  83. p.mu.Lock()
  84. defer p.mu.Unlock()
  85. if p.PluginObj.Enabled {
  86. return fmt.Errorf("cannot set on an active plugin, disable plugin before setting")
  87. }
  88. sets, err := newSettables(args)
  89. if err != nil {
  90. return err
  91. }
  92. // TODO(vieux): lots of code duplication here, needs to be refactored.
  93. next:
  94. for _, s := range sets {
  95. // range over all the envs in the config
  96. for _, env := range p.PluginObj.Config.Env {
  97. // found the env in the config
  98. if env.Name == s.name {
  99. // is it settable ?
  100. if ok, err := s.isSettable(allowedSettableFieldsEnv, env.Settable); err != nil {
  101. return err
  102. } else if !ok {
  103. return fmt.Errorf("%q is not settable", s.prettyName())
  104. }
  105. // is it, so lets update the settings in memory
  106. updateSettingsEnv(&p.PluginObj.Settings.Env, &s)
  107. continue next
  108. }
  109. }
  110. // range over all the mounts in the config
  111. for _, mount := range p.PluginObj.Config.Mounts {
  112. // found the mount in the config
  113. if mount.Name == s.name {
  114. // is it settable ?
  115. if ok, err := s.isSettable(allowedSettableFieldsMounts, mount.Settable); err != nil {
  116. return err
  117. } else if !ok {
  118. return fmt.Errorf("%q is not settable", s.prettyName())
  119. }
  120. // it is, so lets update the settings in memory
  121. *mount.Source = s.value
  122. continue next
  123. }
  124. }
  125. // range over all the devices in the config
  126. for _, device := range p.PluginObj.Config.Linux.Devices {
  127. // found the device in the config
  128. if device.Name == s.name {
  129. // is it settable ?
  130. if ok, err := s.isSettable(allowedSettableFieldsDevices, device.Settable); err != nil {
  131. return err
  132. } else if !ok {
  133. return fmt.Errorf("%q is not settable", s.prettyName())
  134. }
  135. // it is, so lets update the settings in memory
  136. *device.Path = s.value
  137. continue next
  138. }
  139. }
  140. // found the name in the config
  141. if p.PluginObj.Config.Args.Name == s.name {
  142. // is it settable ?
  143. if ok, err := s.isSettable(allowedSettableFieldsArgs, p.PluginObj.Config.Args.Settable); err != nil {
  144. return err
  145. } else if !ok {
  146. return fmt.Errorf("%q is not settable", s.prettyName())
  147. }
  148. // it is, so lets update the settings in memory
  149. p.PluginObj.Settings.Args = strings.Split(s.value, " ")
  150. continue next
  151. }
  152. return fmt.Errorf("setting %q not found in the plugin configuration", s.name)
  153. }
  154. return nil
  155. }
  156. // IsEnabled returns the active state of the plugin.
  157. func (p *Plugin) IsEnabled() bool {
  158. p.mu.RLock()
  159. defer p.mu.RUnlock()
  160. return p.PluginObj.Enabled
  161. }
  162. // GetID returns the plugin's ID.
  163. func (p *Plugin) GetID() string {
  164. p.mu.RLock()
  165. defer p.mu.RUnlock()
  166. return p.PluginObj.ID
  167. }
  168. // GetSocket returns the plugin socket.
  169. func (p *Plugin) GetSocket() string {
  170. p.mu.RLock()
  171. defer p.mu.RUnlock()
  172. return p.PluginObj.Config.Interface.Socket
  173. }
  174. // GetTypes returns the interface types of a plugin.
  175. func (p *Plugin) GetTypes() []types.PluginInterfaceType {
  176. p.mu.RLock()
  177. defer p.mu.RUnlock()
  178. return p.PluginObj.Config.Interface.Types
  179. }
  180. // GetRefCount returns the reference count.
  181. func (p *Plugin) GetRefCount() int {
  182. p.mu.RLock()
  183. defer p.mu.RUnlock()
  184. return p.refCount
  185. }
  186. // AddRefCount adds to reference count.
  187. func (p *Plugin) AddRefCount(count int) {
  188. p.mu.Lock()
  189. defer p.mu.Unlock()
  190. p.refCount += count
  191. }
  192. // Acquire increments the plugin's reference count
  193. // This should be followed up by `Release()` when the plugin is no longer in use.
  194. func (p *Plugin) Acquire() {
  195. p.AddRefCount(plugingetter.Acquire)
  196. }
  197. // Release decrements the plugin's reference count
  198. // This should only be called when the plugin is no longer in use, e.g. with
  199. // via `Acquire()` or getter.Get("name", "type", plugingetter.Acquire)
  200. func (p *Plugin) Release() {
  201. p.AddRefCount(plugingetter.Release)
  202. }