1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

fix docker swarm init/update --secret

Signed-off-by: Victor Vieux <vieux@docker.com>
This commit is contained in:
Victor Vieux 2016-06-15 14:30:54 -07:00
parent 011774e6f0
commit 085895342c
15 changed files with 159 additions and 66 deletions

View file

@ -41,7 +41,8 @@ func runRestart(dockerCli *client.DockerCli, opts *restartOptions) error {
ctx := context.Background() ctx := context.Background()
var errs []string var errs []string
for _, name := range opts.containers { for _, name := range opts.containers {
if err := dockerCli.Client().ContainerRestart(ctx, name, time.Duration(opts.nSeconds)*time.Second); err != nil { timeout := time.Duration(opts.nSeconds) * time.Second
if err := dockerCli.Client().ContainerRestart(ctx, name, &timeout); err != nil {
errs = append(errs, err.Error()) errs = append(errs, err.Error())
} else { } else {
fmt.Fprintf(dockerCli.Out(), "%s\n", name) fmt.Fprintf(dockerCli.Out(), "%s\n", name)

View file

@ -43,7 +43,8 @@ func runStop(dockerCli *client.DockerCli, opts *stopOptions) error {
var errs []string var errs []string
for _, container := range opts.containers { for _, container := range opts.containers {
if err := dockerCli.Client().ContainerStop(ctx, container, time.Duration(opts.time)*time.Second); err != nil { timeout := time.Duration(opts.time) * time.Second
if err := dockerCli.Client().ContainerStop(ctx, container, &timeout); err != nil {
errs = append(errs, err.Error()) errs = append(errs, err.Error())
} else { } else {
fmt.Fprintf(dockerCli.Out(), "%s\n", container) fmt.Fprintf(dockerCli.Out(), "%s\n", container)

View file

@ -9,6 +9,7 @@ import (
"github.com/docker/docker/cli" "github.com/docker/docker/cli"
"github.com/docker/engine-api/types/swarm" "github.com/docker/engine-api/types/swarm"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/pflag"
) )
type initOptions struct { type initOptions struct {
@ -19,6 +20,7 @@ type initOptions struct {
} }
func newInitCommand(dockerCli *client.DockerCli) *cobra.Command { func newInitCommand(dockerCli *client.DockerCli) *cobra.Command {
var flags *pflag.FlagSet
opts := initOptions{ opts := initOptions{
listenAddr: NewNodeAddrOption(), listenAddr: NewNodeAddrOption(),
autoAccept: NewAutoAcceptOption(), autoAccept: NewAutoAcceptOption(),
@ -29,11 +31,11 @@ func newInitCommand(dockerCli *client.DockerCli) *cobra.Command {
Short: "Initialize a Swarm.", Short: "Initialize a Swarm.",
Args: cli.NoArgs, Args: cli.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
return runInit(dockerCli, opts) return runInit(dockerCli, flags, opts)
}, },
} }
flags := cmd.Flags() flags = cmd.Flags()
flags.Var(&opts.listenAddr, "listen-addr", "Listen address") flags.Var(&opts.listenAddr, "listen-addr", "Listen address")
flags.Var(&opts.autoAccept, "auto-accept", "Auto acceptance policy (worker, manager, or none)") flags.Var(&opts.autoAccept, "auto-accept", "Auto acceptance policy (worker, manager, or none)")
flags.StringVar(&opts.secret, "secret", "", "Set secret value needed to accept nodes into cluster") flags.StringVar(&opts.secret, "secret", "", "Set secret value needed to accept nodes into cluster")
@ -41,7 +43,7 @@ func newInitCommand(dockerCli *client.DockerCli) *cobra.Command {
return cmd return cmd
} }
func runInit(dockerCli *client.DockerCli, opts initOptions) error { func runInit(dockerCli *client.DockerCli, flags *pflag.FlagSet, opts initOptions) error {
client := dockerCli.Client() client := dockerCli.Client()
ctx := context.Background() ctx := context.Background()
@ -50,8 +52,11 @@ func runInit(dockerCli *client.DockerCli, opts initOptions) error {
ForceNewCluster: opts.forceNewCluster, ForceNewCluster: opts.forceNewCluster,
} }
req.Spec.AcceptancePolicy.Policies = opts.autoAccept.Policies(opts.secret) if flags.Changed("secret") {
req.Spec.AcceptancePolicy.Policies = opts.autoAccept.Policies(&opts.secret)
} else {
req.Spec.AcceptancePolicy.Policies = opts.autoAccept.Policies(nil)
}
nodeID, err := client.SwarmInit(ctx, req) nodeID, err := client.SwarmInit(ctx, req)
if err != nil { if err != nil {
return err return err

View file

@ -102,7 +102,7 @@ func (o *AutoAcceptOption) Type() string {
} }
// Policies returns a representation of this option for the api // Policies returns a representation of this option for the api
func (o *AutoAcceptOption) Policies(secret string) []swarm.Policy { func (o *AutoAcceptOption) Policies(secret *string) []swarm.Policy {
policies := []swarm.Policy{} policies := []swarm.Policy{}
for _, p := range defaultPolicies { for _, p := range defaultPolicies {
if len(o.values) != 0 { if len(o.values) != 0 {

View file

@ -54,6 +54,7 @@ func runUpdate(dockerCli *client.DockerCli, flags *pflag.FlagSet, opts updateOpt
if err != nil { if err != nil {
return err return err
} }
err = client.SwarmUpdate(ctx, swarm.Version, swarm.Spec) err = client.SwarmUpdate(ctx, swarm.Version, swarm.Spec)
if err != nil { if err != nil {
return err return err
@ -68,18 +69,17 @@ func mergeSwarm(swarm *swarm.Swarm, flags *pflag.FlagSet) error {
if flags.Changed("auto-accept") { if flags.Changed("auto-accept") {
value := flags.Lookup("auto-accept").Value.(*AutoAcceptOption) value := flags.Lookup("auto-accept").Value.(*AutoAcceptOption)
if len(spec.AcceptancePolicy.Policies) > 0 { spec.AcceptancePolicy.Policies = value.Policies(nil)
spec.AcceptancePolicy.Policies = value.Policies(spec.AcceptancePolicy.Policies[0].Secret)
} else {
spec.AcceptancePolicy.Policies = value.Policies("")
}
} }
var psecret *string
if flags.Changed("secret") { if flags.Changed("secret") {
secret, _ := flags.GetString("secret") secret, _ := flags.GetString("secret")
for _, policy := range spec.AcceptancePolicy.Policies { psecret = &secret
policy.Secret = secret }
}
for i := range spec.AcceptancePolicy.Policies {
spec.AcceptancePolicy.Policies[i].Secret = psecret
} }
if flags.Changed("task-history-limit") { if flags.Changed("task-history-limit") {

View file

@ -444,12 +444,12 @@ func (c *Cluster) Update(version uint64, spec types.Spec) error {
return ErrNoManager return ErrNoManager
} }
swarmSpec, err := convert.SwarmSpecToGRPC(spec) swarm, err := getSwarm(c.getRequestContext(), c.client)
if err != nil { if err != nil {
return err return err
} }
swarm, err := getSwarm(c.getRequestContext(), c.client) swarmSpec, err := convert.SwarmSpecToGRPCandMerge(spec, &swarm.Spec)
if err != nil { if err != nil {
return err return err
} }
@ -1030,7 +1030,7 @@ func initAcceptancePolicy(node *swarmagent.Node, acceptancePolicy types.Acceptan
} }
spec := &cluster.Spec spec := &cluster.Spec
if err := convert.SwarmSpecUpdateAcceptancePolicy(spec, acceptancePolicy); err != nil { if err := convert.SwarmSpecUpdateAcceptancePolicy(spec, acceptancePolicy, nil); err != nil {
return fmt.Errorf("error updating cluster settings: %v", err) return fmt.Errorf("error updating cluster settings: %v", err)
} }
_, err := client.UpdateCluster(ctx, &swarmapi.UpdateClusterRequest{ _, err := client.UpdateCluster(ctx, &swarmapi.UpdateClusterRequest{

View file

@ -49,7 +49,8 @@ func SwarmFromGRPC(c swarmapi.Cluster) types.Swarm {
Autoaccept: policy.Autoaccept, Autoaccept: policy.Autoaccept,
} }
if policy.Secret != nil { if policy.Secret != nil {
p.Secret = string(policy.Secret.Data) secret := string(policy.Secret.Data)
p.Secret = &secret
} }
swarm.Spec.AcceptancePolicy.Policies = append(swarm.Spec.AcceptancePolicy.Policies, p) swarm.Spec.AcceptancePolicy.Policies = append(swarm.Spec.AcceptancePolicy.Policies, p)
} }
@ -57,8 +58,8 @@ func SwarmFromGRPC(c swarmapi.Cluster) types.Swarm {
return swarm return swarm
} }
// SwarmSpecToGRPC converts a Spec to a grpc ClusterSpec. // SwarmSpecToGRPCandMerge converts a Spec to a grpc ClusterSpec and merge AcceptancePolicy from an existing grpc ClusterSpec if provided.
func SwarmSpecToGRPC(s types.Spec) (swarmapi.ClusterSpec, error) { func SwarmSpecToGRPCandMerge(s types.Spec, existingSpec *swarmapi.ClusterSpec) (swarmapi.ClusterSpec, error) {
spec := swarmapi.ClusterSpec{ spec := swarmapi.ClusterSpec{
Annotations: swarmapi.Annotations{ Annotations: swarmapi.Annotations{
Name: s.Name, Name: s.Name,
@ -82,14 +83,15 @@ func SwarmSpecToGRPC(s types.Spec) (swarmapi.ClusterSpec, error) {
}, },
} }
if err := SwarmSpecUpdateAcceptancePolicy(&spec, s.AcceptancePolicy); err != nil { if err := SwarmSpecUpdateAcceptancePolicy(&spec, s.AcceptancePolicy, existingSpec); err != nil {
return swarmapi.ClusterSpec{}, err return swarmapi.ClusterSpec{}, err
} }
return spec, nil return spec, nil
} }
// SwarmSpecUpdateAcceptancePolicy updates a grpc ClusterSpec using AcceptancePolicy. // SwarmSpecUpdateAcceptancePolicy updates a grpc ClusterSpec using AcceptancePolicy.
func SwarmSpecUpdateAcceptancePolicy(spec *swarmapi.ClusterSpec, acceptancePolicy types.AcceptancePolicy) error { func SwarmSpecUpdateAcceptancePolicy(spec *swarmapi.ClusterSpec, acceptancePolicy types.AcceptancePolicy, oldSpec *swarmapi.ClusterSpec) error {
spec.AcceptancePolicy.Policies = nil spec.AcceptancePolicy.Policies = nil
for _, p := range acceptancePolicy.Policies { for _, p := range acceptancePolicy.Policies {
role, ok := swarmapi.NodeRole_value[strings.ToUpper(string(p.Role))] role, ok := swarmapi.NodeRole_value[strings.ToUpper(string(p.Role))]
@ -102,11 +104,20 @@ func SwarmSpecUpdateAcceptancePolicy(spec *swarmapi.ClusterSpec, acceptancePolic
Autoaccept: p.Autoaccept, Autoaccept: p.Autoaccept,
} }
if p.Secret != "" { if p.Secret != nil {
hashPwd, _ := bcrypt.GenerateFromPassword([]byte(p.Secret), 0) if *p.Secret == "" { // if provided secret is empty, it means erase previous secret.
policy.Secret = nil
} else { // if provided secret is not empty, we generate a new one.
hashPwd, _ := bcrypt.GenerateFromPassword([]byte(*p.Secret), 0)
policy.Secret = &swarmapi.AcceptancePolicy_RoleAdmissionPolicy_HashedSecret{
Data: hashPwd,
Alg: "bcrypt",
}
}
} else if oldSecret := getOldSecret(oldSpec, policy.Role); oldSecret != nil { // else use the old one.
policy.Secret = &swarmapi.AcceptancePolicy_RoleAdmissionPolicy_HashedSecret{ policy.Secret = &swarmapi.AcceptancePolicy_RoleAdmissionPolicy_HashedSecret{
Data: hashPwd, Data: oldSecret.Data,
Alg: "bcrypt", Alg: oldSecret.Alg,
} }
} }
@ -114,3 +125,15 @@ func SwarmSpecUpdateAcceptancePolicy(spec *swarmapi.ClusterSpec, acceptancePolic
} }
return nil return nil
} }
func getOldSecret(oldSpec *swarmapi.ClusterSpec, role swarmapi.NodeRole) *swarmapi.AcceptancePolicy_RoleAdmissionPolicy_HashedSecret {
if oldSpec == nil {
return nil
}
for _, p := range oldSpec.AcceptancePolicy.Policies {
if p.Role == role {
return p.Secret
}
}
return nil
}

View file

@ -60,7 +60,7 @@ clone git golang.org/x/net 2beffdc2e92c8a3027590f898fe88f69af48a3f8 https://gith
clone git golang.org/x/sys eb2c74142fd19a79b3f237334c7384d5167b1b46 https://github.com/golang/sys.git clone git golang.org/x/sys eb2c74142fd19a79b3f237334c7384d5167b1b46 https://github.com/golang/sys.git
clone git github.com/docker/go-units 651fc226e7441360384da338d0fd37f2440ffbe3 clone git github.com/docker/go-units 651fc226e7441360384da338d0fd37f2440ffbe3
clone git github.com/docker/go-connections fa2850ff103453a9ad190da0df0af134f0314b3d clone git github.com/docker/go-connections fa2850ff103453a9ad190da0df0af134f0314b3d
clone git github.com/docker/engine-api f3b5ad20d4576de14c96603db522dec530d03f62 clone git github.com/docker/engine-api f50fbe5f9c4c8eeed591549d2c8187f4076f3717
clone git github.com/RackSec/srslog 259aed10dfa74ea2961eddd1d9847619f6e98837 clone git github.com/RackSec/srslog 259aed10dfa74ea2961eddd1d9847619f6e98837
clone git github.com/imdario/mergo 0.2.1 clone git github.com/imdario/mergo 0.2.1

View file

@ -26,11 +26,16 @@ func (d *SwarmDaemon) Init(autoAccept map[string]bool, secret string) error {
ListenAddr: d.listenAddr, ListenAddr: d.listenAddr,
} }
for _, role := range []swarm.NodeRole{swarm.NodeRoleManager, swarm.NodeRoleWorker} { for _, role := range []swarm.NodeRole{swarm.NodeRoleManager, swarm.NodeRoleWorker} {
req.Spec.AcceptancePolicy.Policies = append(req.Spec.AcceptancePolicy.Policies, swarm.Policy{ policy := swarm.Policy{
Role: role, Role: role,
Autoaccept: autoAccept[strings.ToLower(string(role))], Autoaccept: autoAccept[strings.ToLower(string(role))],
Secret: secret, }
})
if secret != "" {
policy.Secret = &secret
}
req.Spec.AcceptancePolicy.Policies = append(req.Spec.AcceptancePolicy.Policies, policy)
} }
status, out, err := d.SockRequest("POST", "/swarm/init", req) status, out, err := d.SockRequest("POST", "/swarm/init", req)
if status != http.StatusOK { if status != http.StatusOK {
@ -49,13 +54,17 @@ func (d *SwarmDaemon) Init(autoAccept map[string]bool, secret string) error {
// Join joins a current daemon with existing cluster. // Join joins a current daemon with existing cluster.
func (d *SwarmDaemon) Join(remoteAddr, secret, cahash string, manager bool) error { func (d *SwarmDaemon) Join(remoteAddr, secret, cahash string, manager bool) error {
status, out, err := d.SockRequest("POST", "/swarm/join", swarm.JoinRequest{ req := swarm.JoinRequest{
ListenAddr: d.listenAddr, ListenAddr: d.listenAddr,
RemoteAddrs: []string{remoteAddr}, RemoteAddrs: []string{remoteAddr},
Manager: manager, Manager: manager,
Secret: secret,
CACertHash: cahash, CACertHash: cahash,
}) }
if secret != "" {
req.Secret = secret
}
status, out, err := d.SockRequest("POST", "/swarm/join", req)
if status != http.StatusOK { if status != http.StatusOK {
return fmt.Errorf("joining swarm: invalid statuscode %v, %q", status, out) return fmt.Errorf("joining swarm: invalid statuscode %v, %q", status, out)
} }

View file

@ -11,9 +11,11 @@ import (
// ContainerRestart stops and starts a container again. // ContainerRestart stops and starts a container again.
// It makes the daemon to wait for the container to be up again for // It makes the daemon to wait for the container to be up again for
// a specific amount of time, given the timeout. // a specific amount of time, given the timeout.
func (cli *Client) ContainerRestart(ctx context.Context, containerID string, timeout time.Duration) error { func (cli *Client) ContainerRestart(ctx context.Context, containerID string, timeout *time.Duration) error {
query := url.Values{} query := url.Values{}
query.Set("t", timetypes.DurationToSecondsString(timeout)) if timeout != nil {
query.Set("t", timetypes.DurationToSecondsString(*timeout))
}
resp, err := cli.post(ctx, "/containers/"+containerID+"/restart", query, nil, nil) resp, err := cli.post(ctx, "/containers/"+containerID+"/restart", query, nil, nil)
ensureReaderClosed(resp) ensureReaderClosed(resp)
return err return err

View file

@ -10,9 +10,11 @@ import (
// ContainerStop stops a container without terminating the process. // ContainerStop stops a container without terminating the process.
// The process is blocked until the container stops or the timeout expires. // The process is blocked until the container stops or the timeout expires.
func (cli *Client) ContainerStop(ctx context.Context, containerID string, timeout time.Duration) error { func (cli *Client) ContainerStop(ctx context.Context, containerID string, timeout *time.Duration) error {
query := url.Values{} query := url.Values{}
query.Set("t", timetypes.DurationToSecondsString(timeout)) if timeout != nil {
query.Set("t", timetypes.DurationToSecondsString(*timeout))
}
resp, err := cli.post(ctx, "/containers/"+containerID+"/stop", query, nil, nil) resp, err := cli.post(ctx, "/containers/"+containerID+"/stop", query, nil, nil)
ensureReaderClosed(resp) ensureReaderClosed(resp)
return err return err

View file

@ -15,26 +15,21 @@ import (
// CommonAPIClient is the common methods between stable and experimental versions of APIClient. // CommonAPIClient is the common methods between stable and experimental versions of APIClient.
type CommonAPIClient interface { type CommonAPIClient interface {
ContainerAPIClient
ImageAPIClient
NodeAPIClient
NetworkAPIClient
ServiceAPIClient
SwarmAPIClient
SystemAPIClient
VolumeAPIClient
ClientVersion() string ClientVersion() string
CheckpointCreate(ctx context.Context, container string, options types.CheckpointCreateOptions) error ServerVersion(ctx context.Context) (types.Version, error)
CheckpointDelete(ctx context.Context, container string, checkpointID string) error UpdateClientVersion(v string)
CheckpointList(ctx context.Context, container string) ([]types.Checkpoint, error) }
SwarmInit(ctx context.Context, req swarm.InitRequest) (string, error)
SwarmJoin(ctx context.Context, req swarm.JoinRequest) error // ContainerAPIClient defines API client methods for the containers
SwarmLeave(ctx context.Context, force bool) error type ContainerAPIClient interface {
SwarmInspect(ctx context.Context) (swarm.Swarm, error)
SwarmUpdate(ctx context.Context, version swarm.Version, swarm swarm.Spec) error
NodeInspect(ctx context.Context, nodeID string) (swarm.Node, error)
NodeList(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error)
NodeRemove(ctx context.Context, nodeID string) error
NodeUpdate(ctx context.Context, nodeID string, version swarm.Version, node swarm.NodeSpec) error
ServiceCreate(ctx context.Context, service swarm.ServiceSpec) (types.ServiceCreateResponse, error)
ServiceInspect(ctx context.Context, serviceID string) (swarm.Service, error)
ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error)
ServiceRemove(ctx context.Context, serviceID string) error
ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec) error
TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error)
TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error)
ContainerAttach(ctx context.Context, container string, options types.ContainerAttachOptions) (types.HijackedResponse, error) ContainerAttach(ctx context.Context, container string, options types.ContainerAttachOptions) (types.HijackedResponse, error)
ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.ContainerCommitResponse, error) ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.ContainerCommitResponse, error)
ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (types.ContainerCreateResponse, error) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (types.ContainerCreateResponse, error)
@ -54,18 +49,21 @@ type CommonAPIClient interface {
ContainerRemove(ctx context.Context, container string, options types.ContainerRemoveOptions) error ContainerRemove(ctx context.Context, container string, options types.ContainerRemoveOptions) error
ContainerRename(ctx context.Context, container, newContainerName string) error ContainerRename(ctx context.Context, container, newContainerName string) error
ContainerResize(ctx context.Context, container string, options types.ResizeOptions) error ContainerResize(ctx context.Context, container string, options types.ResizeOptions) error
ContainerRestart(ctx context.Context, container string, timeout time.Duration) error ContainerRestart(ctx context.Context, container string, timeout *time.Duration) error
ContainerStatPath(ctx context.Context, container, path string) (types.ContainerPathStat, error) ContainerStatPath(ctx context.Context, container, path string) (types.ContainerPathStat, error)
ContainerStats(ctx context.Context, container string, stream bool) (io.ReadCloser, error) ContainerStats(ctx context.Context, container string, stream bool) (io.ReadCloser, error)
ContainerStart(ctx context.Context, container string, options types.ContainerStartOptions) error ContainerStart(ctx context.Context, container string, options types.ContainerStartOptions) error
ContainerStop(ctx context.Context, container string, timeout time.Duration) error ContainerStop(ctx context.Context, container string, timeout *time.Duration) error
ContainerTop(ctx context.Context, container string, arguments []string) (types.ContainerProcessList, error) ContainerTop(ctx context.Context, container string, arguments []string) (types.ContainerProcessList, error)
ContainerUnpause(ctx context.Context, container string) error ContainerUnpause(ctx context.Context, container string) error
ContainerUpdate(ctx context.Context, container string, updateConfig container.UpdateConfig) error ContainerUpdate(ctx context.Context, container string, updateConfig container.UpdateConfig) error
ContainerWait(ctx context.Context, container string) (int, error) ContainerWait(ctx context.Context, container string) (int, error)
CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error)
CopyToContainer(ctx context.Context, container, path string, content io.Reader, options types.CopyToContainerOptions) error CopyToContainer(ctx context.Context, container, path string, content io.Reader, options types.CopyToContainerOptions) error
Events(ctx context.Context, options types.EventsOptions) (io.ReadCloser, error) }
// ImageAPIClient defines API client methods for the images
type ImageAPIClient interface {
ImageBuild(ctx context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) ImageBuild(ctx context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error)
ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error)
ImageHistory(ctx context.Context, image string) ([]types.ImageHistory, error) ImageHistory(ctx context.Context, image string) ([]types.ImageHistory, error)
@ -79,7 +77,10 @@ type CommonAPIClient interface {
ImageSearch(ctx context.Context, term string, options types.ImageSearchOptions) ([]registry.SearchResult, error) ImageSearch(ctx context.Context, term string, options types.ImageSearchOptions) ([]registry.SearchResult, error)
ImageSave(ctx context.Context, images []string) (io.ReadCloser, error) ImageSave(ctx context.Context, images []string) (io.ReadCloser, error)
ImageTag(ctx context.Context, image, ref string) error ImageTag(ctx context.Context, image, ref string) error
Info(ctx context.Context) (types.Info, error) }
// NetworkAPIClient defines API client methods for the networks
type NetworkAPIClient interface {
NetworkConnect(ctx context.Context, networkID, container string, config *network.EndpointSettings) error NetworkConnect(ctx context.Context, networkID, container string, config *network.EndpointSettings) error
NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error)
NetworkDisconnect(ctx context.Context, networkID, container string, force bool) error NetworkDisconnect(ctx context.Context, networkID, container string, force bool) error
@ -87,9 +88,45 @@ type CommonAPIClient interface {
NetworkInspectWithRaw(ctx context.Context, networkID string) (types.NetworkResource, []byte, error) NetworkInspectWithRaw(ctx context.Context, networkID string) (types.NetworkResource, []byte, error)
NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error)
NetworkRemove(ctx context.Context, networkID string) error NetworkRemove(ctx context.Context, networkID string) error
}
// NodeAPIClient defines API client methods for the nodes
type NodeAPIClient interface {
NodeInspect(ctx context.Context, nodeID string) (swarm.Node, error)
NodeList(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error)
NodeRemove(ctx context.Context, nodeID string) error
NodeUpdate(ctx context.Context, nodeID string, version swarm.Version, node swarm.NodeSpec) error
}
// ServiceAPIClient defines API client methods for the services
type ServiceAPIClient interface {
ServiceCreate(ctx context.Context, service swarm.ServiceSpec) (types.ServiceCreateResponse, error)
ServiceInspect(ctx context.Context, serviceID string) (swarm.Service, error)
ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error)
ServiceRemove(ctx context.Context, serviceID string) error
ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec) error
TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error)
TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error)
}
// SwarmAPIClient defines API client methods for the swarm
type SwarmAPIClient interface {
SwarmInit(ctx context.Context, req swarm.InitRequest) (string, error)
SwarmJoin(ctx context.Context, req swarm.JoinRequest) error
SwarmLeave(ctx context.Context, force bool) error
SwarmInspect(ctx context.Context) (swarm.Swarm, error)
SwarmUpdate(ctx context.Context, version swarm.Version, swarm swarm.Spec) error
}
// SystemAPIClient defines API client methods for the system
type SystemAPIClient interface {
Events(ctx context.Context, options types.EventsOptions) (io.ReadCloser, error)
Info(ctx context.Context) (types.Info, error)
RegistryLogin(ctx context.Context, auth types.AuthConfig) (types.AuthResponse, error) RegistryLogin(ctx context.Context, auth types.AuthConfig) (types.AuthResponse, error)
ServerVersion(ctx context.Context) (types.Version, error) }
UpdateClientVersion(v string)
// VolumeAPIClient defines API client methods for the volumes
type VolumeAPIClient interface {
VolumeCreate(ctx context.Context, options types.VolumeCreateRequest) (types.Volume, error) VolumeCreate(ctx context.Context, options types.VolumeCreateRequest) (types.Volume, error)
VolumeInspect(ctx context.Context, volumeID string) (types.Volume, error) VolumeInspect(ctx context.Context, volumeID string) (types.Volume, error)
VolumeInspectWithRaw(ctx context.Context, volumeID string) (types.Volume, []byte, error) VolumeInspectWithRaw(ctx context.Context, volumeID string) (types.Volume, []byte, error)

View file

@ -12,6 +12,19 @@ import (
// APIClient is an interface that clients that talk with a docker server must implement. // APIClient is an interface that clients that talk with a docker server must implement.
type APIClient interface { type APIClient interface {
CommonAPIClient CommonAPIClient
CheckpointAPIClient
PluginAPIClient
}
// CheckpointAPIClient defines API client methods for the checkpoints
type CheckpointAPIClient interface {
CheckpointCreate(ctx context.Context, container string, options types.CheckpointCreateOptions) error
CheckpointDelete(ctx context.Context, container string, checkpointID string) error
CheckpointList(ctx context.Context, container string) ([]types.Checkpoint, error)
}
// PluginAPIClient defines API client methods for the plugins
type PluginAPIClient interface {
PluginList(ctx context.Context) (types.PluginsListResponse, error) PluginList(ctx context.Context) (types.PluginsListResponse, error)
PluginRemove(ctx context.Context, name string) error PluginRemove(ctx context.Context, name string) error
PluginEnable(ctx context.Context, name string) error PluginEnable(ctx context.Context, name string) error

View file

@ -303,7 +303,7 @@ type HostConfig struct {
PublishAllPorts bool // Should docker publish all exposed port for the container PublishAllPorts bool // Should docker publish all exposed port for the container
ReadonlyRootfs bool // Is the container root filesystem in read-only ReadonlyRootfs bool // Is the container root filesystem in read-only
SecurityOpt []string // List of string values to customize labels for MLS systems, such as SELinux. SecurityOpt []string // List of string values to customize labels for MLS systems, such as SELinux.
StorageOpt map[string]string // Storage driver options per container. StorageOpt map[string]string `json:",omitempty"` // Storage driver options per container.
Tmpfs map[string]string `json:",omitempty"` // List of tmpfs (mounts) used for the container Tmpfs map[string]string `json:",omitempty"` // List of tmpfs (mounts) used for the container
UTSMode UTSMode // UTS namespace to use for the container UTSMode UTSMode // UTS namespace to use for the container
UsernsMode UsernsMode // The user namespace to use for the container UsernsMode UsernsMode // The user namespace to use for the container

View file

@ -29,7 +29,7 @@ type AcceptancePolicy struct {
type Policy struct { type Policy struct {
Role NodeRole Role NodeRole
Autoaccept bool Autoaccept bool
Secret string `json:",omitempty"` Secret *string `json:",omitempty"`
} }
// OrchestrationConfig represents ochestration configuration. // OrchestrationConfig represents ochestration configuration.