mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
* update fsouza bindings to get https://github.com/fsouza/go-dockerclient/pull/776 * add memory swappiness setting to 0 without this, is vm.swappiness is not turned off, then it allows containers to use unlimited (up to host max) anonymous swap space on the host. this behavior is not what we want, particularly for getting tests to pass on everybody's dev environment, but we don't really want this behavior in any case. * fix pids
418 lines
13 KiB
Go
418 lines
13 KiB
Go
// Copyright 2018 go-dockerclient authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package docker
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"io/ioutil"
|
|
"net/http"
|
|
)
|
|
|
|
// PluginPrivilege represents a privilege for a plugin.
|
|
type PluginPrivilege struct {
|
|
Name string `json:"Name,omitempty" yaml:"Name,omitempty" toml:"Name,omitempty"`
|
|
Description string `json:"Description,omitempty" yaml:"Description,omitempty" toml:"Description,omitempty"`
|
|
Value []string `json:"Value,omitempty" yaml:"Value,omitempty" toml:"Value,omitempty"`
|
|
}
|
|
|
|
// InstallPluginOptions specify parameters to the InstallPlugins function.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
type InstallPluginOptions struct {
|
|
Remote string
|
|
Name string
|
|
Plugins []PluginPrivilege `qs:"-"`
|
|
|
|
Auth AuthConfiguration
|
|
|
|
Context context.Context
|
|
}
|
|
|
|
// InstallPlugins installs a plugin or returns an error in case of failure.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
func (c *Client) InstallPlugins(opts InstallPluginOptions) error {
|
|
path := "/plugins/pull?" + queryString(opts)
|
|
resp, err := c.do("POST", path, doOptions{
|
|
data: opts.Plugins,
|
|
context: opts.Context,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
resp.Body.Close()
|
|
return nil
|
|
}
|
|
|
|
// PluginSettings stores plugin settings.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
type PluginSettings struct {
|
|
Env []string `json:"Env,omitempty" yaml:"Env,omitempty" toml:"Env,omitempty"`
|
|
Args []string `json:"Args,omitempty" yaml:"Args,omitempty" toml:"Args,omitempty"`
|
|
Devices []string `json:"Devices,omitempty" yaml:"Devices,omitempty" toml:"Devices,omitempty"`
|
|
}
|
|
|
|
// PluginInterface stores plugin interface.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
type PluginInterface struct {
|
|
Types []string `json:"Types,omitempty" yaml:"Types,omitempty" toml:"Types,omitempty"`
|
|
Socket string `json:"Socket,omitempty" yaml:"Socket,omitempty" toml:"Socket,omitempty"`
|
|
}
|
|
|
|
// PluginNetwork stores plugin network type.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
type PluginNetwork struct {
|
|
Type string `json:"Type,omitempty" yaml:"Type,omitempty" toml:"Type,omitempty"`
|
|
}
|
|
|
|
// PluginLinux stores plugin linux setting.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
type PluginLinux struct {
|
|
Capabilities []string `json:"Capabilities,omitempty" yaml:"Capabilities,omitempty" toml:"Capabilities,omitempty"`
|
|
AllowAllDevices bool `json:"AllowAllDevices,omitempty" yaml:"AllowAllDevices,omitempty" toml:"AllowAllDevices,omitempty"`
|
|
Devices []PluginLinuxDevices `json:"Devices,omitempty" yaml:"Devices,omitempty" toml:"Devices,omitempty"`
|
|
}
|
|
|
|
// PluginLinuxDevices stores plugin linux device setting.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
type PluginLinuxDevices struct {
|
|
Name string `json:"Name,omitempty" yaml:"Name,omitempty" toml:"Name,omitempty"`
|
|
Description string `json:"Documentation,omitempty" yaml:"Documentation,omitempty" toml:"Documentation,omitempty"`
|
|
Settable []string `json:"Settable,omitempty" yaml:"Settable,omitempty" toml:"Settable,omitempty"`
|
|
Path string `json:"Path,omitempty" yaml:"Path,omitempty" toml:"Path,omitempty"`
|
|
}
|
|
|
|
// PluginEnv stores plugin environment.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
type PluginEnv struct {
|
|
Name string `json:"Name,omitempty" yaml:"Name,omitempty" toml:"Name,omitempty"`
|
|
Description string `json:"Description,omitempty" yaml:"Description,omitempty" toml:"Description,omitempty"`
|
|
Settable []string `json:"Settable,omitempty" yaml:"Settable,omitempty" toml:"Settable,omitempty"`
|
|
Value string `json:"Value,omitempty" yaml:"Value,omitempty" toml:"Value,omitempty"`
|
|
}
|
|
|
|
// PluginArgs stores plugin arguments.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
type PluginArgs struct {
|
|
Name string `json:"Name,omitempty" yaml:"Name,omitempty" toml:"Name,omitempty"`
|
|
Description string `json:"Description,omitempty" yaml:"Description,omitempty" toml:"Description,omitempty"`
|
|
Settable []string `json:"Settable,omitempty" yaml:"Settable,omitempty" toml:"Settable,omitempty"`
|
|
Value []string `json:"Value,omitempty" yaml:"Value,omitempty" toml:"Value,omitempty"`
|
|
}
|
|
|
|
// PluginUser stores plugin user.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
type PluginUser struct {
|
|
UID int32 `json:"UID,omitempty" yaml:"UID,omitempty" toml:"UID,omitempty"`
|
|
GID int32 `json:"GID,omitempty" yaml:"GID,omitempty" toml:"GID,omitempty"`
|
|
}
|
|
|
|
// PluginConfig stores plugin config.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
type PluginConfig struct {
|
|
Description string `json:"Description,omitempty" yaml:"Description,omitempty" toml:"Description,omitempty"`
|
|
Documentation string
|
|
Interface PluginInterface `json:"Interface,omitempty" yaml:"Interface,omitempty" toml:"Interface,omitempty"`
|
|
Entrypoint []string `json:"Entrypoint,omitempty" yaml:"Entrypoint,omitempty" toml:"Entrypoint,omitempty"`
|
|
WorkDir string `json:"WorkDir,omitempty" yaml:"WorkDir,omitempty" toml:"WorkDir,omitempty"`
|
|
User PluginUser `json:"User,omitempty" yaml:"User,omitempty" toml:"User,omitempty"`
|
|
Network PluginNetwork `json:"Network,omitempty" yaml:"Network,omitempty" toml:"Network,omitempty"`
|
|
Linux PluginLinux `json:"Linux,omitempty" yaml:"Linux,omitempty" toml:"Linux,omitempty"`
|
|
PropagatedMount string `json:"PropagatedMount,omitempty" yaml:"PropagatedMount,omitempty" toml:"PropagatedMount,omitempty"`
|
|
Mounts []Mount `json:"Mounts,omitempty" yaml:"Mounts,omitempty" toml:"Mounts,omitempty"`
|
|
Env []PluginEnv `json:"Env,omitempty" yaml:"Env,omitempty" toml:"Env,omitempty"`
|
|
Args PluginArgs `json:"Args,omitempty" yaml:"Args,omitempty" toml:"Args,omitempty"`
|
|
}
|
|
|
|
// PluginDetail specify results from the ListPlugins function.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
type PluginDetail struct {
|
|
ID string `json:"Id,omitempty" yaml:"Id,omitempty" toml:"Id,omitempty"`
|
|
Name string `json:"Name,omitempty" yaml:"Name,omitempty" toml:"Name,omitempty"`
|
|
Tag string `json:"Tag,omitempty" yaml:"Tag,omitempty" toml:"Tag,omitempty"`
|
|
Active bool `json:"Enabled,omitempty" yaml:"Active,omitempty" toml:"Active,omitempty"`
|
|
Settings PluginSettings `json:"Settings,omitempty" yaml:"Settings,omitempty" toml:"Settings,omitempty"`
|
|
Config PluginConfig `json:"Config,omitempty" yaml:"Config,omitempty" toml:"Config,omitempty"`
|
|
}
|
|
|
|
// ListPlugins returns pluginDetails or an error.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
func (c *Client) ListPlugins(ctx context.Context) ([]PluginDetail, error) {
|
|
resp, err := c.do("GET", "/plugins", doOptions{
|
|
context: ctx,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
pluginDetails := make([]PluginDetail, 0)
|
|
if err := json.NewDecoder(resp.Body).Decode(&pluginDetails); err != nil {
|
|
return nil, err
|
|
}
|
|
return pluginDetails, nil
|
|
}
|
|
|
|
// ListFilteredPluginsOptions specify parameters to the ListFilteredPlugins function.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
type ListFilteredPluginsOptions struct {
|
|
Filters map[string][]string
|
|
Context context.Context
|
|
}
|
|
|
|
// ListFilteredPlugins returns pluginDetails or an error.
|
|
//
|
|
// See https://goo.gl/rmdmWg for more details.
|
|
func (c *Client) ListFilteredPlugins(opts ListFilteredPluginsOptions) ([]PluginDetail, error) {
|
|
path := "/plugins/json?" + queryString(opts)
|
|
resp, err := c.do("GET", path, doOptions{
|
|
context: opts.Context,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
pluginDetails := make([]PluginDetail, 0)
|
|
if err := json.NewDecoder(resp.Body).Decode(&pluginDetails); err != nil {
|
|
return nil, err
|
|
}
|
|
return pluginDetails, nil
|
|
}
|
|
|
|
// GetPluginPrivileges returns pulginPrivileges or an error.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
func (c *Client) GetPluginPrivileges(name string, ctx context.Context) ([]PluginPrivilege, error) {
|
|
resp, err := c.do("GET", "/plugins/privileges?remote="+name, doOptions{
|
|
context: ctx,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
var pluginPrivileges []PluginPrivilege
|
|
if err := json.NewDecoder(resp.Body).Decode(&pluginPrivileges); err != nil {
|
|
return nil, err
|
|
}
|
|
return pluginPrivileges, nil
|
|
}
|
|
|
|
// InspectPlugins returns a pluginDetail or an error.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
func (c *Client) InspectPlugins(name string, ctx context.Context) (*PluginDetail, error) {
|
|
resp, err := c.do("GET", "/plugins/"+name+"/json", doOptions{
|
|
context: ctx,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
if err != nil {
|
|
if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
|
|
return nil, &NoSuchPlugin{ID: name}
|
|
}
|
|
return nil, err
|
|
}
|
|
resp.Body.Close()
|
|
var pluginDetail PluginDetail
|
|
if err := json.NewDecoder(resp.Body).Decode(&pluginDetail); err != nil {
|
|
return nil, err
|
|
}
|
|
return &pluginDetail, nil
|
|
}
|
|
|
|
// RemovePluginOptions specify parameters to the RemovePlugin function.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
type RemovePluginOptions struct {
|
|
// The Name of the plugin.
|
|
Name string `qs:"-"`
|
|
|
|
Force bool `qs:"force"`
|
|
Context context.Context
|
|
}
|
|
|
|
// RemovePlugin returns a PluginDetail or an error.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
func (c *Client) RemovePlugin(opts RemovePluginOptions) (*PluginDetail, error) {
|
|
path := "/plugins/" + opts.Name + "?" + queryString(opts)
|
|
resp, err := c.do("DELETE", path, doOptions{context: opts.Context})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
if err != nil {
|
|
if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
|
|
return nil, &NoSuchPlugin{ID: opts.Name}
|
|
}
|
|
return nil, err
|
|
}
|
|
resp.Body.Close()
|
|
var pluginDetail PluginDetail
|
|
if err := json.NewDecoder(resp.Body).Decode(&pluginDetail); err != nil {
|
|
return nil, err
|
|
}
|
|
return &pluginDetail, nil
|
|
}
|
|
|
|
// EnablePluginOptions specify parameters to the EnablePlugin function.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
type EnablePluginOptions struct {
|
|
// The Name of the plugin.
|
|
Name string `qs:"-"`
|
|
Timeout int64 `qs:"timeout"`
|
|
|
|
Context context.Context
|
|
}
|
|
|
|
// EnablePlugin enables plugin that opts point or returns an error.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
func (c *Client) EnablePlugin(opts EnablePluginOptions) error {
|
|
path := "/plugins/" + opts.Name + "/enable?" + queryString(opts)
|
|
resp, err := c.do("POST", path, doOptions{context: opts.Context})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
resp.Body.Close()
|
|
return nil
|
|
}
|
|
|
|
// DisablePluginOptions specify parameters to the DisablePlugin function.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
type DisablePluginOptions struct {
|
|
// The Name of the plugin.
|
|
Name string `qs:"-"`
|
|
|
|
Context context.Context
|
|
}
|
|
|
|
// DisablePlugin disables plugin that opts point or returns an error.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
func (c *Client) DisablePlugin(opts DisablePluginOptions) error {
|
|
path := "/plugins/" + opts.Name + "/disable"
|
|
resp, err := c.do("POST", path, doOptions{context: opts.Context})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
resp.Body.Close()
|
|
return nil
|
|
}
|
|
|
|
// CreatePluginOptions specify parameters to the CreatePlugin function.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
type CreatePluginOptions struct {
|
|
// The Name of the plugin.
|
|
Name string `qs:"name"`
|
|
// Path to tar containing plugin
|
|
Path string `qs:"-"`
|
|
|
|
Context context.Context
|
|
}
|
|
|
|
// CreatePlugin creates plugin that opts point or returns an error.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
func (c *Client) CreatePlugin(opts CreatePluginOptions) (string, error) {
|
|
path := "/plugins/create?" + queryString(opts)
|
|
resp, err := c.do("POST", path, doOptions{
|
|
data: opts.Path,
|
|
context: opts.Context,
|
|
})
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer resp.Body.Close()
|
|
containerNameBytes, err := ioutil.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return string(containerNameBytes), nil
|
|
}
|
|
|
|
// PushPluginOptions specify parameters to PushPlugin function.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
type PushPluginOptions struct {
|
|
// The Name of the plugin.
|
|
Name string
|
|
|
|
Context context.Context
|
|
}
|
|
|
|
// PushPlugin pushes plugin that opts point or returns an error.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
func (c *Client) PushPlugin(opts PushPluginOptions) error {
|
|
path := "/plugins/" + opts.Name + "/push"
|
|
resp, err := c.do("POST", path, doOptions{context: opts.Context})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
resp.Body.Close()
|
|
return nil
|
|
}
|
|
|
|
// ConfigurePluginOptions specify parameters to the ConfigurePlugin
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
type ConfigurePluginOptions struct {
|
|
// The Name of the plugin.
|
|
Name string `qs:"name"`
|
|
Envs []string
|
|
|
|
Context context.Context
|
|
}
|
|
|
|
// ConfigurePlugin configures plugin that opts point or returns an error.
|
|
//
|
|
// See https://goo.gl/C4t7Tz for more details.
|
|
func (c *Client) ConfigurePlugin(opts ConfigurePluginOptions) error {
|
|
path := "/plugins/" + opts.Name + "/set"
|
|
resp, err := c.do("POST", path, doOptions{
|
|
data: opts.Envs,
|
|
context: opts.Context,
|
|
})
|
|
if err != nil {
|
|
if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
|
|
return &NoSuchPlugin{ID: opts.Name}
|
|
}
|
|
return err
|
|
}
|
|
resp.Body.Close()
|
|
return nil
|
|
}
|
|
|
|
// NoSuchPlugin is the error returned when a given plugin does not exist.
|
|
type NoSuchPlugin struct {
|
|
ID string
|
|
Err error
|
|
}
|
|
|
|
func (err *NoSuchPlugin) Error() string {
|
|
if err.Err != nil {
|
|
return err.Err.Error()
|
|
}
|
|
return "No such plugin: " + err.ID
|
|
}
|