mirror of
https://github.com/moby/moby.git
synced 2025-07-30 18:23:29 +03:00
Make internal/test/daemon.Daemon swarm aware
This remove the daemon.Swarm construction by make the new test Daemon struct aware of swarm. Signed-off-by: Vincent Demeester <vincent@sbr.pm>
This commit is contained in:
@ -311,7 +311,7 @@ func init() {
|
|||||||
type DockerSwarmSuite struct {
|
type DockerSwarmSuite struct {
|
||||||
server *httptest.Server
|
server *httptest.Server
|
||||||
ds *DockerSuite
|
ds *DockerSuite
|
||||||
daemons []*daemon.Swarm
|
daemons []*daemon.Daemon
|
||||||
daemonsLock sync.Mutex // protect access to daemons
|
daemonsLock sync.Mutex // protect access to daemons
|
||||||
portIndex int
|
portIndex int
|
||||||
}
|
}
|
||||||
@ -328,14 +328,10 @@ func (s *DockerSwarmSuite) SetUpTest(c *check.C) {
|
|||||||
testRequires(c, DaemonIsLinux, SameHostDaemon)
|
testRequires(c, DaemonIsLinux, SameHostDaemon)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DockerSwarmSuite) AddDaemon(c *check.C, joinSwarm, manager bool) *daemon.Swarm {
|
func (s *DockerSwarmSuite) AddDaemon(c *check.C, joinSwarm, manager bool) *daemon.Daemon {
|
||||||
d := &daemon.Swarm{
|
d := daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
|
||||||
Daemon: daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
|
Experimental: testEnv.DaemonInfo.ExperimentalBuild,
|
||||||
Experimental: testEnv.DaemonInfo.ExperimentalBuild,
|
}, testdaemon.WithSwarmPort(defaultSwarmPort+s.portIndex))
|
||||||
}),
|
|
||||||
Port: defaultSwarmPort + s.portIndex,
|
|
||||||
}
|
|
||||||
d.ListenAddr = fmt.Sprintf("0.0.0.0:%d", d.Port)
|
|
||||||
args := []string{"--iptables=false", "--swarm-default-advertise-addr=lo"} // avoid networking conflicts
|
args := []string{"--iptables=false", "--swarm-default-advertise-addr=lo"} // avoid networking conflicts
|
||||||
d.StartWithBusybox(c, args...)
|
d.StartWithBusybox(c, args...)
|
||||||
|
|
||||||
@ -346,12 +342,12 @@ func (s *DockerSwarmSuite) AddDaemon(c *check.C, joinSwarm, manager bool) *daemo
|
|||||||
if manager {
|
if manager {
|
||||||
token = tokens.Manager
|
token = tokens.Manager
|
||||||
}
|
}
|
||||||
c.Assert(d.Join(swarm.JoinRequest{
|
d.SwarmJoin(c, swarm.JoinRequest{
|
||||||
RemoteAddrs: []string{s.daemons[0].ListenAddr},
|
RemoteAddrs: []string{s.daemons[0].SwarmListenAddr()},
|
||||||
JoinToken: token,
|
JoinToken: token,
|
||||||
}), check.IsNil)
|
})
|
||||||
} else {
|
} else {
|
||||||
c.Assert(d.Init(swarm.InitRequest{}), check.IsNil)
|
d.SwarmInit(c, swarm.InitRequest{})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,10 +38,8 @@ type Config struct {
|
|||||||
// New returns a Daemon instance to be used for testing.
|
// New returns a Daemon instance to be used for testing.
|
||||||
// This will create a directory such as d123456789 in the folder specified by $DOCKER_INTEGRATION_DAEMON_DEST or $DEST.
|
// This will create a directory such as d123456789 in the folder specified by $DOCKER_INTEGRATION_DAEMON_DEST or $DEST.
|
||||||
// The daemon will not automatically start.
|
// The daemon will not automatically start.
|
||||||
func New(t testingT, dockerBinary string, dockerdBinary string, config Config) *Daemon {
|
func New(t testingT, dockerBinary string, dockerdBinary string, config Config, ops ...func(*daemon.Daemon)) *Daemon {
|
||||||
ops := []func(*daemon.Daemon){
|
ops = append(ops, daemon.WithDockerdBinary(dockerdBinary))
|
||||||
daemon.WithDockerdBinary(dockerdBinary),
|
|
||||||
}
|
|
||||||
if config.Experimental {
|
if config.Experimental {
|
||||||
ops = append(ops, daemon.WithExperimental)
|
ops = append(ops, daemon.WithExperimental)
|
||||||
}
|
}
|
||||||
@ -150,6 +148,21 @@ func (d *Daemon) WaitRun(contID string) error {
|
|||||||
return WaitInspectWithArgs(d.dockerBinary, contID, "{{.State.Running}}", "true", 10*time.Second, args...)
|
return WaitInspectWithArgs(d.dockerBinary, contID, "{{.State.Running}}", "true", 10*time.Second, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CmdRetryOutOfSequence tries the specified command against the current daemon for 10 times
|
||||||
|
func (d *Daemon) CmdRetryOutOfSequence(args ...string) (string, error) {
|
||||||
|
for i := 0; ; i++ {
|
||||||
|
out, err := d.Cmd(args...)
|
||||||
|
if err != nil {
|
||||||
|
if strings.Contains(out, "update out of sequence") {
|
||||||
|
if i < 10 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WaitInspectWithArgs waits for the specified expression to be equals to the specified expected string in the given time.
|
// WaitInspectWithArgs waits for the specified expression to be equals to the specified expected string in the given time.
|
||||||
// Deprecated: use cli.WaitCmd instead
|
// Deprecated: use cli.WaitCmd instead
|
||||||
func WaitInspectWithArgs(dockerBinary, name, expr, expected string, timeout time.Duration, arg ...string) error {
|
func WaitInspectWithArgs(dockerBinary, name, expr, expected string, timeout time.Duration, arg ...string) error {
|
||||||
|
@ -3,7 +3,6 @@ package daemon // import "github.com/docker/docker/integration-cli/daemon"
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
@ -12,178 +11,12 @@ import (
|
|||||||
"github.com/docker/docker/integration-cli/checker"
|
"github.com/docker/docker/integration-cli/checker"
|
||||||
"github.com/go-check/check"
|
"github.com/go-check/check"
|
||||||
"github.com/gotestyourself/gotestyourself/assert"
|
"github.com/gotestyourself/gotestyourself/assert"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Swarm is a test daemon with helpers for participating in a swarm.
|
|
||||||
type Swarm struct {
|
|
||||||
*Daemon
|
|
||||||
swarm.Info
|
|
||||||
Port int
|
|
||||||
ListenAddr string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init initializes a new swarm cluster.
|
|
||||||
func (d *Swarm) Init(req swarm.InitRequest) error {
|
|
||||||
if req.ListenAddr == "" {
|
|
||||||
req.ListenAddr = d.ListenAddr
|
|
||||||
}
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("initializing swarm: failed to create client %v", err)
|
|
||||||
}
|
|
||||||
defer cli.Close()
|
|
||||||
_, err = cli.SwarmInit(context.Background(), req)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("initializing swarm: %v", err)
|
|
||||||
}
|
|
||||||
info, err := d.SwarmInfo()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
d.Info = info
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Join joins a daemon to an existing cluster.
|
|
||||||
func (d *Swarm) Join(req swarm.JoinRequest) error {
|
|
||||||
if req.ListenAddr == "" {
|
|
||||||
req.ListenAddr = d.ListenAddr
|
|
||||||
}
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("joining swarm: failed to create client %v", err)
|
|
||||||
}
|
|
||||||
defer cli.Close()
|
|
||||||
err = cli.SwarmJoin(context.Background(), req)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("joining swarm: %v", err)
|
|
||||||
}
|
|
||||||
info, err := d.SwarmInfo()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
d.Info = info
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Leave forces daemon to leave current cluster.
|
|
||||||
func (d *Swarm) Leave(force bool) error {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("leaving swarm: failed to create client %v", err)
|
|
||||||
}
|
|
||||||
defer cli.Close()
|
|
||||||
err = cli.SwarmLeave(context.Background(), force)
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("leaving swarm: %v", err)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// SwarmInfo returns the swarm information of the daemon
|
|
||||||
func (d *Swarm) SwarmInfo() (swarm.Info, error) {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
if err != nil {
|
|
||||||
return swarm.Info{}, fmt.Errorf("get swarm info: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
info, err := cli.Info(context.Background())
|
|
||||||
if err != nil {
|
|
||||||
return swarm.Info{}, fmt.Errorf("get swarm info: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return info.Swarm, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unlock tries to unlock a locked swarm
|
|
||||||
func (d *Swarm) Unlock(req swarm.UnlockRequest) error {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unlocking swarm: failed to create client %v", err)
|
|
||||||
}
|
|
||||||
defer cli.Close()
|
|
||||||
err = cli.SwarmUnlock(context.Background(), req)
|
|
||||||
if err != nil {
|
|
||||||
err = errors.Wrap(err, "unlocking swarm")
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServiceConstructor defines a swarm service constructor function
|
|
||||||
type ServiceConstructor func(*swarm.Service)
|
|
||||||
|
|
||||||
// NodeConstructor defines a swarm node constructor
|
|
||||||
type NodeConstructor func(*swarm.Node)
|
|
||||||
|
|
||||||
// SecretConstructor defines a swarm secret constructor
|
|
||||||
type SecretConstructor func(*swarm.Secret)
|
|
||||||
|
|
||||||
// ConfigConstructor defines a swarm config constructor
|
|
||||||
type ConfigConstructor func(*swarm.Config)
|
|
||||||
|
|
||||||
// SpecConstructor defines a swarm spec constructor
|
|
||||||
type SpecConstructor func(*swarm.Spec)
|
|
||||||
|
|
||||||
// CreateServiceWithOptions creates a swarm service given the specified service constructors
|
|
||||||
// and auth config
|
|
||||||
func (d *Swarm) CreateServiceWithOptions(c *check.C, opts types.ServiceCreateOptions, f ...ServiceConstructor) string {
|
|
||||||
var service swarm.Service
|
|
||||||
for _, fn := range f {
|
|
||||||
fn(&service)
|
|
||||||
}
|
|
||||||
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
res, err := cli.ServiceCreate(ctx, service.Spec, opts)
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
return res.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateService creates a swarm service given the specified service constructor
|
|
||||||
func (d *Swarm) CreateService(c *check.C, f ...ServiceConstructor) string {
|
|
||||||
return d.CreateServiceWithOptions(c, types.ServiceCreateOptions{}, f...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetService returns the swarm service corresponding to the specified id
|
|
||||||
func (d *Swarm) GetService(c *check.C, id string) *swarm.Service {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
service, _, err := cli.ServiceInspectWithRaw(context.Background(), id, types.ServiceInspectOptions{})
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
return &service
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetServiceTasks returns the swarm tasks for the specified service
|
|
||||||
func (d *Swarm) GetServiceTasks(c *check.C, service string) []swarm.Task {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
filterArgs := filters.NewArgs()
|
|
||||||
filterArgs.Add("desired-state", "running")
|
|
||||||
filterArgs.Add("service", service)
|
|
||||||
|
|
||||||
options := types.TaskListOptions{
|
|
||||||
Filters: filterArgs,
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks, err := cli.TaskList(context.Background(), options)
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
return tasks
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckServiceTasksInState returns the number of tasks with a matching state,
|
// CheckServiceTasksInState returns the number of tasks with a matching state,
|
||||||
// and optional message substring.
|
// and optional message substring.
|
||||||
func (d *Swarm) CheckServiceTasksInState(service string, state swarm.TaskState, message string) func(*check.C) (interface{}, check.CommentInterface) {
|
func (d *Daemon) CheckServiceTasksInState(service string, state swarm.TaskState, message string) func(*check.C) (interface{}, check.CommentInterface) {
|
||||||
return func(c *check.C) (interface{}, check.CommentInterface) {
|
return func(c *check.C) (interface{}, check.CommentInterface) {
|
||||||
tasks := d.GetServiceTasks(c, service)
|
tasks := d.GetServiceTasks(c, service)
|
||||||
var count int
|
var count int
|
||||||
@ -200,7 +33,7 @@ func (d *Swarm) CheckServiceTasksInState(service string, state swarm.TaskState,
|
|||||||
|
|
||||||
// CheckServiceTasksInStateWithError returns the number of tasks with a matching state,
|
// CheckServiceTasksInStateWithError returns the number of tasks with a matching state,
|
||||||
// and optional message substring.
|
// and optional message substring.
|
||||||
func (d *Swarm) CheckServiceTasksInStateWithError(service string, state swarm.TaskState, errorMessage string) func(*check.C) (interface{}, check.CommentInterface) {
|
func (d *Daemon) CheckServiceTasksInStateWithError(service string, state swarm.TaskState, errorMessage string) func(*check.C) (interface{}, check.CommentInterface) {
|
||||||
return func(c *check.C) (interface{}, check.CommentInterface) {
|
return func(c *check.C) (interface{}, check.CommentInterface) {
|
||||||
tasks := d.GetServiceTasks(c, service)
|
tasks := d.GetServiceTasks(c, service)
|
||||||
var count int
|
var count int
|
||||||
@ -216,12 +49,12 @@ func (d *Swarm) CheckServiceTasksInStateWithError(service string, state swarm.Ta
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CheckServiceRunningTasks returns the number of running tasks for the specified service
|
// CheckServiceRunningTasks returns the number of running tasks for the specified service
|
||||||
func (d *Swarm) CheckServiceRunningTasks(service string) func(*check.C) (interface{}, check.CommentInterface) {
|
func (d *Daemon) CheckServiceRunningTasks(service string) func(*check.C) (interface{}, check.CommentInterface) {
|
||||||
return d.CheckServiceTasksInState(service, swarm.TaskStateRunning, "")
|
return d.CheckServiceTasksInState(service, swarm.TaskStateRunning, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckServiceUpdateState returns the current update state for the specified service
|
// CheckServiceUpdateState returns the current update state for the specified service
|
||||||
func (d *Swarm) CheckServiceUpdateState(service string) func(*check.C) (interface{}, check.CommentInterface) {
|
func (d *Daemon) CheckServiceUpdateState(service string) func(*check.C) (interface{}, check.CommentInterface) {
|
||||||
return func(c *check.C) (interface{}, check.CommentInterface) {
|
return func(c *check.C) (interface{}, check.CommentInterface) {
|
||||||
service := d.GetService(c, service)
|
service := d.GetService(c, service)
|
||||||
if service.UpdateStatus == nil {
|
if service.UpdateStatus == nil {
|
||||||
@ -232,7 +65,7 @@ func (d *Swarm) CheckServiceUpdateState(service string) func(*check.C) (interfac
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CheckPluginRunning returns the runtime state of the plugin
|
// CheckPluginRunning returns the runtime state of the plugin
|
||||||
func (d *Swarm) CheckPluginRunning(plugin string) func(c *check.C) (interface{}, check.CommentInterface) {
|
func (d *Daemon) CheckPluginRunning(plugin string) func(c *check.C) (interface{}, check.CommentInterface) {
|
||||||
return func(c *check.C) (interface{}, check.CommentInterface) {
|
return func(c *check.C) (interface{}, check.CommentInterface) {
|
||||||
apiclient, err := d.NewClient()
|
apiclient, err := d.NewClient()
|
||||||
assert.NilError(c, err)
|
assert.NilError(c, err)
|
||||||
@ -246,7 +79,7 @@ func (d *Swarm) CheckPluginRunning(plugin string) func(c *check.C) (interface{},
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CheckPluginImage returns the runtime state of the plugin
|
// CheckPluginImage returns the runtime state of the plugin
|
||||||
func (d *Swarm) CheckPluginImage(plugin string) func(c *check.C) (interface{}, check.CommentInterface) {
|
func (d *Daemon) CheckPluginImage(plugin string) func(c *check.C) (interface{}, check.CommentInterface) {
|
||||||
return func(c *check.C) (interface{}, check.CommentInterface) {
|
return func(c *check.C) (interface{}, check.CommentInterface) {
|
||||||
apiclient, err := d.NewClient()
|
apiclient, err := d.NewClient()
|
||||||
assert.NilError(c, err)
|
assert.NilError(c, err)
|
||||||
@ -260,7 +93,7 @@ func (d *Swarm) CheckPluginImage(plugin string) func(c *check.C) (interface{}, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CheckServiceTasks returns the number of tasks for the specified service
|
// CheckServiceTasks returns the number of tasks for the specified service
|
||||||
func (d *Swarm) CheckServiceTasks(service string) func(*check.C) (interface{}, check.CommentInterface) {
|
func (d *Daemon) CheckServiceTasks(service string) func(*check.C) (interface{}, check.CommentInterface) {
|
||||||
return func(c *check.C) (interface{}, check.CommentInterface) {
|
return func(c *check.C) (interface{}, check.CommentInterface) {
|
||||||
tasks := d.GetServiceTasks(c, service)
|
tasks := d.GetServiceTasks(c, service)
|
||||||
return len(tasks), nil
|
return len(tasks), nil
|
||||||
@ -268,7 +101,7 @@ func (d *Swarm) CheckServiceTasks(service string) func(*check.C) (interface{}, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CheckRunningTaskNetworks returns the number of times each network is referenced from a task.
|
// CheckRunningTaskNetworks returns the number of times each network is referenced from a task.
|
||||||
func (d *Swarm) CheckRunningTaskNetworks(c *check.C) (interface{}, check.CommentInterface) {
|
func (d *Daemon) CheckRunningTaskNetworks(c *check.C) (interface{}, check.CommentInterface) {
|
||||||
cli, err := d.NewClient()
|
cli, err := d.NewClient()
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
defer cli.Close()
|
defer cli.Close()
|
||||||
@ -293,7 +126,7 @@ func (d *Swarm) CheckRunningTaskNetworks(c *check.C) (interface{}, check.Comment
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CheckRunningTaskImages returns the times each image is running as a task.
|
// CheckRunningTaskImages returns the times each image is running as a task.
|
||||||
func (d *Swarm) CheckRunningTaskImages(c *check.C) (interface{}, check.CommentInterface) {
|
func (d *Daemon) CheckRunningTaskImages(c *check.C) (interface{}, check.CommentInterface) {
|
||||||
cli, err := d.NewClient()
|
cli, err := d.NewClient()
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
defer cli.Close()
|
defer cli.Close()
|
||||||
@ -318,7 +151,7 @@ func (d *Swarm) CheckRunningTaskImages(c *check.C) (interface{}, check.CommentIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CheckNodeReadyCount returns the number of ready node on the swarm
|
// CheckNodeReadyCount returns the number of ready node on the swarm
|
||||||
func (d *Swarm) CheckNodeReadyCount(c *check.C) (interface{}, check.CommentInterface) {
|
func (d *Daemon) CheckNodeReadyCount(c *check.C) (interface{}, check.CommentInterface) {
|
||||||
nodes := d.ListNodes(c)
|
nodes := d.ListNodes(c)
|
||||||
var readyCount int
|
var readyCount int
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
@ -329,303 +162,21 @@ func (d *Swarm) CheckNodeReadyCount(c *check.C) (interface{}, check.CommentInter
|
|||||||
return readyCount, nil
|
return readyCount, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTask returns the swarm task identified by the specified id
|
|
||||||
func (d *Swarm) GetTask(c *check.C, id string) swarm.Task {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
task, _, err := cli.TaskInspectWithRaw(context.Background(), id)
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
return task
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateService updates a swarm service with the specified service constructor
|
|
||||||
func (d *Swarm) UpdateService(c *check.C, service *swarm.Service, f ...ServiceConstructor) {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
for _, fn := range f {
|
|
||||||
fn(service)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = cli.ServiceUpdate(context.Background(), service.ID, service.Version, service.Spec, types.ServiceUpdateOptions{})
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveService removes the specified service
|
|
||||||
func (d *Swarm) RemoveService(c *check.C, id string) {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
err = cli.ServiceRemove(context.Background(), id)
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetNode returns a swarm node identified by the specified id
|
|
||||||
func (d *Swarm) GetNode(c *check.C, id string) *swarm.Node {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
node, _, err := cli.NodeInspectWithRaw(context.Background(), id)
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(node.ID, checker.Equals, id)
|
|
||||||
return &node
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveNode removes the specified node
|
|
||||||
func (d *Swarm) RemoveNode(c *check.C, id string, force bool) {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
options := types.NodeRemoveOptions{
|
|
||||||
Force: force,
|
|
||||||
}
|
|
||||||
err = cli.NodeRemove(context.Background(), id, options)
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateNode updates a swarm node with the specified node constructor
|
|
||||||
func (d *Swarm) UpdateNode(c *check.C, id string, f ...NodeConstructor) {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
for i := 0; ; i++ {
|
|
||||||
node := d.GetNode(c, id)
|
|
||||||
for _, fn := range f {
|
|
||||||
fn(node)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = cli.NodeUpdate(context.Background(), node.ID, node.Version, node.Spec)
|
|
||||||
if i < 10 && err != nil && strings.Contains(err.Error(), "update out of sequence") {
|
|
||||||
time.Sleep(100 * time.Millisecond)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListNodes returns the list of the current swarm nodes
|
|
||||||
func (d *Swarm) ListNodes(c *check.C) []swarm.Node {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
nodes, err := cli.NodeList(context.Background(), types.NodeListOptions{})
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
|
|
||||||
return nodes
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListServices returns the list of the current swarm services
|
|
||||||
func (d *Swarm) ListServices(c *check.C) []swarm.Service {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
services, err := cli.ServiceList(context.Background(), types.ServiceListOptions{})
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
return services
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateSecret creates a secret given the specified spec
|
|
||||||
func (d *Swarm) CreateSecret(c *check.C, secretSpec swarm.SecretSpec) string {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
scr, err := cli.SecretCreate(context.Background(), secretSpec)
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
|
|
||||||
return scr.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListSecrets returns the list of the current swarm secrets
|
|
||||||
func (d *Swarm) ListSecrets(c *check.C) []swarm.Secret {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
secrets, err := cli.SecretList(context.Background(), types.SecretListOptions{})
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
return secrets
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSecret returns a swarm secret identified by the specified id
|
|
||||||
func (d *Swarm) GetSecret(c *check.C, id string) *swarm.Secret {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
secret, _, err := cli.SecretInspectWithRaw(context.Background(), id)
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
return &secret
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteSecret removes the swarm secret identified by the specified id
|
|
||||||
func (d *Swarm) DeleteSecret(c *check.C, id string) {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
err = cli.SecretRemove(context.Background(), id)
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateSecret updates the swarm secret identified by the specified id
|
|
||||||
// Currently, only label update is supported.
|
|
||||||
func (d *Swarm) UpdateSecret(c *check.C, id string, f ...SecretConstructor) {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
secret := d.GetSecret(c, id)
|
|
||||||
for _, fn := range f {
|
|
||||||
fn(secret)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = cli.SecretUpdate(context.Background(), secret.ID, secret.Version, secret.Spec)
|
|
||||||
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateConfig creates a config given the specified spec
|
|
||||||
func (d *Swarm) CreateConfig(c *check.C, configSpec swarm.ConfigSpec) string {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
scr, err := cli.ConfigCreate(context.Background(), configSpec)
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
return scr.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListConfigs returns the list of the current swarm configs
|
|
||||||
func (d *Swarm) ListConfigs(c *check.C) []swarm.Config {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
configs, err := cli.ConfigList(context.Background(), types.ConfigListOptions{})
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
return configs
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetConfig returns a swarm config identified by the specified id
|
|
||||||
func (d *Swarm) GetConfig(c *check.C, id string) *swarm.Config {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
config, _, err := cli.ConfigInspectWithRaw(context.Background(), id)
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
return &config
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteConfig removes the swarm config identified by the specified id
|
|
||||||
func (d *Swarm) DeleteConfig(c *check.C, id string) {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
err = cli.ConfigRemove(context.Background(), id)
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateConfig updates the swarm config identified by the specified id
|
|
||||||
// Currently, only label update is supported.
|
|
||||||
func (d *Swarm) UpdateConfig(c *check.C, id string, f ...ConfigConstructor) {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
config := d.GetConfig(c, id)
|
|
||||||
for _, fn := range f {
|
|
||||||
fn(config)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = cli.ConfigUpdate(context.Background(), config.ID, config.Version, config.Spec)
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSwarm returns the current swarm object
|
|
||||||
func (d *Swarm) GetSwarm(c *check.C) swarm.Swarm {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
sw, err := cli.SwarmInspect(context.Background())
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
return sw
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateSwarm updates the current swarm object with the specified spec constructors
|
|
||||||
func (d *Swarm) UpdateSwarm(c *check.C, f ...SpecConstructor) {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
sw := d.GetSwarm(c)
|
|
||||||
for _, fn := range f {
|
|
||||||
fn(&sw.Spec)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = cli.SwarmUpdate(context.Background(), sw.Version, sw.Spec, swarm.UpdateFlags{})
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RotateTokens update the swarm to rotate tokens
|
|
||||||
func (d *Swarm) RotateTokens(c *check.C) {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
sw, err := cli.SwarmInspect(context.Background())
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
|
|
||||||
flags := swarm.UpdateFlags{
|
|
||||||
RotateManagerToken: true,
|
|
||||||
RotateWorkerToken: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
err = cli.SwarmUpdate(context.Background(), sw.Version, sw.Spec, flags)
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// JoinTokens returns the current swarm join tokens
|
|
||||||
func (d *Swarm) JoinTokens(c *check.C) swarm.JoinTokens {
|
|
||||||
cli, err := d.NewClient()
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
defer cli.Close()
|
|
||||||
|
|
||||||
sw, err := cli.SwarmInspect(context.Background())
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
return sw.JoinTokens
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckLocalNodeState returns the current swarm node state
|
// CheckLocalNodeState returns the current swarm node state
|
||||||
func (d *Swarm) CheckLocalNodeState(c *check.C) (interface{}, check.CommentInterface) {
|
func (d *Daemon) CheckLocalNodeState(c *check.C) (interface{}, check.CommentInterface) {
|
||||||
info, err := d.SwarmInfo()
|
info := d.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
return info.LocalNodeState, nil
|
return info.LocalNodeState, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckControlAvailable returns the current swarm control available
|
// CheckControlAvailable returns the current swarm control available
|
||||||
func (d *Swarm) CheckControlAvailable(c *check.C) (interface{}, check.CommentInterface) {
|
func (d *Daemon) CheckControlAvailable(c *check.C) (interface{}, check.CommentInterface) {
|
||||||
info, err := d.SwarmInfo()
|
info := d.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
||||||
return info.ControlAvailable, nil
|
return info.ControlAvailable, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckLeader returns whether there is a leader on the swarm or not
|
// CheckLeader returns whether there is a leader on the swarm or not
|
||||||
func (d *Swarm) CheckLeader(c *check.C) (interface{}, check.CommentInterface) {
|
func (d *Daemon) CheckLeader(c *check.C) (interface{}, check.CommentInterface) {
|
||||||
cli, err := d.NewClient()
|
cli, err := d.NewClient()
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
defer cli.Close()
|
defer cli.Close()
|
||||||
@ -644,18 +195,3 @@ func (d *Swarm) CheckLeader(c *check.C) (interface{}, check.CommentInterface) {
|
|||||||
}
|
}
|
||||||
return fmt.Errorf("no leader"), check.Commentf("could not find leader")
|
return fmt.Errorf("no leader"), check.Commentf("could not find leader")
|
||||||
}
|
}
|
||||||
|
|
||||||
// CmdRetryOutOfSequence tries the specified command against the current daemon for 10 times
|
|
||||||
func (d *Swarm) CmdRetryOutOfSequence(args ...string) (string, error) {
|
|
||||||
for i := 0; ; i++ {
|
|
||||||
out, err := d.Cmd(args...)
|
|
||||||
if err != nil {
|
|
||||||
if strings.Contains(out, "update out of sequence") {
|
|
||||||
if i < 10 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return out, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -5,11 +5,11 @@ import (
|
|||||||
"github.com/go-check/check"
|
"github.com/go-check/check"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *DockerSwarmSuite) getDaemon(c *check.C, nodeID string) *daemon.Swarm {
|
func (s *DockerSwarmSuite) getDaemon(c *check.C, nodeID string) *daemon.Daemon {
|
||||||
s.daemonsLock.Lock()
|
s.daemonsLock.Lock()
|
||||||
defer s.daemonsLock.Unlock()
|
defer s.daemonsLock.Unlock()
|
||||||
for _, d := range s.daemons {
|
for _, d := range s.daemons {
|
||||||
if d.NodeID == nodeID {
|
if d.NodeID() == nodeID {
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,8 @@ func (s *DockerSwarmSuite) TestAPISwarmListNodes(c *check.C) {
|
|||||||
|
|
||||||
loop0:
|
loop0:
|
||||||
for _, n := range nodes {
|
for _, n := range nodes {
|
||||||
for _, d := range []*daemon.Swarm{d1, d2, d3} {
|
for _, d := range []*daemon.Daemon{d1, d2, d3} {
|
||||||
if n.ID == d.NodeID {
|
if n.ID == d.NodeID() {
|
||||||
continue loop0
|
continue loop0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,8 +53,7 @@ func (s *DockerSwarmSuite) TestAPISwarmNodeRemove(c *check.C) {
|
|||||||
c.Assert(len(nodes), checker.Equals, 3, check.Commentf("nodes: %#v", nodes))
|
c.Assert(len(nodes), checker.Equals, 3, check.Commentf("nodes: %#v", nodes))
|
||||||
|
|
||||||
// Getting the info so we can take the NodeID
|
// Getting the info so we can take the NodeID
|
||||||
d2Info, err := d2.SwarmInfo()
|
d2Info := d2.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
|
|
||||||
// forceful removal of d2 should work
|
// forceful removal of d2 should work
|
||||||
d1.RemoveNode(c, d2Info.NodeID, true)
|
d1.RemoveNode(c, d2Info.NodeID, true)
|
||||||
@ -88,14 +87,14 @@ func (s *DockerSwarmSuite) TestAPISwarmNodeDrainPause(c *check.C) {
|
|||||||
waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals, instances)
|
waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals, instances)
|
||||||
|
|
||||||
// drain d2, all containers should move to d1
|
// drain d2, all containers should move to d1
|
||||||
d1.UpdateNode(c, d2.NodeID, func(n *swarm.Node) {
|
d1.UpdateNode(c, d2.NodeID(), func(n *swarm.Node) {
|
||||||
n.Spec.Availability = swarm.NodeAvailabilityDrain
|
n.Spec.Availability = swarm.NodeAvailabilityDrain
|
||||||
})
|
})
|
||||||
waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.Equals, instances)
|
waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.Equals, instances)
|
||||||
waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.Equals, 0)
|
waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.Equals, 0)
|
||||||
|
|
||||||
// set d2 back to active
|
// set d2 back to active
|
||||||
d1.UpdateNode(c, d2.NodeID, func(n *swarm.Node) {
|
d1.UpdateNode(c, d2.NodeID(), func(n *swarm.Node) {
|
||||||
n.Spec.Availability = swarm.NodeAvailabilityActive
|
n.Spec.Availability = swarm.NodeAvailabilityActive
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -115,7 +114,7 @@ func (s *DockerSwarmSuite) TestAPISwarmNodeDrainPause(c *check.C) {
|
|||||||
d2ContainerCount := len(d2.ActiveContainers())
|
d2ContainerCount := len(d2.ActiveContainers())
|
||||||
|
|
||||||
// set d2 to paused, scale service up, only d1 gets new tasks
|
// set d2 to paused, scale service up, only d1 gets new tasks
|
||||||
d1.UpdateNode(c, d2.NodeID, func(n *swarm.Node) {
|
d1.UpdateNode(c, d2.NodeID(), func(n *swarm.Node) {
|
||||||
n.Spec.Availability = swarm.NodeAvailabilityPause
|
n.Spec.Availability = swarm.NodeAvailabilityPause
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -15,12 +15,13 @@ import (
|
|||||||
"github.com/docker/docker/integration-cli/checker"
|
"github.com/docker/docker/integration-cli/checker"
|
||||||
"github.com/docker/docker/integration-cli/daemon"
|
"github.com/docker/docker/integration-cli/daemon"
|
||||||
"github.com/docker/docker/integration-cli/fixtures/plugin"
|
"github.com/docker/docker/integration-cli/fixtures/plugin"
|
||||||
|
testdaemon "github.com/docker/docker/internal/test/daemon"
|
||||||
"github.com/go-check/check"
|
"github.com/go-check/check"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
func setPortConfig(portConfig []swarm.PortConfig) daemon.ServiceConstructor {
|
func setPortConfig(portConfig []swarm.PortConfig) testdaemon.ServiceConstructor {
|
||||||
return func(s *swarm.Service) {
|
return func(s *swarm.Service) {
|
||||||
if s.Spec.EndpointSpec == nil {
|
if s.Spec.EndpointSpec == nil {
|
||||||
s.Spec.EndpointSpec = &swarm.EndpointSpec{}
|
s.Spec.EndpointSpec = &swarm.EndpointSpec{}
|
||||||
@ -140,7 +141,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesCreateGlobal(c *check.C) {
|
|||||||
|
|
||||||
func (s *DockerSwarmSuite) TestAPISwarmServicesUpdate(c *check.C) {
|
func (s *DockerSwarmSuite) TestAPISwarmServicesUpdate(c *check.C) {
|
||||||
const nodeCount = 3
|
const nodeCount = 3
|
||||||
var daemons [nodeCount]*daemon.Swarm
|
var daemons [nodeCount]*daemon.Daemon
|
||||||
for i := 0; i < nodeCount; i++ {
|
for i := 0; i < nodeCount; i++ {
|
||||||
daemons[i] = s.AddDaemon(c, true, i == 0)
|
daemons[i] = s.AddDaemon(c, true, i == 0)
|
||||||
}
|
}
|
||||||
@ -309,7 +310,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesUpdateStartFirst(c *check.C) {
|
|||||||
|
|
||||||
func (s *DockerSwarmSuite) TestAPISwarmServicesFailedUpdate(c *check.C) {
|
func (s *DockerSwarmSuite) TestAPISwarmServicesFailedUpdate(c *check.C) {
|
||||||
const nodeCount = 3
|
const nodeCount = 3
|
||||||
var daemons [nodeCount]*daemon.Swarm
|
var daemons [nodeCount]*daemon.Daemon
|
||||||
for i := 0; i < nodeCount; i++ {
|
for i := 0; i < nodeCount; i++ {
|
||||||
daemons[i] = s.AddDaemon(c, true, i == 0)
|
daemons[i] = s.AddDaemon(c, true, i == 0)
|
||||||
}
|
}
|
||||||
@ -349,7 +350,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesFailedUpdate(c *check.C) {
|
|||||||
|
|
||||||
func (s *DockerSwarmSuite) TestAPISwarmServiceConstraintRole(c *check.C) {
|
func (s *DockerSwarmSuite) TestAPISwarmServiceConstraintRole(c *check.C) {
|
||||||
const nodeCount = 3
|
const nodeCount = 3
|
||||||
var daemons [nodeCount]*daemon.Swarm
|
var daemons [nodeCount]*daemon.Daemon
|
||||||
for i := 0; i < nodeCount; i++ {
|
for i := 0; i < nodeCount; i++ {
|
||||||
daemons[i] = s.AddDaemon(c, true, i == 0)
|
daemons[i] = s.AddDaemon(c, true, i == 0)
|
||||||
}
|
}
|
||||||
@ -401,7 +402,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServiceConstraintRole(c *check.C) {
|
|||||||
|
|
||||||
func (s *DockerSwarmSuite) TestAPISwarmServiceConstraintLabel(c *check.C) {
|
func (s *DockerSwarmSuite) TestAPISwarmServiceConstraintLabel(c *check.C) {
|
||||||
const nodeCount = 3
|
const nodeCount = 3
|
||||||
var daemons [nodeCount]*daemon.Swarm
|
var daemons [nodeCount]*daemon.Daemon
|
||||||
for i := 0; i < nodeCount; i++ {
|
for i := 0; i < nodeCount; i++ {
|
||||||
daemons[i] = s.AddDaemon(c, true, i == 0)
|
daemons[i] = s.AddDaemon(c, true, i == 0)
|
||||||
}
|
}
|
||||||
@ -496,7 +497,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServiceConstraintLabel(c *check.C) {
|
|||||||
|
|
||||||
func (s *DockerSwarmSuite) TestAPISwarmServicePlacementPrefs(c *check.C) {
|
func (s *DockerSwarmSuite) TestAPISwarmServicePlacementPrefs(c *check.C) {
|
||||||
const nodeCount = 3
|
const nodeCount = 3
|
||||||
var daemons [nodeCount]*daemon.Swarm
|
var daemons [nodeCount]*daemon.Daemon
|
||||||
for i := 0; i < nodeCount; i++ {
|
for i := 0; i < nodeCount; i++ {
|
||||||
daemons[i] = s.AddDaemon(c, true, i == 0)
|
daemons[i] = s.AddDaemon(c, true, i == 0)
|
||||||
}
|
}
|
||||||
@ -551,9 +552,9 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesStateReporting(c *check.C) {
|
|||||||
|
|
||||||
waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals, instances)
|
waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals, instances)
|
||||||
|
|
||||||
getContainers := func() map[string]*daemon.Swarm {
|
getContainers := func() map[string]*daemon.Daemon {
|
||||||
m := make(map[string]*daemon.Swarm)
|
m := make(map[string]*daemon.Daemon)
|
||||||
for _, d := range []*daemon.Swarm{d1, d2, d3} {
|
for _, d := range []*daemon.Daemon{d1, d2, d3} {
|
||||||
for _, id := range d.ActiveContainers() {
|
for _, id := range d.ActiveContainers() {
|
||||||
m[id] = d
|
m[id] = d
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
"github.com/docker/docker/integration-cli/checker"
|
"github.com/docker/docker/integration-cli/checker"
|
||||||
"github.com/docker/docker/integration-cli/daemon"
|
"github.com/docker/docker/integration-cli/daemon"
|
||||||
"github.com/docker/docker/integration-cli/request"
|
"github.com/docker/docker/integration-cli/request"
|
||||||
|
testdaemon "github.com/docker/docker/internal/test/daemon"
|
||||||
"github.com/docker/swarmkit/ca"
|
"github.com/docker/swarmkit/ca"
|
||||||
"github.com/go-check/check"
|
"github.com/go-check/check"
|
||||||
"github.com/gotestyourself/gotestyourself/assert"
|
"github.com/gotestyourself/gotestyourself/assert"
|
||||||
@ -35,30 +36,30 @@ var defaultReconciliationTimeout = 30 * time.Second
|
|||||||
func (s *DockerSwarmSuite) TestAPISwarmInit(c *check.C) {
|
func (s *DockerSwarmSuite) TestAPISwarmInit(c *check.C) {
|
||||||
// todo: should find a better way to verify that components are running than /info
|
// todo: should find a better way to verify that components are running than /info
|
||||||
d1 := s.AddDaemon(c, true, true)
|
d1 := s.AddDaemon(c, true, true)
|
||||||
info, err := d1.SwarmInfo()
|
info := d1.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.ControlAvailable, checker.True)
|
c.Assert(info.ControlAvailable, checker.True)
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
||||||
c.Assert(info.Cluster.RootRotationInProgress, checker.False)
|
c.Assert(info.Cluster.RootRotationInProgress, checker.False)
|
||||||
|
|
||||||
d2 := s.AddDaemon(c, true, false)
|
d2 := s.AddDaemon(c, true, false)
|
||||||
info, err = d2.SwarmInfo()
|
info = d2.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.ControlAvailable, checker.False)
|
c.Assert(info.ControlAvailable, checker.False)
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
||||||
|
|
||||||
// Leaving cluster
|
// Leaving cluster
|
||||||
c.Assert(d2.Leave(false), checker.IsNil)
|
c.Assert(d2.SwarmLeave(false), checker.IsNil)
|
||||||
|
|
||||||
info, err = d2.SwarmInfo()
|
info = d2.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.ControlAvailable, checker.False)
|
c.Assert(info.ControlAvailable, checker.False)
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
|
||||||
|
|
||||||
c.Assert(d2.Join(swarm.JoinRequest{JoinToken: d1.JoinTokens(c).Worker, RemoteAddrs: []string{d1.ListenAddr}}), checker.IsNil)
|
d2.SwarmJoin(c, swarm.JoinRequest{
|
||||||
|
ListenAddr: d1.SwarmListenAddr(),
|
||||||
|
JoinToken: d1.JoinTokens(c).Worker,
|
||||||
|
RemoteAddrs: []string{d1.SwarmListenAddr()},
|
||||||
|
})
|
||||||
|
|
||||||
info, err = d2.SwarmInfo()
|
info = d2.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.ControlAvailable, checker.False)
|
c.Assert(info.ControlAvailable, checker.False)
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
||||||
|
|
||||||
@ -69,93 +70,100 @@ func (s *DockerSwarmSuite) TestAPISwarmInit(c *check.C) {
|
|||||||
d1.Start(c)
|
d1.Start(c)
|
||||||
d2.Start(c)
|
d2.Start(c)
|
||||||
|
|
||||||
info, err = d1.SwarmInfo()
|
info = d1.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.ControlAvailable, checker.True)
|
c.Assert(info.ControlAvailable, checker.True)
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
||||||
|
|
||||||
info, err = d2.SwarmInfo()
|
info = d2.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.ControlAvailable, checker.False)
|
c.Assert(info.ControlAvailable, checker.False)
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DockerSwarmSuite) TestAPISwarmJoinToken(c *check.C) {
|
func (s *DockerSwarmSuite) TestAPISwarmJoinToken(c *check.C) {
|
||||||
d1 := s.AddDaemon(c, false, false)
|
d1 := s.AddDaemon(c, false, false)
|
||||||
c.Assert(d1.Init(swarm.InitRequest{}), checker.IsNil)
|
d1.SwarmInit(c, swarm.InitRequest{})
|
||||||
|
|
||||||
// todo: error message differs depending if some components of token are valid
|
// todo: error message differs depending if some components of token are valid
|
||||||
|
|
||||||
d2 := s.AddDaemon(c, false, false)
|
d2 := s.AddDaemon(c, false, false)
|
||||||
err := d2.Join(swarm.JoinRequest{RemoteAddrs: []string{d1.ListenAddr}})
|
c2 := d2.NewClientT(c)
|
||||||
|
err := c2.SwarmJoin(context.Background(), swarm.JoinRequest{
|
||||||
|
ListenAddr: d2.SwarmListenAddr(),
|
||||||
|
RemoteAddrs: []string{d1.SwarmListenAddr()},
|
||||||
|
})
|
||||||
c.Assert(err, checker.NotNil)
|
c.Assert(err, checker.NotNil)
|
||||||
c.Assert(err.Error(), checker.Contains, "join token is necessary")
|
c.Assert(err.Error(), checker.Contains, "join token is necessary")
|
||||||
info, err := d2.SwarmInfo()
|
info := d2.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
|
||||||
|
|
||||||
err = d2.Join(swarm.JoinRequest{JoinToken: "foobaz", RemoteAddrs: []string{d1.ListenAddr}})
|
err = c2.SwarmJoin(context.Background(), swarm.JoinRequest{
|
||||||
|
ListenAddr: d2.SwarmListenAddr(),
|
||||||
|
JoinToken: "foobaz",
|
||||||
|
RemoteAddrs: []string{d1.SwarmListenAddr()},
|
||||||
|
})
|
||||||
c.Assert(err, checker.NotNil)
|
c.Assert(err, checker.NotNil)
|
||||||
c.Assert(err.Error(), checker.Contains, "invalid join token")
|
c.Assert(err.Error(), checker.Contains, "invalid join token")
|
||||||
info, err = d2.SwarmInfo()
|
info = d2.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
|
||||||
|
|
||||||
workerToken := d1.JoinTokens(c).Worker
|
workerToken := d1.JoinTokens(c).Worker
|
||||||
|
|
||||||
c.Assert(d2.Join(swarm.JoinRequest{JoinToken: workerToken, RemoteAddrs: []string{d1.ListenAddr}}), checker.IsNil)
|
d2.SwarmJoin(c, swarm.JoinRequest{
|
||||||
info, err = d2.SwarmInfo()
|
ListenAddr: d2.SwarmListenAddr(),
|
||||||
c.Assert(err, checker.IsNil)
|
JoinToken: workerToken,
|
||||||
|
RemoteAddrs: []string{d1.SwarmListenAddr()},
|
||||||
|
})
|
||||||
|
info = d2.SwarmInfo(c)
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
||||||
c.Assert(d2.Leave(false), checker.IsNil)
|
c.Assert(d2.SwarmLeave(false), checker.IsNil)
|
||||||
info, err = d2.SwarmInfo()
|
info = d2.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
|
||||||
|
|
||||||
// change tokens
|
// change tokens
|
||||||
d1.RotateTokens(c)
|
d1.RotateTokens(c)
|
||||||
|
|
||||||
err = d2.Join(swarm.JoinRequest{JoinToken: workerToken, RemoteAddrs: []string{d1.ListenAddr}})
|
err = c2.SwarmJoin(context.Background(), swarm.JoinRequest{
|
||||||
|
ListenAddr: d2.SwarmListenAddr(),
|
||||||
|
JoinToken: workerToken,
|
||||||
|
RemoteAddrs: []string{d1.SwarmListenAddr()},
|
||||||
|
})
|
||||||
c.Assert(err, checker.NotNil)
|
c.Assert(err, checker.NotNil)
|
||||||
c.Assert(err.Error(), checker.Contains, "join token is necessary")
|
c.Assert(err.Error(), checker.Contains, "join token is necessary")
|
||||||
info, err = d2.SwarmInfo()
|
info = d2.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
|
||||||
|
|
||||||
workerToken = d1.JoinTokens(c).Worker
|
workerToken = d1.JoinTokens(c).Worker
|
||||||
|
|
||||||
c.Assert(d2.Join(swarm.JoinRequest{JoinToken: workerToken, RemoteAddrs: []string{d1.ListenAddr}}), checker.IsNil)
|
d2.SwarmJoin(c, swarm.JoinRequest{JoinToken: workerToken, RemoteAddrs: []string{d1.SwarmListenAddr()}})
|
||||||
info, err = d2.SwarmInfo()
|
info = d2.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
||||||
c.Assert(d2.Leave(false), checker.IsNil)
|
c.Assert(d2.SwarmLeave(false), checker.IsNil)
|
||||||
info, err = d2.SwarmInfo()
|
info = d2.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
|
||||||
|
|
||||||
// change spec, don't change tokens
|
// change spec, don't change tokens
|
||||||
d1.UpdateSwarm(c, func(s *swarm.Spec) {})
|
d1.UpdateSwarm(c, func(s *swarm.Spec) {})
|
||||||
|
|
||||||
err = d2.Join(swarm.JoinRequest{RemoteAddrs: []string{d1.ListenAddr}})
|
err = c2.SwarmJoin(context.Background(), swarm.JoinRequest{
|
||||||
|
ListenAddr: d2.SwarmListenAddr(),
|
||||||
|
RemoteAddrs: []string{d1.SwarmListenAddr()},
|
||||||
|
})
|
||||||
c.Assert(err, checker.NotNil)
|
c.Assert(err, checker.NotNil)
|
||||||
c.Assert(err.Error(), checker.Contains, "join token is necessary")
|
c.Assert(err.Error(), checker.Contains, "join token is necessary")
|
||||||
info, err = d2.SwarmInfo()
|
info = d2.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
|
||||||
|
|
||||||
c.Assert(d2.Join(swarm.JoinRequest{JoinToken: workerToken, RemoteAddrs: []string{d1.ListenAddr}}), checker.IsNil)
|
d2.SwarmJoin(c, swarm.JoinRequest{JoinToken: workerToken, RemoteAddrs: []string{d1.SwarmListenAddr()}})
|
||||||
info, err = d2.SwarmInfo()
|
info = d2.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
||||||
c.Assert(d2.Leave(false), checker.IsNil)
|
c.Assert(d2.SwarmLeave(false), checker.IsNil)
|
||||||
info, err = d2.SwarmInfo()
|
info = d2.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DockerSwarmSuite) TestUpdateSwarmAddExternalCA(c *check.C) {
|
func (s *DockerSwarmSuite) TestUpdateSwarmAddExternalCA(c *check.C) {
|
||||||
d1 := s.AddDaemon(c, false, false)
|
d1 := s.AddDaemon(c, false, false)
|
||||||
c.Assert(d1.Init(swarm.InitRequest{}), checker.IsNil)
|
d1.SwarmInit(c, swarm.InitRequest{})
|
||||||
d1.UpdateSwarm(c, func(s *swarm.Spec) {
|
d1.UpdateSwarm(c, func(s *swarm.Spec) {
|
||||||
s.CAConfig.ExternalCAs = []*swarm.ExternalCA{
|
s.CAConfig.ExternalCAs = []*swarm.ExternalCA{
|
||||||
{
|
{
|
||||||
@ -169,8 +177,7 @@ func (s *DockerSwarmSuite) TestUpdateSwarmAddExternalCA(c *check.C) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
info, err := d1.SwarmInfo()
|
info := d1.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.Cluster.Spec.CAConfig.ExternalCAs, checker.HasLen, 2)
|
c.Assert(info.Cluster.Spec.CAConfig.ExternalCAs, checker.HasLen, 2)
|
||||||
c.Assert(info.Cluster.Spec.CAConfig.ExternalCAs[0].CACert, checker.Equals, "")
|
c.Assert(info.Cluster.Spec.CAConfig.ExternalCAs[0].CACert, checker.Equals, "")
|
||||||
c.Assert(info.Cluster.Spec.CAConfig.ExternalCAs[1].CACert, checker.Equals, "cacert")
|
c.Assert(info.Cluster.Spec.CAConfig.ExternalCAs[1].CACert, checker.Equals, "cacert")
|
||||||
@ -182,28 +189,32 @@ func (s *DockerSwarmSuite) TestAPISwarmCAHash(c *check.C) {
|
|||||||
splitToken := strings.Split(d1.JoinTokens(c).Worker, "-")
|
splitToken := strings.Split(d1.JoinTokens(c).Worker, "-")
|
||||||
splitToken[2] = "1kxftv4ofnc6mt30lmgipg6ngf9luhwqopfk1tz6bdmnkubg0e"
|
splitToken[2] = "1kxftv4ofnc6mt30lmgipg6ngf9luhwqopfk1tz6bdmnkubg0e"
|
||||||
replacementToken := strings.Join(splitToken, "-")
|
replacementToken := strings.Join(splitToken, "-")
|
||||||
err := d2.Join(swarm.JoinRequest{JoinToken: replacementToken, RemoteAddrs: []string{d1.ListenAddr}})
|
c2 := d2.NewClientT(c)
|
||||||
|
err := c2.SwarmJoin(context.Background(), swarm.JoinRequest{
|
||||||
|
ListenAddr: d2.SwarmListenAddr(),
|
||||||
|
JoinToken: replacementToken,
|
||||||
|
RemoteAddrs: []string{d1.SwarmListenAddr()},
|
||||||
|
})
|
||||||
c.Assert(err, checker.NotNil)
|
c.Assert(err, checker.NotNil)
|
||||||
c.Assert(err.Error(), checker.Contains, "remote CA does not match fingerprint")
|
c.Assert(err.Error(), checker.Contains, "remote CA does not match fingerprint")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DockerSwarmSuite) TestAPISwarmPromoteDemote(c *check.C) {
|
func (s *DockerSwarmSuite) TestAPISwarmPromoteDemote(c *check.C) {
|
||||||
d1 := s.AddDaemon(c, false, false)
|
d1 := s.AddDaemon(c, false, false)
|
||||||
c.Assert(d1.Init(swarm.InitRequest{}), checker.IsNil)
|
d1.SwarmInit(c, swarm.InitRequest{})
|
||||||
d2 := s.AddDaemon(c, true, false)
|
d2 := s.AddDaemon(c, true, false)
|
||||||
|
|
||||||
info, err := d2.SwarmInfo()
|
info := d2.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.ControlAvailable, checker.False)
|
c.Assert(info.ControlAvailable, checker.False)
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
||||||
|
|
||||||
d1.UpdateNode(c, d2.NodeID, func(n *swarm.Node) {
|
d1.UpdateNode(c, d2.NodeID(), func(n *swarm.Node) {
|
||||||
n.Spec.Role = swarm.NodeRoleManager
|
n.Spec.Role = swarm.NodeRoleManager
|
||||||
})
|
})
|
||||||
|
|
||||||
waitAndAssert(c, defaultReconciliationTimeout, d2.CheckControlAvailable, checker.True)
|
waitAndAssert(c, defaultReconciliationTimeout, d2.CheckControlAvailable, checker.True)
|
||||||
|
|
||||||
d1.UpdateNode(c, d2.NodeID, func(n *swarm.Node) {
|
d1.UpdateNode(c, d2.NodeID(), func(n *swarm.Node) {
|
||||||
n.Spec.Role = swarm.NodeRoleWorker
|
n.Spec.Role = swarm.NodeRoleWorker
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -228,7 +239,7 @@ func (s *DockerSwarmSuite) TestAPISwarmPromoteDemote(c *check.C) {
|
|||||||
}, checker.Equals, "swarm-worker")
|
}, checker.Equals, "swarm-worker")
|
||||||
|
|
||||||
// Demoting last node should fail
|
// Demoting last node should fail
|
||||||
node := d1.GetNode(c, d1.NodeID)
|
node := d1.GetNode(c, d1.NodeID())
|
||||||
node.Spec.Role = swarm.NodeRoleWorker
|
node.Spec.Role = swarm.NodeRoleWorker
|
||||||
url := fmt.Sprintf("/nodes/%s/update?version=%d", node.ID, node.Version.Index)
|
url := fmt.Sprintf("/nodes/%s/update?version=%d", node.ID, node.Version.Index)
|
||||||
res, body, err := request.DoOnHost(d1.Sock(), url, request.Method("POST"), request.JSONBody(node.Spec))
|
res, body, err := request.DoOnHost(d1.Sock(), url, request.Method("POST"), request.JSONBody(node.Spec))
|
||||||
@ -246,13 +257,12 @@ func (s *DockerSwarmSuite) TestAPISwarmPromoteDemote(c *check.C) {
|
|||||||
if !strings.Contains(string(b), "last manager of the swarm") {
|
if !strings.Contains(string(b), "last manager of the swarm") {
|
||||||
c.Assert(string(b), checker.Contains, "this would result in a loss of quorum")
|
c.Assert(string(b), checker.Contains, "this would result in a loss of quorum")
|
||||||
}
|
}
|
||||||
info, err = d1.SwarmInfo()
|
info = d1.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
||||||
c.Assert(info.ControlAvailable, checker.True)
|
c.Assert(info.ControlAvailable, checker.True)
|
||||||
|
|
||||||
// Promote already demoted node
|
// Promote already demoted node
|
||||||
d1.UpdateNode(c, d2.NodeID, func(n *swarm.Node) {
|
d1.UpdateNode(c, d2.NodeID(), func(n *swarm.Node) {
|
||||||
n.Spec.Role = swarm.NodeRoleManager
|
n.Spec.Role = swarm.NodeRoleManager
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -278,7 +288,7 @@ func (s *DockerSwarmSuite) TestAPISwarmLeaderProxy(c *check.C) {
|
|||||||
|
|
||||||
// 3 services should be started now, because the requests were proxied to leader
|
// 3 services should be started now, because the requests were proxied to leader
|
||||||
// query each node and make sure it returns 3 services
|
// query each node and make sure it returns 3 services
|
||||||
for _, d := range []*daemon.Swarm{d1, d2, d3} {
|
for _, d := range []*daemon.Daemon{d1, d2, d3} {
|
||||||
services := d.ListServices(c)
|
services := d.ListServices(c)
|
||||||
c.Assert(services, checker.HasLen, 3)
|
c.Assert(services, checker.HasLen, 3)
|
||||||
}
|
}
|
||||||
@ -291,23 +301,23 @@ func (s *DockerSwarmSuite) TestAPISwarmLeaderElection(c *check.C) {
|
|||||||
d3 := s.AddDaemon(c, true, true)
|
d3 := s.AddDaemon(c, true, true)
|
||||||
|
|
||||||
// assert that the first node we made is the leader, and the other two are followers
|
// assert that the first node we made is the leader, and the other two are followers
|
||||||
c.Assert(d1.GetNode(c, d1.NodeID).ManagerStatus.Leader, checker.True)
|
c.Assert(d1.GetNode(c, d1.NodeID()).ManagerStatus.Leader, checker.True)
|
||||||
c.Assert(d1.GetNode(c, d2.NodeID).ManagerStatus.Leader, checker.False)
|
c.Assert(d1.GetNode(c, d2.NodeID()).ManagerStatus.Leader, checker.False)
|
||||||
c.Assert(d1.GetNode(c, d3.NodeID).ManagerStatus.Leader, checker.False)
|
c.Assert(d1.GetNode(c, d3.NodeID()).ManagerStatus.Leader, checker.False)
|
||||||
|
|
||||||
d1.Stop(c)
|
d1.Stop(c)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
leader *daemon.Swarm // keep track of leader
|
leader *daemon.Daemon // keep track of leader
|
||||||
followers []*daemon.Swarm // keep track of followers
|
followers []*daemon.Daemon // keep track of followers
|
||||||
)
|
)
|
||||||
checkLeader := func(nodes ...*daemon.Swarm) checkF {
|
checkLeader := func(nodes ...*daemon.Daemon) checkF {
|
||||||
return func(c *check.C) (interface{}, check.CommentInterface) {
|
return func(c *check.C) (interface{}, check.CommentInterface) {
|
||||||
// clear these out before each run
|
// clear these out before each run
|
||||||
leader = nil
|
leader = nil
|
||||||
followers = nil
|
followers = nil
|
||||||
for _, d := range nodes {
|
for _, d := range nodes {
|
||||||
if d.GetNode(c, d.NodeID).ManagerStatus.Leader {
|
if d.GetNode(c, d.NodeID()).ManagerStatus.Leader {
|
||||||
leader = d
|
leader = d
|
||||||
} else {
|
} else {
|
||||||
followers = append(followers, d)
|
followers = append(followers, d)
|
||||||
@ -344,7 +354,7 @@ func (s *DockerSwarmSuite) TestAPISwarmLeaderElection(c *check.C) {
|
|||||||
c.Assert(leader, checker.NotNil)
|
c.Assert(leader, checker.NotNil)
|
||||||
c.Assert(followers, checker.HasLen, 2)
|
c.Assert(followers, checker.HasLen, 2)
|
||||||
// and that after we added d1 back, the leader hasn't changed
|
// and that after we added d1 back, the leader hasn't changed
|
||||||
c.Assert(leader.NodeID, checker.Equals, stableleader.NodeID)
|
c.Assert(leader.NodeID(), checker.Equals, stableleader.NodeID())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DockerSwarmSuite) TestAPISwarmRaftQuorum(c *check.C) {
|
func (s *DockerSwarmSuite) TestAPISwarmRaftQuorum(c *check.C) {
|
||||||
@ -400,8 +410,8 @@ func (s *DockerSwarmSuite) TestAPISwarmLeaveRemovesContainer(c *check.C) {
|
|||||||
|
|
||||||
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances+1)
|
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances+1)
|
||||||
|
|
||||||
c.Assert(d.Leave(false), checker.NotNil)
|
c.Assert(d.SwarmLeave(false), checker.NotNil)
|
||||||
c.Assert(d.Leave(true), checker.IsNil)
|
c.Assert(d.SwarmLeave(true), checker.IsNil)
|
||||||
|
|
||||||
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
|
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
|
||||||
|
|
||||||
@ -420,17 +430,18 @@ func (s *DockerSwarmSuite) TestAPISwarmLeaveOnPendingJoin(c *check.C) {
|
|||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
id = strings.TrimSpace(id)
|
id = strings.TrimSpace(id)
|
||||||
|
|
||||||
err = d2.Join(swarm.JoinRequest{
|
c2 := d2.NewClientT(c)
|
||||||
|
err = c2.SwarmJoin(context.Background(), swarm.JoinRequest{
|
||||||
|
ListenAddr: d2.SwarmListenAddr(),
|
||||||
RemoteAddrs: []string{"123.123.123.123:1234"},
|
RemoteAddrs: []string{"123.123.123.123:1234"},
|
||||||
})
|
})
|
||||||
c.Assert(err, check.NotNil)
|
c.Assert(err, check.NotNil)
|
||||||
c.Assert(err.Error(), checker.Contains, "Timeout was reached")
|
c.Assert(err.Error(), checker.Contains, "Timeout was reached")
|
||||||
|
|
||||||
info, err := d2.SwarmInfo()
|
info := d2.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStatePending)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStatePending)
|
||||||
|
|
||||||
c.Assert(d2.Leave(true), checker.IsNil)
|
c.Assert(d2.SwarmLeave(true), checker.IsNil)
|
||||||
|
|
||||||
waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.Equals, 1)
|
waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.Equals, 1)
|
||||||
|
|
||||||
@ -443,7 +454,9 @@ func (s *DockerSwarmSuite) TestAPISwarmLeaveOnPendingJoin(c *check.C) {
|
|||||||
func (s *DockerSwarmSuite) TestAPISwarmRestoreOnPendingJoin(c *check.C) {
|
func (s *DockerSwarmSuite) TestAPISwarmRestoreOnPendingJoin(c *check.C) {
|
||||||
testRequires(c, Network)
|
testRequires(c, Network)
|
||||||
d := s.AddDaemon(c, false, false)
|
d := s.AddDaemon(c, false, false)
|
||||||
err := d.Join(swarm.JoinRequest{
|
client := d.NewClientT(c)
|
||||||
|
err := client.SwarmJoin(context.Background(), swarm.JoinRequest{
|
||||||
|
ListenAddr: d.SwarmListenAddr(),
|
||||||
RemoteAddrs: []string{"123.123.123.123:1234"},
|
RemoteAddrs: []string{"123.123.123.123:1234"},
|
||||||
})
|
})
|
||||||
c.Assert(err, check.NotNil)
|
c.Assert(err, check.NotNil)
|
||||||
@ -454,8 +467,7 @@ func (s *DockerSwarmSuite) TestAPISwarmRestoreOnPendingJoin(c *check.C) {
|
|||||||
d.Stop(c)
|
d.Stop(c)
|
||||||
d.Start(c)
|
d.Start(c)
|
||||||
|
|
||||||
info, err := d.SwarmInfo()
|
info := d.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -539,7 +551,7 @@ func (s *DockerSwarmSuite) TestAPISwarmForceNewCluster(c *check.C) {
|
|||||||
waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals, instances)
|
waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals, instances)
|
||||||
|
|
||||||
// drain d2, all containers should move to d1
|
// drain d2, all containers should move to d1
|
||||||
d1.UpdateNode(c, d2.NodeID, func(n *swarm.Node) {
|
d1.UpdateNode(c, d2.NodeID(), func(n *swarm.Node) {
|
||||||
n.Spec.Availability = swarm.NodeAvailabilityDrain
|
n.Spec.Availability = swarm.NodeAvailabilityDrain
|
||||||
})
|
})
|
||||||
waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.Equals, instances)
|
waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.Equals, instances)
|
||||||
@ -547,16 +559,15 @@ func (s *DockerSwarmSuite) TestAPISwarmForceNewCluster(c *check.C) {
|
|||||||
|
|
||||||
d2.Stop(c)
|
d2.Stop(c)
|
||||||
|
|
||||||
c.Assert(d1.Init(swarm.InitRequest{
|
d1.SwarmInit(c, swarm.InitRequest{
|
||||||
ForceNewCluster: true,
|
ForceNewCluster: true,
|
||||||
Spec: swarm.Spec{},
|
Spec: swarm.Spec{},
|
||||||
}), checker.IsNil)
|
})
|
||||||
|
|
||||||
waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.Equals, instances)
|
waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.Equals, instances)
|
||||||
|
|
||||||
d3 := s.AddDaemon(c, true, true)
|
d3 := s.AddDaemon(c, true, true)
|
||||||
info, err := d3.SwarmInfo()
|
info := d3.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.ControlAvailable, checker.True)
|
c.Assert(info.ControlAvailable, checker.True)
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
||||||
|
|
||||||
@ -622,7 +633,7 @@ func serviceForUpdate(s *swarm.Service) {
|
|||||||
s.Spec.Name = "updatetest"
|
s.Spec.Name = "updatetest"
|
||||||
}
|
}
|
||||||
|
|
||||||
func setInstances(replicas int) daemon.ServiceConstructor {
|
func setInstances(replicas int) testdaemon.ServiceConstructor {
|
||||||
ureplicas := uint64(replicas)
|
ureplicas := uint64(replicas)
|
||||||
return func(s *swarm.Service) {
|
return func(s *swarm.Service) {
|
||||||
s.Spec.Mode = swarm.ServiceMode{
|
s.Spec.Mode = swarm.ServiceMode{
|
||||||
@ -633,7 +644,7 @@ func setInstances(replicas int) daemon.ServiceConstructor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setUpdateOrder(order string) daemon.ServiceConstructor {
|
func setUpdateOrder(order string) testdaemon.ServiceConstructor {
|
||||||
return func(s *swarm.Service) {
|
return func(s *swarm.Service) {
|
||||||
if s.Spec.UpdateConfig == nil {
|
if s.Spec.UpdateConfig == nil {
|
||||||
s.Spec.UpdateConfig = &swarm.UpdateConfig{}
|
s.Spec.UpdateConfig = &swarm.UpdateConfig{}
|
||||||
@ -642,7 +653,7 @@ func setUpdateOrder(order string) daemon.ServiceConstructor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setRollbackOrder(order string) daemon.ServiceConstructor {
|
func setRollbackOrder(order string) testdaemon.ServiceConstructor {
|
||||||
return func(s *swarm.Service) {
|
return func(s *swarm.Service) {
|
||||||
if s.Spec.RollbackConfig == nil {
|
if s.Spec.RollbackConfig == nil {
|
||||||
s.Spec.RollbackConfig = &swarm.UpdateConfig{}
|
s.Spec.RollbackConfig = &swarm.UpdateConfig{}
|
||||||
@ -651,7 +662,7 @@ func setRollbackOrder(order string) daemon.ServiceConstructor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setImage(image string) daemon.ServiceConstructor {
|
func setImage(image string) testdaemon.ServiceConstructor {
|
||||||
return func(s *swarm.Service) {
|
return func(s *swarm.Service) {
|
||||||
if s.Spec.TaskTemplate.ContainerSpec == nil {
|
if s.Spec.TaskTemplate.ContainerSpec == nil {
|
||||||
s.Spec.TaskTemplate.ContainerSpec = &swarm.ContainerSpec{}
|
s.Spec.TaskTemplate.ContainerSpec = &swarm.ContainerSpec{}
|
||||||
@ -660,25 +671,25 @@ func setImage(image string) daemon.ServiceConstructor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setFailureAction(failureAction string) daemon.ServiceConstructor {
|
func setFailureAction(failureAction string) testdaemon.ServiceConstructor {
|
||||||
return func(s *swarm.Service) {
|
return func(s *swarm.Service) {
|
||||||
s.Spec.UpdateConfig.FailureAction = failureAction
|
s.Spec.UpdateConfig.FailureAction = failureAction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setMaxFailureRatio(maxFailureRatio float32) daemon.ServiceConstructor {
|
func setMaxFailureRatio(maxFailureRatio float32) testdaemon.ServiceConstructor {
|
||||||
return func(s *swarm.Service) {
|
return func(s *swarm.Service) {
|
||||||
s.Spec.UpdateConfig.MaxFailureRatio = maxFailureRatio
|
s.Spec.UpdateConfig.MaxFailureRatio = maxFailureRatio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setParallelism(parallelism uint64) daemon.ServiceConstructor {
|
func setParallelism(parallelism uint64) testdaemon.ServiceConstructor {
|
||||||
return func(s *swarm.Service) {
|
return func(s *swarm.Service) {
|
||||||
s.Spec.UpdateConfig.Parallelism = parallelism
|
s.Spec.UpdateConfig.Parallelism = parallelism
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setConstraints(constraints []string) daemon.ServiceConstructor {
|
func setConstraints(constraints []string) testdaemon.ServiceConstructor {
|
||||||
return func(s *swarm.Service) {
|
return func(s *swarm.Service) {
|
||||||
if s.Spec.TaskTemplate.Placement == nil {
|
if s.Spec.TaskTemplate.Placement == nil {
|
||||||
s.Spec.TaskTemplate.Placement = &swarm.Placement{}
|
s.Spec.TaskTemplate.Placement = &swarm.Placement{}
|
||||||
@ -687,7 +698,7 @@ func setConstraints(constraints []string) daemon.ServiceConstructor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setPlacementPrefs(prefs []swarm.PlacementPreference) daemon.ServiceConstructor {
|
func setPlacementPrefs(prefs []swarm.PlacementPreference) testdaemon.ServiceConstructor {
|
||||||
return func(s *swarm.Service) {
|
return func(s *swarm.Service) {
|
||||||
if s.Spec.TaskTemplate.Placement == nil {
|
if s.Spec.TaskTemplate.Placement == nil {
|
||||||
s.Spec.TaskTemplate.Placement = &swarm.Placement{}
|
s.Spec.TaskTemplate.Placement = &swarm.Placement{}
|
||||||
@ -702,18 +713,19 @@ func setGlobalMode(s *swarm.Service) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkClusterHealth(c *check.C, cl []*daemon.Swarm, managerCount, workerCount int) {
|
func checkClusterHealth(c *check.C, cl []*daemon.Daemon, managerCount, workerCount int) {
|
||||||
var totalMCount, totalWCount int
|
var totalMCount, totalWCount int
|
||||||
|
|
||||||
for _, d := range cl {
|
for _, d := range cl {
|
||||||
var (
|
var (
|
||||||
info swarm.Info
|
info swarm.Info
|
||||||
err error
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// check info in a waitAndAssert, because if the cluster doesn't have a leader, `info` will return an error
|
// check info in a waitAndAssert, because if the cluster doesn't have a leader, `info` will return an error
|
||||||
checkInfo := func(c *check.C) (interface{}, check.CommentInterface) {
|
checkInfo := func(c *check.C) (interface{}, check.CommentInterface) {
|
||||||
info, err = d.SwarmInfo()
|
client := d.NewClientT(c)
|
||||||
|
daemonInfo, err := client.Info(context.Background())
|
||||||
|
info = daemonInfo.Swarm
|
||||||
return err, check.Commentf("cluster not ready in time")
|
return err, check.Commentf("cluster not ready in time")
|
||||||
}
|
}
|
||||||
waitAndAssert(c, defaultReconciliationTimeout, checkInfo, checker.IsNil)
|
waitAndAssert(c, defaultReconciliationTimeout, checkInfo, checker.IsNil)
|
||||||
@ -733,7 +745,7 @@ func checkClusterHealth(c *check.C, cl []*daemon.Swarm, managerCount, workerCoun
|
|||||||
}
|
}
|
||||||
nn := d.GetNode(c, n.ID)
|
nn := d.GetNode(c, n.ID)
|
||||||
n = *nn
|
n = *nn
|
||||||
return n.Status.State == swarm.NodeStateReady, check.Commentf("state of node %s, reported by %s", n.ID, d.Info.NodeID)
|
return n.Status.State == swarm.NodeStateReady, check.Commentf("state of node %s, reported by %s", n.ID, d.NodeID())
|
||||||
}
|
}
|
||||||
waitAndAssert(c, defaultReconciliationTimeout, waitReady, checker.True)
|
waitAndAssert(c, defaultReconciliationTimeout, waitReady, checker.True)
|
||||||
|
|
||||||
@ -743,18 +755,18 @@ func checkClusterHealth(c *check.C, cl []*daemon.Swarm, managerCount, workerCoun
|
|||||||
}
|
}
|
||||||
nn := d.GetNode(c, n.ID)
|
nn := d.GetNode(c, n.ID)
|
||||||
n = *nn
|
n = *nn
|
||||||
return n.Spec.Availability == swarm.NodeAvailabilityActive, check.Commentf("availability of node %s, reported by %s", n.ID, d.Info.NodeID)
|
return n.Spec.Availability == swarm.NodeAvailabilityActive, check.Commentf("availability of node %s, reported by %s", n.ID, d.NodeID())
|
||||||
}
|
}
|
||||||
waitAndAssert(c, defaultReconciliationTimeout, waitActive, checker.True)
|
waitAndAssert(c, defaultReconciliationTimeout, waitActive, checker.True)
|
||||||
|
|
||||||
if n.Spec.Role == swarm.NodeRoleManager {
|
if n.Spec.Role == swarm.NodeRoleManager {
|
||||||
c.Assert(n.ManagerStatus, checker.NotNil, check.Commentf("manager status of node %s (manager), reported by %s", n.ID, d.Info.NodeID))
|
c.Assert(n.ManagerStatus, checker.NotNil, check.Commentf("manager status of node %s (manager), reported by %s", n.ID, d.NodeID()))
|
||||||
if n.ManagerStatus.Leader {
|
if n.ManagerStatus.Leader {
|
||||||
leaderFound = true
|
leaderFound = true
|
||||||
}
|
}
|
||||||
mCount++
|
mCount++
|
||||||
} else {
|
} else {
|
||||||
c.Assert(n.ManagerStatus, checker.IsNil, check.Commentf("manager status of node %s (worker), reported by %s", n.ID, d.Info.NodeID))
|
c.Assert(n.ManagerStatus, checker.IsNil, check.Commentf("manager status of node %s (worker), reported by %s", n.ID, d.NodeID()))
|
||||||
wCount++
|
wCount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -769,11 +781,10 @@ func checkClusterHealth(c *check.C, cl []*daemon.Swarm, managerCount, workerCoun
|
|||||||
func (s *DockerSwarmSuite) TestAPISwarmRestartCluster(c *check.C) {
|
func (s *DockerSwarmSuite) TestAPISwarmRestartCluster(c *check.C) {
|
||||||
mCount, wCount := 5, 1
|
mCount, wCount := 5, 1
|
||||||
|
|
||||||
var nodes []*daemon.Swarm
|
var nodes []*daemon.Daemon
|
||||||
for i := 0; i < mCount; i++ {
|
for i := 0; i < mCount; i++ {
|
||||||
manager := s.AddDaemon(c, true, true)
|
manager := s.AddDaemon(c, true, true)
|
||||||
info, err := manager.SwarmInfo()
|
info := manager.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.ControlAvailable, checker.True)
|
c.Assert(info.ControlAvailable, checker.True)
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
||||||
nodes = append(nodes, manager)
|
nodes = append(nodes, manager)
|
||||||
@ -781,8 +792,7 @@ func (s *DockerSwarmSuite) TestAPISwarmRestartCluster(c *check.C) {
|
|||||||
|
|
||||||
for i := 0; i < wCount; i++ {
|
for i := 0; i < wCount; i++ {
|
||||||
worker := s.AddDaemon(c, true, false)
|
worker := s.AddDaemon(c, true, false)
|
||||||
info, err := worker.SwarmInfo()
|
info := worker.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.ControlAvailable, checker.False)
|
c.Assert(info.ControlAvailable, checker.False)
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
||||||
nodes = append(nodes, worker)
|
nodes = append(nodes, worker)
|
||||||
@ -795,7 +805,7 @@ func (s *DockerSwarmSuite) TestAPISwarmRestartCluster(c *check.C) {
|
|||||||
errs := make(chan error, len(nodes))
|
errs := make(chan error, len(nodes))
|
||||||
|
|
||||||
for _, d := range nodes {
|
for _, d := range nodes {
|
||||||
go func(daemon *daemon.Swarm) {
|
go func(daemon *daemon.Daemon) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
if err := daemon.StopWithError(); err != nil {
|
if err := daemon.StopWithError(); err != nil {
|
||||||
errs <- err
|
errs <- err
|
||||||
@ -820,7 +830,7 @@ func (s *DockerSwarmSuite) TestAPISwarmRestartCluster(c *check.C) {
|
|||||||
errs := make(chan error, len(nodes))
|
errs := make(chan error, len(nodes))
|
||||||
|
|
||||||
for _, d := range nodes {
|
for _, d := range nodes {
|
||||||
go func(daemon *daemon.Swarm) {
|
go func(daemon *daemon.Daemon) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
if err := daemon.StartWithError("--iptables=false"); err != nil {
|
if err := daemon.StartWithError("--iptables=false"); err != nil {
|
||||||
errs <- err
|
errs <- err
|
||||||
@ -859,7 +869,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesUpdateWithName(c *check.C) {
|
|||||||
// Unlocking an unlocked swarm results in an error
|
// Unlocking an unlocked swarm results in an error
|
||||||
func (s *DockerSwarmSuite) TestAPISwarmUnlockNotLocked(c *check.C) {
|
func (s *DockerSwarmSuite) TestAPISwarmUnlockNotLocked(c *check.C) {
|
||||||
d := s.AddDaemon(c, true, true)
|
d := s.AddDaemon(c, true, true)
|
||||||
err := d.Unlock(swarm.UnlockRequest{UnlockKey: "wrong-key"})
|
err := d.SwarmUnlock(swarm.UnlockRequest{UnlockKey: "wrong-key"})
|
||||||
c.Assert(err, checker.NotNil)
|
c.Assert(err, checker.NotNil)
|
||||||
c.Assert(err.Error(), checker.Contains, "swarm is not locked")
|
c.Assert(err.Error(), checker.Contains, "swarm is not locked")
|
||||||
}
|
}
|
||||||
@ -870,7 +880,10 @@ func (s *DockerSwarmSuite) TestAPISwarmErrorHandling(c *check.C) {
|
|||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
defer ln.Close()
|
defer ln.Close()
|
||||||
d := s.AddDaemon(c, false, false)
|
d := s.AddDaemon(c, false, false)
|
||||||
err = d.Init(swarm.InitRequest{})
|
client := d.NewClientT(c)
|
||||||
|
_, err = client.SwarmInit(context.Background(), swarm.InitRequest{
|
||||||
|
ListenAddr: d.SwarmListenAddr(),
|
||||||
|
})
|
||||||
c.Assert(err, checker.NotNil)
|
c.Assert(err, checker.NotNil)
|
||||||
c.Assert(err.Error(), checker.Contains, "address already in use")
|
c.Assert(err.Error(), checker.Contains, "address already in use")
|
||||||
}
|
}
|
||||||
@ -940,13 +953,13 @@ func (s *DockerSwarmSuite) TestSwarmRepeatedRootRotation(c *check.C) {
|
|||||||
m := s.AddDaemon(c, true, true)
|
m := s.AddDaemon(c, true, true)
|
||||||
w := s.AddDaemon(c, true, false)
|
w := s.AddDaemon(c, true, false)
|
||||||
|
|
||||||
info, err := m.SwarmInfo()
|
info := m.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
|
|
||||||
currentTrustRoot := info.Cluster.TLSInfo.TrustRoot
|
currentTrustRoot := info.Cluster.TLSInfo.TrustRoot
|
||||||
|
|
||||||
// rotate multiple times
|
// rotate multiple times
|
||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < 4; i++ {
|
||||||
|
var err error
|
||||||
var cert, key []byte
|
var cert, key []byte
|
||||||
if i%2 != 0 {
|
if i%2 != 0 {
|
||||||
cert, _, key, err = initca.New(&csr.CertificateRequest{
|
cert, _, key, err = initca.New(&csr.CertificateRequest{
|
||||||
@ -966,8 +979,7 @@ func (s *DockerSwarmSuite) TestSwarmRepeatedRootRotation(c *check.C) {
|
|||||||
// poll to make sure update succeeds
|
// poll to make sure update succeeds
|
||||||
var clusterTLSInfo swarm.TLSInfo
|
var clusterTLSInfo swarm.TLSInfo
|
||||||
for j := 0; j < 18; j++ {
|
for j := 0; j < 18; j++ {
|
||||||
info, err := m.SwarmInfo()
|
info := m.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
|
|
||||||
// the desired CA cert and key is always redacted
|
// the desired CA cert and key is always redacted
|
||||||
c.Assert(info.Cluster.Spec.CAConfig.SigningCAKey, checker.Equals, "")
|
c.Assert(info.Cluster.Spec.CAConfig.SigningCAKey, checker.Equals, "")
|
||||||
@ -989,8 +1001,8 @@ func (s *DockerSwarmSuite) TestSwarmRepeatedRootRotation(c *check.C) {
|
|||||||
// could take another second or two for the nodes to trust the new roots after they've all gotten
|
// could take another second or two for the nodes to trust the new roots after they've all gotten
|
||||||
// new TLS certificates
|
// new TLS certificates
|
||||||
for j := 0; j < 18; j++ {
|
for j := 0; j < 18; j++ {
|
||||||
mInfo := m.GetNode(c, m.NodeID).Description.TLSInfo
|
mInfo := m.GetNode(c, m.NodeID()).Description.TLSInfo
|
||||||
wInfo := m.GetNode(c, w.NodeID).Description.TLSInfo
|
wInfo := m.GetNode(c, w.NodeID()).Description.TLSInfo
|
||||||
|
|
||||||
if mInfo.TrustRoot == clusterTLSInfo.TrustRoot && wInfo.TrustRoot == clusterTLSInfo.TrustRoot {
|
if mInfo.TrustRoot == clusterTLSInfo.TrustRoot && wInfo.TrustRoot == clusterTLSInfo.TrustRoot {
|
||||||
break
|
break
|
||||||
@ -1000,8 +1012,8 @@ func (s *DockerSwarmSuite) TestSwarmRepeatedRootRotation(c *check.C) {
|
|||||||
time.Sleep(250 * time.Millisecond)
|
time.Sleep(250 * time.Millisecond)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Assert(m.GetNode(c, m.NodeID).Description.TLSInfo, checker.DeepEquals, clusterTLSInfo)
|
c.Assert(m.GetNode(c, m.NodeID()).Description.TLSInfo, checker.DeepEquals, clusterTLSInfo)
|
||||||
c.Assert(m.GetNode(c, w.NodeID).Description.TLSInfo, checker.DeepEquals, clusterTLSInfo)
|
c.Assert(m.GetNode(c, w.NodeID()).Description.TLSInfo, checker.DeepEquals, clusterTLSInfo)
|
||||||
currentTrustRoot = clusterTLSInfo.TrustRoot
|
currentTrustRoot = clusterTLSInfo.TrustRoot
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ import (
|
|||||||
"github.com/go-check/check"
|
"github.com/go-check/check"
|
||||||
)
|
)
|
||||||
|
|
||||||
func pruneNetworkAndVerify(c *check.C, d *daemon.Swarm, kept, pruned []string) {
|
func pruneNetworkAndVerify(c *check.C, d *daemon.Daemon, kept, pruned []string) {
|
||||||
_, err := d.Cmd("network", "prune", "--force")
|
_, err := d.Cmd("network", "prune", "--force")
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ func (s *DockerSwarmSuite) TestServiceLogs(c *check.C) {
|
|||||||
// countLogLines returns a closure that can be used with waitAndAssert to
|
// countLogLines returns a closure that can be used with waitAndAssert to
|
||||||
// verify that a minimum number of expected container log messages have been
|
// verify that a minimum number of expected container log messages have been
|
||||||
// output.
|
// output.
|
||||||
func countLogLines(d *daemon.Swarm, name string) func(*check.C) (interface{}, check.CommentInterface) {
|
func countLogLines(d *daemon.Daemon, name string) func(*check.C) (interface{}, check.CommentInterface) {
|
||||||
return func(c *check.C) (interface{}, check.CommentInterface) {
|
return func(c *check.C) (interface{}, check.CommentInterface) {
|
||||||
result := icmd.RunCmd(d.Command("service", "logs", "-t", "--raw", name))
|
result := icmd.RunCmd(d.Command("service", "logs", "-t", "--raw", name))
|
||||||
result.Assert(c, icmd.Expected{})
|
result.Assert(c, icmd.Expected{})
|
||||||
|
@ -57,7 +57,7 @@ func (s *DockerSwarmSuite) TestSwarmUpdate(c *check.C) {
|
|||||||
// passing an external CA (this is without starting a root rotation) does not fail
|
// passing an external CA (this is without starting a root rotation) does not fail
|
||||||
cli.Docker(cli.Args("swarm", "update", "--external-ca", "protocol=cfssl,url=https://something.org",
|
cli.Docker(cli.Args("swarm", "update", "--external-ca", "protocol=cfssl,url=https://something.org",
|
||||||
"--external-ca", "protocol=cfssl,url=https://somethingelse.org,cacert=fixtures/https/ca.pem"),
|
"--external-ca", "protocol=cfssl,url=https://somethingelse.org,cacert=fixtures/https/ca.pem"),
|
||||||
cli.Daemon(d.Daemon)).Assert(c, icmd.Success)
|
cli.Daemon(d)).Assert(c, icmd.Success)
|
||||||
|
|
||||||
expected, err := ioutil.ReadFile("fixtures/https/ca.pem")
|
expected, err := ioutil.ReadFile("fixtures/https/ca.pem")
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
@ -73,7 +73,7 @@ func (s *DockerSwarmSuite) TestSwarmUpdate(c *check.C) {
|
|||||||
|
|
||||||
result := cli.Docker(cli.Args("swarm", "update",
|
result := cli.Docker(cli.Args("swarm", "update",
|
||||||
"--external-ca", fmt.Sprintf("protocol=cfssl,url=https://something.org,cacert=%s", tempFile.Path())),
|
"--external-ca", fmt.Sprintf("protocol=cfssl,url=https://something.org,cacert=%s", tempFile.Path())),
|
||||||
cli.Daemon(d.Daemon))
|
cli.Daemon(d))
|
||||||
result.Assert(c, icmd.Expected{
|
result.Assert(c, icmd.Expected{
|
||||||
ExitCode: 125,
|
ExitCode: 125,
|
||||||
Err: "must be in PEM format",
|
Err: "must be in PEM format",
|
||||||
@ -94,7 +94,7 @@ func (s *DockerSwarmSuite) TestSwarmInit(c *check.C) {
|
|||||||
|
|
||||||
result := cli.Docker(cli.Args("swarm", "init", "--cert-expiry", "30h", "--dispatcher-heartbeat", "11s",
|
result := cli.Docker(cli.Args("swarm", "init", "--cert-expiry", "30h", "--dispatcher-heartbeat", "11s",
|
||||||
"--external-ca", fmt.Sprintf("protocol=cfssl,url=https://somethingelse.org,cacert=%s", tempFile.Path())),
|
"--external-ca", fmt.Sprintf("protocol=cfssl,url=https://somethingelse.org,cacert=%s", tempFile.Path())),
|
||||||
cli.Daemon(d.Daemon))
|
cli.Daemon(d))
|
||||||
result.Assert(c, icmd.Expected{
|
result.Assert(c, icmd.Expected{
|
||||||
ExitCode: 125,
|
ExitCode: 125,
|
||||||
Err: "must be in PEM format",
|
Err: "must be in PEM format",
|
||||||
@ -103,7 +103,7 @@ func (s *DockerSwarmSuite) TestSwarmInit(c *check.C) {
|
|||||||
cli.Docker(cli.Args("swarm", "init", "--cert-expiry", "30h", "--dispatcher-heartbeat", "11s",
|
cli.Docker(cli.Args("swarm", "init", "--cert-expiry", "30h", "--dispatcher-heartbeat", "11s",
|
||||||
"--external-ca", "protocol=cfssl,url=https://something.org",
|
"--external-ca", "protocol=cfssl,url=https://something.org",
|
||||||
"--external-ca", "protocol=cfssl,url=https://somethingelse.org,cacert=fixtures/https/ca.pem"),
|
"--external-ca", "protocol=cfssl,url=https://somethingelse.org,cacert=fixtures/https/ca.pem"),
|
||||||
cli.Daemon(d.Daemon)).Assert(c, icmd.Success)
|
cli.Daemon(d)).Assert(c, icmd.Success)
|
||||||
|
|
||||||
expected, err := ioutil.ReadFile("fixtures/https/ca.pem")
|
expected, err := ioutil.ReadFile("fixtures/https/ca.pem")
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
@ -115,8 +115,8 @@ func (s *DockerSwarmSuite) TestSwarmInit(c *check.C) {
|
|||||||
c.Assert(spec.CAConfig.ExternalCAs[0].CACert, checker.Equals, "")
|
c.Assert(spec.CAConfig.ExternalCAs[0].CACert, checker.Equals, "")
|
||||||
c.Assert(spec.CAConfig.ExternalCAs[1].CACert, checker.Equals, string(expected))
|
c.Assert(spec.CAConfig.ExternalCAs[1].CACert, checker.Equals, string(expected))
|
||||||
|
|
||||||
c.Assert(d.Leave(true), checker.IsNil)
|
c.Assert(d.SwarmLeave(true), checker.IsNil)
|
||||||
cli.Docker(cli.Args("swarm", "init"), cli.Daemon(d.Daemon)).Assert(c, icmd.Success)
|
cli.Docker(cli.Args("swarm", "init"), cli.Daemon(d)).Assert(c, icmd.Success)
|
||||||
|
|
||||||
spec = getSpec()
|
spec = getSpec()
|
||||||
c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 90*24*time.Hour)
|
c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 90*24*time.Hour)
|
||||||
@ -126,12 +126,12 @@ func (s *DockerSwarmSuite) TestSwarmInit(c *check.C) {
|
|||||||
func (s *DockerSwarmSuite) TestSwarmInitIPv6(c *check.C) {
|
func (s *DockerSwarmSuite) TestSwarmInitIPv6(c *check.C) {
|
||||||
testRequires(c, IPv6)
|
testRequires(c, IPv6)
|
||||||
d1 := s.AddDaemon(c, false, false)
|
d1 := s.AddDaemon(c, false, false)
|
||||||
cli.Docker(cli.Args("swarm", "init", "--listen-add", "::1"), cli.Daemon(d1.Daemon)).Assert(c, icmd.Success)
|
cli.Docker(cli.Args("swarm", "init", "--listen-add", "::1"), cli.Daemon(d1)).Assert(c, icmd.Success)
|
||||||
|
|
||||||
d2 := s.AddDaemon(c, false, false)
|
d2 := s.AddDaemon(c, false, false)
|
||||||
cli.Docker(cli.Args("swarm", "join", "::1"), cli.Daemon(d2.Daemon)).Assert(c, icmd.Success)
|
cli.Docker(cli.Args("swarm", "join", "::1"), cli.Daemon(d2)).Assert(c, icmd.Success)
|
||||||
|
|
||||||
out := cli.Docker(cli.Args("info"), cli.Daemon(d2.Daemon)).Assert(c, icmd.Success).Combined()
|
out := cli.Docker(cli.Args("info"), cli.Daemon(d2)).Assert(c, icmd.Success).Combined()
|
||||||
c.Assert(out, checker.Contains, "Swarm: active")
|
c.Assert(out, checker.Contains, "Swarm: active")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,13 +145,12 @@ func (s *DockerSwarmSuite) TestSwarmInitUnspecifiedAdvertiseAddr(c *check.C) {
|
|||||||
func (s *DockerSwarmSuite) TestSwarmIncompatibleDaemon(c *check.C) {
|
func (s *DockerSwarmSuite) TestSwarmIncompatibleDaemon(c *check.C) {
|
||||||
// init swarm mode and stop a daemon
|
// init swarm mode and stop a daemon
|
||||||
d := s.AddDaemon(c, true, true)
|
d := s.AddDaemon(c, true, true)
|
||||||
info, err := d.SwarmInfo()
|
info := d.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
||||||
d.Stop(c)
|
d.Stop(c)
|
||||||
|
|
||||||
// start a daemon with --cluster-store and --cluster-advertise
|
// start a daemon with --cluster-store and --cluster-advertise
|
||||||
err = d.StartWithError("--cluster-store=consul://consuladdr:consulport/some/path", "--cluster-advertise=1.1.1.1:2375")
|
err := d.StartWithError("--cluster-store=consul://consuladdr:consulport/some/path", "--cluster-advertise=1.1.1.1:2375")
|
||||||
c.Assert(err, checker.NotNil)
|
c.Assert(err, checker.NotNil)
|
||||||
content, err := d.ReadLogFile()
|
content, err := d.ReadLogFile()
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
@ -426,7 +425,7 @@ func (s *DockerSwarmSuite) TestOverlayAttachableOnSwarmLeave(c *check.C) {
|
|||||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||||
|
|
||||||
// Leave the swarm
|
// Leave the swarm
|
||||||
err = d.Leave(true)
|
err = d.SwarmLeave(true)
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
// Check the container is disconnected
|
// Check the container is disconnected
|
||||||
@ -989,13 +988,12 @@ func (s *DockerSwarmSuite) TestDNSConfigUpdate(c *check.C) {
|
|||||||
c.Assert(strings.TrimSpace(out), checker.Equals, "{[1.2.3.4] [example.com] [timeout:3]}")
|
c.Assert(strings.TrimSpace(out), checker.Equals, "{[1.2.3.4] [example.com] [timeout:3]}")
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNodeStatus(c *check.C, d *daemon.Swarm) swarm.LocalNodeState {
|
func getNodeStatus(c *check.C, d *daemon.Daemon) swarm.LocalNodeState {
|
||||||
info, err := d.SwarmInfo()
|
info := d.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
return info.LocalNodeState
|
return info.LocalNodeState
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkKeyIsEncrypted(d *daemon.Swarm) func(*check.C) (interface{}, check.CommentInterface) {
|
func checkKeyIsEncrypted(d *daemon.Daemon) func(*check.C) (interface{}, check.CommentInterface) {
|
||||||
return func(c *check.C) (interface{}, check.CommentInterface) {
|
return func(c *check.C) (interface{}, check.CommentInterface) {
|
||||||
keyBytes, err := ioutil.ReadFile(filepath.Join(d.Folder, "root", "swarm", "certificates", "swarm-node.key"))
|
keyBytes, err := ioutil.ReadFile(filepath.Join(d.Folder, "root", "swarm", "certificates", "swarm-node.key"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1011,7 +1009,7 @@ func checkKeyIsEncrypted(d *daemon.Swarm) func(*check.C) (interface{}, check.Com
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkSwarmLockedToUnlocked(c *check.C, d *daemon.Swarm, unlockKey string) {
|
func checkSwarmLockedToUnlocked(c *check.C, d *daemon.Daemon, unlockKey string) {
|
||||||
// Wait for the PEM file to become unencrypted
|
// Wait for the PEM file to become unencrypted
|
||||||
waitAndAssert(c, defaultReconciliationTimeout, checkKeyIsEncrypted(d), checker.Equals, false)
|
waitAndAssert(c, defaultReconciliationTimeout, checkKeyIsEncrypted(d), checker.Equals, false)
|
||||||
|
|
||||||
@ -1019,7 +1017,7 @@ func checkSwarmLockedToUnlocked(c *check.C, d *daemon.Swarm, unlockKey string) {
|
|||||||
c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateActive)
|
c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateActive)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkSwarmUnlockedToLocked(c *check.C, d *daemon.Swarm) {
|
func checkSwarmUnlockedToLocked(c *check.C, d *daemon.Daemon) {
|
||||||
// Wait for the PEM file to become encrypted
|
// Wait for the PEM file to become encrypted
|
||||||
waitAndAssert(c, defaultReconciliationTimeout, checkKeyIsEncrypted(d), checker.Equals, true)
|
waitAndAssert(c, defaultReconciliationTimeout, checkKeyIsEncrypted(d), checker.Equals, true)
|
||||||
|
|
||||||
@ -1117,8 +1115,7 @@ func (s *DockerSwarmSuite) TestSwarmLeaveLocked(c *check.C) {
|
|||||||
// It starts off locked
|
// It starts off locked
|
||||||
d.Restart(c, "--swarm-default-advertise-addr=lo")
|
d.Restart(c, "--swarm-default-advertise-addr=lo")
|
||||||
|
|
||||||
info, err := d.SwarmInfo()
|
info := d.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateLocked)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateLocked)
|
||||||
|
|
||||||
outs, _ = d.Cmd("node", "ls")
|
outs, _ = d.Cmd("node", "ls")
|
||||||
@ -1132,15 +1129,13 @@ func (s *DockerSwarmSuite) TestSwarmLeaveLocked(c *check.C) {
|
|||||||
outs, err = d.Cmd("swarm", "leave", "--force")
|
outs, err = d.Cmd("swarm", "leave", "--force")
|
||||||
c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs))
|
c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs))
|
||||||
|
|
||||||
info, err = d.SwarmInfo()
|
info = d.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
|
||||||
|
|
||||||
outs, err = d.Cmd("swarm", "init")
|
outs, err = d.Cmd("swarm", "init")
|
||||||
c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs))
|
c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs))
|
||||||
|
|
||||||
info, err = d.SwarmInfo()
|
info = d.SwarmInfo(c)
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1176,7 +1171,7 @@ func (s *DockerSwarmSuite) TestSwarmLockUnlockCluster(c *check.C) {
|
|||||||
c.Assert(outs, checker.Equals, unlockKey+"\n")
|
c.Assert(outs, checker.Equals, unlockKey+"\n")
|
||||||
|
|
||||||
// The ones that got the cluster update should be set to locked
|
// The ones that got the cluster update should be set to locked
|
||||||
for _, d := range []*daemon.Swarm{d1, d3} {
|
for _, d := range []*daemon.Daemon{d1, d3} {
|
||||||
checkSwarmUnlockedToLocked(c, d)
|
checkSwarmUnlockedToLocked(c, d)
|
||||||
|
|
||||||
cmd := d.Command("swarm", "unlock")
|
cmd := d.Command("swarm", "unlock")
|
||||||
@ -1197,7 +1192,7 @@ func (s *DockerSwarmSuite) TestSwarmLockUnlockCluster(c *check.C) {
|
|||||||
c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs))
|
c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs))
|
||||||
|
|
||||||
// the ones that got the update are now set to unlocked
|
// the ones that got the update are now set to unlocked
|
||||||
for _, d := range []*daemon.Swarm{d1, d3} {
|
for _, d := range []*daemon.Daemon{d1, d3} {
|
||||||
checkSwarmLockedToUnlocked(c, d, unlockKey)
|
checkSwarmLockedToUnlocked(c, d, unlockKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1247,7 +1242,7 @@ func (s *DockerSwarmSuite) TestSwarmJoinPromoteLocked(c *check.C) {
|
|||||||
c.Assert(getNodeStatus(c, d2), checker.Equals, swarm.LocalNodeStateActive)
|
c.Assert(getNodeStatus(c, d2), checker.Equals, swarm.LocalNodeStateActive)
|
||||||
|
|
||||||
// promote worker
|
// promote worker
|
||||||
outs, err = d1.Cmd("node", "promote", d2.Info.NodeID)
|
outs, err = d1.Cmd("node", "promote", d2.NodeID())
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
c.Assert(outs, checker.Contains, "promoted to a manager in the swarm")
|
c.Assert(outs, checker.Contains, "promoted to a manager in the swarm")
|
||||||
|
|
||||||
@ -1255,7 +1250,7 @@ func (s *DockerSwarmSuite) TestSwarmJoinPromoteLocked(c *check.C) {
|
|||||||
d3 := s.AddDaemon(c, true, true)
|
d3 := s.AddDaemon(c, true, true)
|
||||||
|
|
||||||
// both new nodes are locked
|
// both new nodes are locked
|
||||||
for _, d := range []*daemon.Swarm{d2, d3} {
|
for _, d := range []*daemon.Daemon{d2, d3} {
|
||||||
checkSwarmUnlockedToLocked(c, d)
|
checkSwarmUnlockedToLocked(c, d)
|
||||||
|
|
||||||
cmd := d.Command("swarm", "unlock")
|
cmd := d.Command("swarm", "unlock")
|
||||||
@ -1265,7 +1260,7 @@ func (s *DockerSwarmSuite) TestSwarmJoinPromoteLocked(c *check.C) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// demote manager back to worker - workers are not locked
|
// demote manager back to worker - workers are not locked
|
||||||
outs, err = d1.Cmd("node", "demote", d3.Info.NodeID)
|
outs, err = d1.Cmd("node", "demote", d3.NodeID())
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
c.Assert(outs, checker.Contains, "demoted in the swarm")
|
c.Assert(outs, checker.Contains, "demoted in the swarm")
|
||||||
|
|
||||||
@ -1409,7 +1404,7 @@ func (s *DockerSwarmSuite) TestSwarmClusterRotateUnlockKey(c *check.C) {
|
|||||||
d2.Restart(c)
|
d2.Restart(c)
|
||||||
d3.Restart(c)
|
d3.Restart(c)
|
||||||
|
|
||||||
for _, d := range []*daemon.Swarm{d2, d3} {
|
for _, d := range []*daemon.Daemon{d2, d3} {
|
||||||
c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateLocked)
|
c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateLocked)
|
||||||
|
|
||||||
outs, _ := d.Cmd("node", "ls")
|
outs, _ := d.Cmd("node", "ls")
|
||||||
@ -1521,7 +1516,7 @@ func (s *DockerSwarmSuite) TestSwarmManagerAddress(c *check.C) {
|
|||||||
d3 := s.AddDaemon(c, true, false)
|
d3 := s.AddDaemon(c, true, false)
|
||||||
|
|
||||||
// Manager Addresses will always show Node 1's address
|
// Manager Addresses will always show Node 1's address
|
||||||
expectedOutput := fmt.Sprintf("Manager Addresses:\n 127.0.0.1:%d\n", d1.Port)
|
expectedOutput := fmt.Sprintf("Manager Addresses:\n 127.0.0.1:%d\n", d1.SwarmPort)
|
||||||
|
|
||||||
out, err := d1.Cmd("info")
|
out, err := d1.Cmd("info")
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
@ -1641,7 +1636,7 @@ func (s *DockerSwarmSuite) TestSwarmJoinWithDrain(c *check.C) {
|
|||||||
|
|
||||||
d1 := s.AddDaemon(c, false, false)
|
d1 := s.AddDaemon(c, false, false)
|
||||||
|
|
||||||
out, err = d1.Cmd("swarm", "join", "--availability=drain", "--token", token, d.ListenAddr)
|
out, err = d1.Cmd("swarm", "join", "--availability=drain", "--token", token, d.SwarmListenAddr())
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "")
|
c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "")
|
||||||
|
|
||||||
@ -1835,7 +1830,7 @@ func (s *DockerSwarmSuite) TestSwarmJoinLeave(c *check.C) {
|
|||||||
// Verify that back to back join/leave does not cause panics
|
// Verify that back to back join/leave does not cause panics
|
||||||
d1 := s.AddDaemon(c, false, false)
|
d1 := s.AddDaemon(c, false, false)
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
out, err = d1.Cmd("swarm", "join", "--token", token, d.ListenAddr)
|
out, err = d1.Cmd("swarm", "join", "--token", token, d.SwarmListenAddr())
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "")
|
c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "")
|
||||||
|
|
||||||
@ -1846,7 +1841,7 @@ func (s *DockerSwarmSuite) TestSwarmJoinLeave(c *check.C) {
|
|||||||
|
|
||||||
const defaultRetryCount = 10
|
const defaultRetryCount = 10
|
||||||
|
|
||||||
func waitForEvent(c *check.C, d *daemon.Swarm, since string, filter string, event string, retry int) string {
|
func waitForEvent(c *check.C, d *daemon.Daemon, since string, filter string, event string, retry int) string {
|
||||||
if retry < 1 {
|
if retry < 1 {
|
||||||
c.Fatalf("retry count %d is invalid. It should be no less than 1", retry)
|
c.Fatalf("retry count %d is invalid. It should be no less than 1", retry)
|
||||||
return ""
|
return ""
|
||||||
@ -1982,7 +1977,7 @@ func (s *DockerSwarmSuite) TestSwarmClusterEventsNode(c *check.C) {
|
|||||||
s.AddDaemon(c, true, true)
|
s.AddDaemon(c, true, true)
|
||||||
d3 := s.AddDaemon(c, true, true)
|
d3 := s.AddDaemon(c, true, true)
|
||||||
|
|
||||||
d3ID := d3.NodeID
|
d3ID := d3.NodeID()
|
||||||
waitForEvent(c, d1, "0", "-f scope=swarm", "node create "+d3ID, defaultRetryCount)
|
waitForEvent(c, d1, "0", "-f scope=swarm", "node create "+d3ID, defaultRetryCount)
|
||||||
|
|
||||||
t1 := daemonUnixTime(c)
|
t1 := daemonUnixTime(c)
|
||||||
|
@ -2,7 +2,6 @@ package swarm
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -11,18 +10,13 @@ import (
|
|||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
swarmtypes "github.com/docker/docker/api/types/swarm"
|
swarmtypes "github.com/docker/docker/api/types/swarm"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/docker/docker/integration-cli/daemon"
|
"github.com/docker/docker/internal/test/daemon"
|
||||||
"github.com/docker/docker/internal/test/environment"
|
"github.com/docker/docker/internal/test/environment"
|
||||||
"github.com/gotestyourself/gotestyourself/assert"
|
"github.com/gotestyourself/gotestyourself/assert"
|
||||||
"github.com/gotestyourself/gotestyourself/poll"
|
"github.com/gotestyourself/gotestyourself/poll"
|
||||||
"github.com/gotestyourself/gotestyourself/skip"
|
"github.com/gotestyourself/gotestyourself/skip"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
dockerdBinary = "dockerd"
|
|
||||||
defaultSwarmPort = 2477
|
|
||||||
)
|
|
||||||
|
|
||||||
// ServicePoll tweaks the pollSettings for `service`
|
// ServicePoll tweaks the pollSettings for `service`
|
||||||
func ServicePoll(config *poll.Settings) {
|
func ServicePoll(config *poll.Settings) {
|
||||||
// Override the default pollSettings for `service` resource here ...
|
// Override the default pollSettings for `service` resource here ...
|
||||||
@ -55,23 +49,17 @@ func ContainerPoll(config *poll.Settings) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewSwarm creates a swarm daemon for testing
|
// NewSwarm creates a swarm daemon for testing
|
||||||
func NewSwarm(t *testing.T, testEnv *environment.Execution) *daemon.Swarm {
|
func NewSwarm(t *testing.T, testEnv *environment.Execution, ops ...func(*daemon.Daemon)) *daemon.Daemon {
|
||||||
skip.IfCondition(t, testEnv.IsRemoteDaemon())
|
skip.IfCondition(t, testEnv.IsRemoteDaemon())
|
||||||
d := &daemon.Swarm{
|
if testEnv.DaemonInfo.ExperimentalBuild {
|
||||||
Daemon: daemon.New(t, "", dockerdBinary, daemon.Config{
|
ops = append(ops, daemon.WithExperimental)
|
||||||
Experimental: testEnv.DaemonInfo.ExperimentalBuild,
|
|
||||||
}),
|
|
||||||
// TODO: better method of finding an unused port
|
|
||||||
Port: defaultSwarmPort,
|
|
||||||
}
|
}
|
||||||
// TODO: move to a NewSwarm constructor
|
d := daemon.New(t, ops...)
|
||||||
d.ListenAddr = fmt.Sprintf("0.0.0.0:%d", d.Port)
|
|
||||||
|
|
||||||
// avoid networking conflicts
|
// avoid networking conflicts
|
||||||
args := []string{"--iptables=false", "--swarm-default-advertise-addr=lo"}
|
args := []string{"--iptables=false", "--swarm-default-advertise-addr=lo"}
|
||||||
d.StartWithBusybox(t, args...)
|
d.StartWithBusybox(t, args...)
|
||||||
|
|
||||||
assert.NilError(t, d.Init(swarmtypes.InitRequest{}))
|
d.SwarmInit(t, swarmtypes.InitRequest{})
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +67,7 @@ func NewSwarm(t *testing.T, testEnv *environment.Execution) *daemon.Swarm {
|
|||||||
type ServiceSpecOpt func(*swarmtypes.ServiceSpec)
|
type ServiceSpecOpt func(*swarmtypes.ServiceSpec)
|
||||||
|
|
||||||
// CreateService creates a service on the passed in swarm daemon.
|
// CreateService creates a service on the passed in swarm daemon.
|
||||||
func CreateService(t *testing.T, d *daemon.Swarm, opts ...ServiceSpecOpt) string {
|
func CreateService(t *testing.T, d *daemon.Daemon, opts ...ServiceSpecOpt) string {
|
||||||
spec := defaultServiceSpec()
|
spec := defaultServiceSpec()
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
o(&spec)
|
o(&spec)
|
||||||
@ -151,7 +139,7 @@ func ServiceWithName(name string) ServiceSpecOpt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetRunningTasks gets the list of running tasks for a service
|
// GetRunningTasks gets the list of running tasks for a service
|
||||||
func GetRunningTasks(t *testing.T, d *daemon.Swarm, serviceID string) []swarmtypes.Task {
|
func GetRunningTasks(t *testing.T, d *daemon.Daemon, serviceID string) []swarmtypes.Task {
|
||||||
client := GetClient(t, d)
|
client := GetClient(t, d)
|
||||||
|
|
||||||
filterArgs := filters.NewArgs()
|
filterArgs := filters.NewArgs()
|
||||||
@ -167,7 +155,7 @@ func GetRunningTasks(t *testing.T, d *daemon.Swarm, serviceID string) []swarmtyp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ExecTask runs the passed in exec config on the given task
|
// ExecTask runs the passed in exec config on the given task
|
||||||
func ExecTask(t *testing.T, d *daemon.Swarm, task swarmtypes.Task, config types.ExecConfig) types.HijackedResponse {
|
func ExecTask(t *testing.T, d *daemon.Daemon, task swarmtypes.Task, config types.ExecConfig) types.HijackedResponse {
|
||||||
client := GetClient(t, d)
|
client := GetClient(t, d)
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
@ -187,7 +175,7 @@ func ensureContainerSpec(spec *swarmtypes.ServiceSpec) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetClient creates a new client for the passed in swarm daemon.
|
// GetClient creates a new client for the passed in swarm daemon.
|
||||||
func GetClient(t *testing.T, d *daemon.Swarm) client.APIClient {
|
func GetClient(t *testing.T, d *daemon.Daemon) client.APIClient {
|
||||||
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
return client
|
return client
|
||||||
|
66
internal/test/daemon/config.go
Normal file
66
internal/test/daemon/config.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package daemon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/swarm"
|
||||||
|
"github.com/gotestyourself/gotestyourself/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ConfigConstructor defines a swarm config constructor
|
||||||
|
type ConfigConstructor func(*swarm.Config)
|
||||||
|
|
||||||
|
// CreateConfig creates a config given the specified spec
|
||||||
|
func (d *Daemon) CreateConfig(t assert.TestingT, configSpec swarm.ConfigSpec) string {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
scr, err := cli.ConfigCreate(context.Background(), configSpec)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
return scr.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListConfigs returns the list of the current swarm configs
|
||||||
|
func (d *Daemon) ListConfigs(t assert.TestingT) []swarm.Config {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
configs, err := cli.ConfigList(context.Background(), types.ConfigListOptions{})
|
||||||
|
assert.NilError(t, err)
|
||||||
|
return configs
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetConfig returns a swarm config identified by the specified id
|
||||||
|
func (d *Daemon) GetConfig(t assert.TestingT, id string) *swarm.Config {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
config, _, err := cli.ConfigInspectWithRaw(context.Background(), id)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
return &config
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteConfig removes the swarm config identified by the specified id
|
||||||
|
func (d *Daemon) DeleteConfig(t assert.TestingT, id string) {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
err := cli.ConfigRemove(context.Background(), id)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateConfig updates the swarm config identified by the specified id
|
||||||
|
// Currently, only label update is supported.
|
||||||
|
func (d *Daemon) UpdateConfig(t assert.TestingT, id string, f ...ConfigConstructor) {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
config := d.GetConfig(t, id)
|
||||||
|
for _, fn := range f {
|
||||||
|
fn(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := cli.ConfigUpdate(context.Background(), config.ID, config.Version, config.Spec)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
}
|
@ -67,6 +67,13 @@ type Daemon struct {
|
|||||||
experimental bool
|
experimental bool
|
||||||
dockerdBinary string
|
dockerdBinary string
|
||||||
log logT
|
log logT
|
||||||
|
|
||||||
|
// swarm related field
|
||||||
|
swarmListenAddr string
|
||||||
|
SwarmPort int // FIXME(vdemeester) should probably not be exported
|
||||||
|
|
||||||
|
// cached information
|
||||||
|
CachedInfo types.Info
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a Daemon instance to be used for testing.
|
// New returns a Daemon instance to be used for testing.
|
||||||
@ -98,14 +105,16 @@ func New(t testingT, ops ...func(*Daemon)) *Daemon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
d := &Daemon{
|
d := &Daemon{
|
||||||
id: id,
|
id: id,
|
||||||
Folder: daemonFolder,
|
Folder: daemonFolder,
|
||||||
Root: daemonRoot,
|
Root: daemonRoot,
|
||||||
storageDriver: storageDriver,
|
storageDriver: storageDriver,
|
||||||
userlandProxy: userlandProxy,
|
userlandProxy: userlandProxy,
|
||||||
execRoot: filepath.Join(os.TempDir(), "docker-execroot", id),
|
execRoot: filepath.Join(os.TempDir(), "docker-execroot", id),
|
||||||
dockerdBinary: defaultDockerdBinary,
|
dockerdBinary: defaultDockerdBinary,
|
||||||
log: t,
|
swarmListenAddr: defaultSwarmListenAddr,
|
||||||
|
SwarmPort: defaultSwarmPort,
|
||||||
|
log: t,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, op := range ops {
|
for _, op := range ops {
|
||||||
@ -150,12 +159,23 @@ func (d *Daemon) ReadLogFile() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewClient creates new client based on daemon's socket path
|
// NewClient creates new client based on daemon's socket path
|
||||||
|
// FIXME(vdemeester): replace NewClient with NewClientT
|
||||||
func (d *Daemon) NewClient() (*client.Client, error) {
|
func (d *Daemon) NewClient() (*client.Client, error) {
|
||||||
return client.NewClientWithOpts(
|
return client.NewClientWithOpts(
|
||||||
client.FromEnv,
|
client.FromEnv,
|
||||||
client.WithHost(d.Sock()))
|
client.WithHost(d.Sock()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewClientT creates new client based on daemon's socket path
|
||||||
|
// FIXME(vdemeester): replace NewClient with NewClientT
|
||||||
|
func (d *Daemon) NewClientT(t assert.TestingT) *client.Client {
|
||||||
|
c, err := client.NewClientWithOpts(
|
||||||
|
client.FromEnv,
|
||||||
|
client.WithHost(d.Sock()))
|
||||||
|
assert.NilError(t, err, "cannot create daemon client")
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
// CleanupExecRoot cleans the daemon exec root (network namespaces, ...)
|
// CleanupExecRoot cleans the daemon exec root (network namespaces, ...)
|
||||||
func (d *Daemon) CleanupExecRoot(t testingT) {
|
func (d *Daemon) CleanupExecRoot(t testingT) {
|
||||||
cleanupExecRoot(t, d.execRoot)
|
cleanupExecRoot(t, d.execRoot)
|
||||||
@ -610,7 +630,7 @@ func (d *Daemon) queryRootDir() (string, error) {
|
|||||||
|
|
||||||
// Info returns the info struct for this daemon
|
// Info returns the info struct for this daemon
|
||||||
func (d *Daemon) Info(t assert.TestingT) types.Info {
|
func (d *Daemon) Info(t assert.TestingT) types.Info {
|
||||||
apiclient, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
apiclient, err := d.NewClient()
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
info, err := apiclient.Info(context.Background())
|
info, err := apiclient.Info(context.Background())
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
69
internal/test/daemon/node.go
Normal file
69
internal/test/daemon/node.go
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package daemon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/swarm"
|
||||||
|
"github.com/gotestyourself/gotestyourself/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NodeConstructor defines a swarm node constructor
|
||||||
|
type NodeConstructor func(*swarm.Node)
|
||||||
|
|
||||||
|
// GetNode returns a swarm node identified by the specified id
|
||||||
|
func (d *Daemon) GetNode(t assert.TestingT, id string) *swarm.Node {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
node, _, err := cli.NodeInspectWithRaw(context.Background(), id)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Check(t, node.ID == id)
|
||||||
|
return &node
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveNode removes the specified node
|
||||||
|
func (d *Daemon) RemoveNode(t assert.TestingT, id string, force bool) {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
options := types.NodeRemoveOptions{
|
||||||
|
Force: force,
|
||||||
|
}
|
||||||
|
err := cli.NodeRemove(context.Background(), id, options)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateNode updates a swarm node with the specified node constructor
|
||||||
|
func (d *Daemon) UpdateNode(t assert.TestingT, id string, f ...NodeConstructor) {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
for i := 0; ; i++ {
|
||||||
|
node := d.GetNode(t, id)
|
||||||
|
for _, fn := range f {
|
||||||
|
fn(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := cli.NodeUpdate(context.Background(), node.ID, node.Version, node.Spec)
|
||||||
|
if i < 10 && err != nil && strings.Contains(err.Error(), "update out of sequence") {
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
assert.NilError(t, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListNodes returns the list of the current swarm nodes
|
||||||
|
func (d *Daemon) ListNodes(t assert.TestingT) []swarm.Node {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
nodes, err := cli.NodeList(context.Background(), types.NodeListOptions{})
|
||||||
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
return nodes
|
||||||
|
}
|
@ -11,3 +11,17 @@ func WithDockerdBinary(dockerdBinary string) func(*Daemon) {
|
|||||||
d.dockerdBinary = dockerdBinary
|
d.dockerdBinary = dockerdBinary
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithSwarmPort sets the swarm port to use for swarm mode
|
||||||
|
func WithSwarmPort(port int) func(*Daemon) {
|
||||||
|
return func(d *Daemon) {
|
||||||
|
d.SwarmPort = port
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithSwarmListenAddr sets the swarm listen addr to use for swarm mode
|
||||||
|
func WithSwarmListenAddr(listenAddr string) func(*Daemon) {
|
||||||
|
return func(d *Daemon) {
|
||||||
|
d.swarmListenAddr = listenAddr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
68
internal/test/daemon/secret.go
Normal file
68
internal/test/daemon/secret.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package daemon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/swarm"
|
||||||
|
"github.com/gotestyourself/gotestyourself/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SecretConstructor defines a swarm secret constructor
|
||||||
|
type SecretConstructor func(*swarm.Secret)
|
||||||
|
|
||||||
|
// CreateSecret creates a secret given the specified spec
|
||||||
|
func (d *Daemon) CreateSecret(t assert.TestingT, secretSpec swarm.SecretSpec) string {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
scr, err := cli.SecretCreate(context.Background(), secretSpec)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
return scr.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListSecrets returns the list of the current swarm secrets
|
||||||
|
func (d *Daemon) ListSecrets(t assert.TestingT) []swarm.Secret {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
secrets, err := cli.SecretList(context.Background(), types.SecretListOptions{})
|
||||||
|
assert.NilError(t, err)
|
||||||
|
return secrets
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSecret returns a swarm secret identified by the specified id
|
||||||
|
func (d *Daemon) GetSecret(t assert.TestingT, id string) *swarm.Secret {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
secret, _, err := cli.SecretInspectWithRaw(context.Background(), id)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
return &secret
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteSecret removes the swarm secret identified by the specified id
|
||||||
|
func (d *Daemon) DeleteSecret(t assert.TestingT, id string) {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
err := cli.SecretRemove(context.Background(), id)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateSecret updates the swarm secret identified by the specified id
|
||||||
|
// Currently, only label update is supported.
|
||||||
|
func (d *Daemon) UpdateSecret(t assert.TestingT, id string, f ...SecretConstructor) {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
secret := d.GetSecret(t, id)
|
||||||
|
for _, fn := range f {
|
||||||
|
fn(secret)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := cli.SecretUpdate(context.Background(), secret.ID, secret.Version, secret.Spec)
|
||||||
|
|
||||||
|
assert.NilError(t, err)
|
||||||
|
}
|
108
internal/test/daemon/service.go
Normal file
108
internal/test/daemon/service.go
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
package daemon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/filters"
|
||||||
|
"github.com/docker/docker/api/types/swarm"
|
||||||
|
"github.com/gotestyourself/gotestyourself/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ServiceConstructor defines a swarm service constructor function
|
||||||
|
type ServiceConstructor func(*swarm.Service)
|
||||||
|
|
||||||
|
// CreateServiceWithOptions creates a swarm service given the specified service constructors
|
||||||
|
// and auth config
|
||||||
|
func (d *Daemon) CreateServiceWithOptions(t assert.TestingT, opts types.ServiceCreateOptions, f ...ServiceConstructor) string {
|
||||||
|
var service swarm.Service
|
||||||
|
for _, fn := range f {
|
||||||
|
fn(&service)
|
||||||
|
}
|
||||||
|
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
res, err := cli.ServiceCreate(ctx, service.Spec, opts)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
return res.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateService creates a swarm service given the specified service constructor
|
||||||
|
func (d *Daemon) CreateService(t assert.TestingT, f ...ServiceConstructor) string {
|
||||||
|
return d.CreateServiceWithOptions(t, types.ServiceCreateOptions{}, f...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetService returns the swarm service corresponding to the specified id
|
||||||
|
func (d *Daemon) GetService(t assert.TestingT, id string) *swarm.Service {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
service, _, err := cli.ServiceInspectWithRaw(context.Background(), id, types.ServiceInspectOptions{})
|
||||||
|
assert.NilError(t, err)
|
||||||
|
return &service
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetServiceTasks returns the swarm tasks for the specified service
|
||||||
|
func (d *Daemon) GetServiceTasks(t assert.TestingT, service string) []swarm.Task {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
filterArgs := filters.NewArgs()
|
||||||
|
filterArgs.Add("desired-state", "running")
|
||||||
|
filterArgs.Add("service", service)
|
||||||
|
|
||||||
|
options := types.TaskListOptions{
|
||||||
|
Filters: filterArgs,
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks, err := cli.TaskList(context.Background(), options)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
return tasks
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateService updates a swarm service with the specified service constructor
|
||||||
|
func (d *Daemon) UpdateService(t assert.TestingT, service *swarm.Service, f ...ServiceConstructor) {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
for _, fn := range f {
|
||||||
|
fn(service)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := cli.ServiceUpdate(context.Background(), service.ID, service.Version, service.Spec, types.ServiceUpdateOptions{})
|
||||||
|
assert.NilError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveService removes the specified service
|
||||||
|
func (d *Daemon) RemoveService(t assert.TestingT, id string) {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
err := cli.ServiceRemove(context.Background(), id)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListServices returns the list of the current swarm services
|
||||||
|
func (d *Daemon) ListServices(t assert.TestingT) []swarm.Service {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
services, err := cli.ServiceList(context.Background(), types.ServiceListOptions{})
|
||||||
|
assert.NilError(t, err)
|
||||||
|
return services
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTask returns the swarm task identified by the specified id
|
||||||
|
func (d *Daemon) GetTask(t assert.TestingT, id string) swarm.Task {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
task, _, err := cli.TaskInspectWithRaw(context.Background(), id)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
return task
|
||||||
|
}
|
139
internal/test/daemon/swarm.go
Normal file
139
internal/test/daemon/swarm.go
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
package daemon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/docker/docker/api/types/swarm"
|
||||||
|
"github.com/gotestyourself/gotestyourself/assert"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultSwarmPort = 2477
|
||||||
|
defaultSwarmListenAddr = "0.0.0.0"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SpecConstructor defines a swarm spec constructor
|
||||||
|
type SpecConstructor func(*swarm.Spec)
|
||||||
|
|
||||||
|
// SwarmListenAddr returns the listen-addr used for the daemon
|
||||||
|
func (d *Daemon) SwarmListenAddr() string {
|
||||||
|
return fmt.Sprintf("%s:%d", d.swarmListenAddr, d.SwarmPort)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NodeID returns the swarm mode node ID
|
||||||
|
func (d *Daemon) NodeID() string {
|
||||||
|
return d.CachedInfo.Swarm.NodeID
|
||||||
|
}
|
||||||
|
|
||||||
|
// SwarmInit initializes a new swarm cluster.
|
||||||
|
func (d *Daemon) SwarmInit(t assert.TestingT, req swarm.InitRequest) {
|
||||||
|
if req.ListenAddr == "" {
|
||||||
|
req.ListenAddr = fmt.Sprintf("%s:%d", d.swarmListenAddr, d.SwarmPort)
|
||||||
|
}
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
_, err := cli.SwarmInit(context.Background(), req)
|
||||||
|
assert.NilError(t, err, "initializing swarm")
|
||||||
|
d.CachedInfo = d.Info(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SwarmJoin joins a daemon to an existing cluster.
|
||||||
|
func (d *Daemon) SwarmJoin(t assert.TestingT, req swarm.JoinRequest) {
|
||||||
|
if req.ListenAddr == "" {
|
||||||
|
req.ListenAddr = fmt.Sprintf("%s:%d", d.swarmListenAddr, d.SwarmPort)
|
||||||
|
}
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
err := cli.SwarmJoin(context.Background(), req)
|
||||||
|
assert.NilError(t, err, "initializing swarm")
|
||||||
|
d.CachedInfo = d.Info(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SwarmLeave forces daemon to leave current cluster.
|
||||||
|
func (d *Daemon) SwarmLeave(force bool) error {
|
||||||
|
cli, err := d.NewClient()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("leaving swarm: failed to create client %v", err)
|
||||||
|
}
|
||||||
|
defer cli.Close()
|
||||||
|
err = cli.SwarmLeave(context.Background(), force)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("leaving swarm: %v", err)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SwarmInfo returns the swarm information of the daemon
|
||||||
|
func (d *Daemon) SwarmInfo(t assert.TestingT) swarm.Info {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
info, err := cli.Info(context.Background())
|
||||||
|
assert.NilError(t, err, "get swarm info")
|
||||||
|
return info.Swarm
|
||||||
|
}
|
||||||
|
|
||||||
|
// SwarmUnlock tries to unlock a locked swarm
|
||||||
|
func (d *Daemon) SwarmUnlock(req swarm.UnlockRequest) error {
|
||||||
|
cli, err := d.NewClient()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unlocking swarm: failed to create client %v", err)
|
||||||
|
}
|
||||||
|
defer cli.Close()
|
||||||
|
err = cli.SwarmUnlock(context.Background(), req)
|
||||||
|
if err != nil {
|
||||||
|
err = errors.Wrap(err, "unlocking swarm")
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSwarm returns the current swarm object
|
||||||
|
func (d *Daemon) GetSwarm(t assert.TestingT) swarm.Swarm {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
sw, err := cli.SwarmInspect(context.Background())
|
||||||
|
assert.NilError(t, err)
|
||||||
|
return sw
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateSwarm updates the current swarm object with the specified spec constructors
|
||||||
|
func (d *Daemon) UpdateSwarm(t assert.TestingT, f ...SpecConstructor) {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
sw := d.GetSwarm(t)
|
||||||
|
for _, fn := range f {
|
||||||
|
fn(&sw.Spec)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := cli.SwarmUpdate(context.Background(), sw.Version, sw.Spec, swarm.UpdateFlags{})
|
||||||
|
assert.NilError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RotateTokens update the swarm to rotate tokens
|
||||||
|
func (d *Daemon) RotateTokens(t assert.TestingT) {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
sw, err := cli.SwarmInspect(context.Background())
|
||||||
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
flags := swarm.UpdateFlags{
|
||||||
|
RotateManagerToken: true,
|
||||||
|
RotateWorkerToken: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = cli.SwarmUpdate(context.Background(), sw.Version, sw.Spec, flags)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// JoinTokens returns the current swarm join tokens
|
||||||
|
func (d *Daemon) JoinTokens(t assert.TestingT) swarm.JoinTokens {
|
||||||
|
cli := d.NewClientT(t)
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
sw, err := cli.SwarmInspect(context.Background())
|
||||||
|
assert.NilError(t, err)
|
||||||
|
return sw.JoinTokens
|
||||||
|
}
|
Reference in New Issue
Block a user