|
| 1 | +// Copyright 2013 go-dockerclient authors. All rights reserved. |
| 2 | +// Use of this source code is governed by a BSD-style |
| 3 | +// license that can be found in the LICENSE file. |
| 4 | + |
| 5 | +package docker |
| 6 | + |
| 7 | +import ( |
| 8 | + "encoding/json" |
| 9 | + "net/http" |
| 10 | + "net/url" |
| 11 | + "golang.org/x/net/context" |
| 12 | + ioutil "io/ioutil" |
| 13 | +) |
| 14 | + |
| 15 | + |
| 16 | +// PluginPrivilege represents a privilege for a plugin. |
| 17 | +type PluginPrivilege struct { |
| 18 | + Name string `json:"Name,omitempty" yaml:"Name,omitempty" toml:"Name,omitempty"` |
| 19 | + Description string `json:"Description,omitempty" yaml:"Description,omitempty" toml:"Description,omitempty"` |
| 20 | + Value []string `json:"Value,omitempty" yaml:"Value,omitempty" toml:"Value,omitempty"` |
| 21 | +} |
| 22 | + |
| 23 | +type InstallPluginOptions struct { |
| 24 | + Remote string |
| 25 | + Name string |
| 26 | + Plugins []PluginPrivilege |
| 27 | + Context context.Context |
| 28 | +} |
| 29 | + |
| 30 | +// ListContainers returns a slice of containers matching the given criteria. |
| 31 | +// |
| 32 | +// See https://goo.gl/kaOHGw for more details. |
| 33 | +func (c *Client) InstallPlugins(opts InstallPluginOptions, auth AuthConfiguration) (error) { |
| 34 | + params := make(url.Values) |
| 35 | + params.Set("remote", opts.Remote) |
| 36 | + if opts.Name != ""{ |
| 37 | + params.Set("name", opts.Name) |
| 38 | + } |
| 39 | + path := "/plugins/pull?" + queryString(params) |
| 40 | + resp, err := c.do("POST", path, doOptions{ |
| 41 | + data: opts.Plugins, |
| 42 | + context: opts.Context, |
| 43 | + }) |
| 44 | + defer resp.Body.Close() |
| 45 | + if err != nil {return err} |
| 46 | + return nil |
| 47 | +} |
| 48 | + |
| 49 | +type PluginSetting struct { |
| 50 | + Env []string `json:"Env,omitempty" yaml:"Env,omitempty" toml:"Env,omitempty"` |
| 51 | + Args []string `json:"Args,omitempty" yaml:"Args,omitempty" toml:"Args,omitempty"` |
| 52 | + Devices []string `json:"Devices,omitempty" yaml:"Devices,omitempty" toml:"Devices,omitempty"` |
| 53 | +} |
| 54 | + |
| 55 | +type PluginInterfaceType struct { |
| 56 | + Preifx string |
| 57 | + Capability string |
| 58 | + Version string |
| 59 | +} |
| 60 | + |
| 61 | +type PluginInterface struct { |
| 62 | + Types []PluginInterfaceType |
| 63 | + Socket string |
| 64 | +} |
| 65 | + |
| 66 | +type PluginNetwork struct { |
| 67 | + Type string |
| 68 | +} |
| 69 | +type PluginLinux struct { |
| 70 | + Capabilities []string |
| 71 | + AllowAllDevices bool |
| 72 | + Devices []PluginLinuxDevices |
| 73 | +} |
| 74 | + |
| 75 | +type PluginLinuxDevices struct { |
| 76 | + Name string |
| 77 | + Description string |
| 78 | + Settable []string |
| 79 | + Path string |
| 80 | +} |
| 81 | +type PluginEnv struct { |
| 82 | + Name string |
| 83 | + Description string |
| 84 | + Settable []string |
| 85 | + Value string |
| 86 | +} |
| 87 | +type PluginArgs struct { |
| 88 | + Name string |
| 89 | + Description string |
| 90 | + Settable []string |
| 91 | + Value []string |
| 92 | +} |
| 93 | + |
| 94 | +type PluginUser struct { |
| 95 | + UID int32 |
| 96 | + GID int32 |
| 97 | +} |
| 98 | + |
| 99 | +type PluginConfig struct { |
| 100 | + Description string `json:"Description,omitempty" yaml:"Description,omitempty" toml:"Description,omitempty"` |
| 101 | + Documentation string `json:"Documentation,omitempty" yaml:"Documentation,omitempty" toml:"Documentation,omitempty"` |
| 102 | + Interface PluginInterface |
| 103 | + Entrypoint []string |
| 104 | + WorkDir string |
| 105 | + User PluginUser |
| 106 | + Network PluginNetwork |
| 107 | + Linux PluginLinux |
| 108 | + PropagatedMount string |
| 109 | + Mounts []Mount |
| 110 | + Env []PluginEnv |
| 111 | + Args PluginArgs |
| 112 | +} |
| 113 | + |
| 114 | +type PluginDetail struct { |
| 115 | + Id string `json:"Id,omitempty" yaml:"Id,omitempty" toml:"Id,omitempty"` |
| 116 | + Name string `json:"Name,omitempty" yaml:"Name,omitempty" toml:"Name,omitempty"` |
| 117 | + Tag string `json:"Tag,omitempty" yaml:"Tag,omitempty" toml:"Tag,omitempty"` |
| 118 | + Active bool `json:"Active,omitempty" yaml:"Active,omitempty" toml:"Active,omitempty"` |
| 119 | + Settings PluginSetting `json:"Settings,omitempty" yaml:"Settings,omitempty" toml:"Settings,omitempty"` |
| 120 | + Config Config `json:"Config,omitempty" yaml:"Config,omitempty" toml:"Config,omitempty"` |
| 121 | +} |
| 122 | + |
| 123 | +func (c *Client) ListPlugins()([]PluginDetail, error) { |
| 124 | + resp, err := c.do("GET", "/plugins",doOptions{}) |
| 125 | + if err != nil { |
| 126 | + return nil, err |
| 127 | + } |
| 128 | + defer resp.Body.Close() |
| 129 | + pluginDetails := make([]PluginDetail,0) |
| 130 | + if err := json.NewDecoder(resp.Body).Decode(&pluginDetails); err != nil { |
| 131 | + return nil, err |
| 132 | + } |
| 133 | + return pluginDetails, nil |
| 134 | +} |
| 135 | + |
| 136 | + |
| 137 | +func (c *Client) GetPluginPrivileges(name string)([]PluginPrivilege, error) { |
| 138 | + resp, err := c.do("GET", "/plugins/privileges?"+name,doOptions{}) |
| 139 | + if err != nil { |
| 140 | + return nil, err |
| 141 | + } |
| 142 | + defer resp.Body.Close() |
| 143 | + pluginPrivileges := make([]PluginPrivilege,0) |
| 144 | + if err := json.NewDecoder(resp.Body).Decode(&pluginPrivileges); err != nil { |
| 145 | + return nil, err |
| 146 | + } |
| 147 | + return pluginPrivileges, nil |
| 148 | +} |
| 149 | + |
| 150 | +type RemovePluginOptions struct { |
| 151 | + // The ID of the container. |
| 152 | + Name string `qs:"-"` |
| 153 | + |
| 154 | + // A flag that indicates whether Docker should remove the plugin |
| 155 | + // even if it is currently used. |
| 156 | + Force bool `qs:"force"` |
| 157 | + Context context.Context |
| 158 | +} |
| 159 | + |
| 160 | +func (c *Client) RemovePlugin(opts RemovePluginOptions)(*PluginDetail, error) { |
| 161 | + path := "/plugins/"+opts.Name+"?"+queryString(opts) |
| 162 | + resp, err := c.do("DELETE", path, doOptions{context: opts.Context}) |
| 163 | + if err != nil { |
| 164 | + return nil, err |
| 165 | + } |
| 166 | + defer resp.Body.Close() |
| 167 | + if err != nil { |
| 168 | + if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { |
| 169 | + return nil,&NoSuchPlugin{ID: opts.Name} |
| 170 | + } |
| 171 | + return nil,err |
| 172 | + } |
| 173 | + resp.Body.Close() |
| 174 | + var pluginDetail PluginDetail |
| 175 | + if err := json.NewDecoder(resp.Body).Decode(&pluginDetail); err != nil { |
| 176 | + return nil, err |
| 177 | + } |
| 178 | + return &pluginDetail, nil |
| 179 | +} |
| 180 | + |
| 181 | + |
| 182 | +type EnablePluginOptions struct { |
| 183 | + // The ID of the container. |
| 184 | + Name string `qs:"-"` |
| 185 | + Timeout int64 `qs:"timeout"` |
| 186 | + |
| 187 | + Context context.Context |
| 188 | +} |
| 189 | + |
| 190 | +func (c *Client) EnablePlugin(opts EnablePluginOptions)(error) { |
| 191 | + path := "/plugins/"+opts.Name+"/enable?"+queryString(opts) |
| 192 | + resp, err := c.do("POST", path, doOptions{context: opts.Context}) |
| 193 | + defer resp.Body.Close() |
| 194 | + if err != nil { |
| 195 | + return err |
| 196 | + } |
| 197 | + resp.Body.Close() |
| 198 | + return nil |
| 199 | +} |
| 200 | + |
| 201 | +type DisablePluginOptions struct { |
| 202 | + // The ID of the container. |
| 203 | + Name string `qs:"-"` |
| 204 | + |
| 205 | + Context context.Context |
| 206 | +} |
| 207 | + |
| 208 | +func (c *Client) DisablePlugin(opts DisablePluginOptions)(error) { |
| 209 | + path := "/plugins/"+opts.Name+"/disable" |
| 210 | + resp, err := c.do("POST", path, doOptions{context: opts.Context}) |
| 211 | + defer resp.Body.Close() |
| 212 | + if err != nil { |
| 213 | + return err |
| 214 | + } |
| 215 | + resp.Body.Close() |
| 216 | + return nil |
| 217 | +} |
| 218 | + |
| 219 | +type CreatePluginOptions struct { |
| 220 | + // The Name of the container. |
| 221 | + Name string `qs:"name"` |
| 222 | + // Path to tar containing plugin |
| 223 | + Path string `qs:"-"` |
| 224 | + |
| 225 | + Context context.Context |
| 226 | +} |
| 227 | + |
| 228 | +func (c *Client) CreatePlugin(opts CreatePluginOptions)(string,error) { |
| 229 | + path := "/plugins/create?"+queryString(opts.Name) |
| 230 | + resp, err := c.do("POST", path, doOptions{ |
| 231 | + data: opts.Path, |
| 232 | + context: opts.Context}) |
| 233 | + defer resp.Body.Close() |
| 234 | + if err != nil { |
| 235 | + return "",err |
| 236 | + } |
| 237 | + containerNameBytes, err := ioutil.ReadAll(resp.Body) |
| 238 | + if err != nil { |
| 239 | + return "",err |
| 240 | + } |
| 241 | + return string(containerNameBytes),nil |
| 242 | +} |
| 243 | + |
| 244 | +type PushPluginOptions struct { |
| 245 | + // The Name of the container. |
| 246 | + Name string |
| 247 | + |
| 248 | + Context context.Context |
| 249 | +} |
| 250 | + |
| 251 | +func (c *Client) PushPlugin(opts PushPluginOptions)(error) { |
| 252 | + path := "/plugins/"+opts.Name+"/push" |
| 253 | + resp, err := c.do("POST", path, doOptions{context: opts.Context}) |
| 254 | + defer resp.Body.Close() |
| 255 | + if err != nil { |
| 256 | + return err |
| 257 | + } |
| 258 | + return nil |
| 259 | +} |
| 260 | + |
| 261 | +type ConfigurePluginOptions struct { |
| 262 | + // The Name of the container. |
| 263 | + Name string `qs:"name"` |
| 264 | + Envs []string |
| 265 | + |
| 266 | + Context context.Context |
| 267 | +} |
| 268 | + |
| 269 | +func (c *Client) ConfigurePlugin(opts ConfigurePluginOptions)(error) { |
| 270 | + path := "/plugins/"+opts.Name+"/set" |
| 271 | + resp, err := c.do("POST", path, doOptions{ |
| 272 | + data:opts.Envs, |
| 273 | + context: opts.Context, |
| 274 | + }) |
| 275 | + defer resp.Body.Close() |
| 276 | + if err != nil { |
| 277 | + if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound { |
| 278 | + return &NoSuchPlugin{ID: opts.Name} |
| 279 | + } |
| 280 | + return err |
| 281 | + } |
| 282 | + return nil |
| 283 | +} |
| 284 | + |
| 285 | +// NoSuchPlugin is the error returned when a given plugin does not exist. |
| 286 | +type NoSuchPlugin struct { |
| 287 | + ID string |
| 288 | + Err error |
| 289 | +} |
| 290 | + |
| 291 | +func (err *NoSuchPlugin) Error() string { |
| 292 | + if err.Err != nil { |
| 293 | + return err.Err.Error() |
| 294 | + } |
| 295 | + return "No such plugin: " + err.ID |
| 296 | +} |
0 commit comments