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