plugin.go 7.0 KB

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