"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "components/engine/integration-cli/docker_cli_swarm_test.go" between
docker-ce-19.03.2.tar.gz and docker-ce-19.03.3.tar.gz

About: Docker CE is a project to pack, ship and run any application as a lightweight container. Docker containers can run anywhere, on a laptop or at scale, in production, on VMs, bare metal, OpenStack clusters, public clouds and more. Community edition.

docker_cli_swarm_test.go  (docker-ce-19.03.2):docker_cli_swarm_test.go  (docker-ce-19.03.3)
skipping to change at line 18 skipping to change at line 18
"encoding/json" "encoding/json"
"encoding/pem" "encoding/pem"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings" "strings"
"testing"
"time" "time"
"github.com/cloudflare/cfssl/helpers" "github.com/cloudflare/cfssl/helpers"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/integration-cli/checker" "github.com/docker/docker/integration-cli/checker"
"github.com/docker/docker/integration-cli/cli" "github.com/docker/docker/integration-cli/cli"
"github.com/docker/docker/integration-cli/daemon" "github.com/docker/docker/integration-cli/daemon"
"github.com/docker/libnetwork/driverapi" "github.com/docker/libnetwork/driverapi"
"github.com/docker/libnetwork/ipamapi" "github.com/docker/libnetwork/ipamapi"
remoteipam "github.com/docker/libnetwork/ipams/remote/api" remoteipam "github.com/docker/libnetwork/ipams/remote/api"
"github.com/docker/swarmkit/ca/keyutils" "github.com/docker/swarmkit/ca/keyutils"
"github.com/go-check/check"
"github.com/vishvananda/netlink" "github.com/vishvananda/netlink"
"gotest.tools/assert" "gotest.tools/assert"
"gotest.tools/fs" "gotest.tools/fs"
"gotest.tools/icmd" "gotest.tools/icmd"
"gotest.tools/poll"
) )
func (s *DockerSwarmSuite) TestSwarmUpdate(c *check.C) { func (s *DockerSwarmSuite) TestSwarmUpdate(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
getSpec := func() swarm.Spec { getSpec := func() swarm.Spec {
sw := d.GetSwarm(c) sw := d.GetSwarm(c)
return sw.Spec return sw.Spec
} }
out, err := d.Cmd("swarm", "update", "--cert-expiry", "30h", "--dispatche r-heartbeat", "11s") out, err := d.Cmd("swarm", "update", "--cert-expiry", "30h", "--dispatche r-heartbeat", "11s")
assert.NilError(c, err, out) assert.NilError(c, err, out)
spec := getSpec() spec := getSpec()
c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 30*time.Hour) assert.Equal(c, spec.CAConfig.NodeCertExpiry, 30*time.Hour)
c.Assert(spec.Dispatcher.HeartbeatPeriod, checker.Equals, 11*time.Second) assert.Equal(c, spec.Dispatcher.HeartbeatPeriod, 11*time.Second)
// setting anything under 30m for cert-expiry is not allowed // setting anything under 30m for cert-expiry is not allowed
out, err = d.Cmd("swarm", "update", "--cert-expiry", "15m") out, err = d.Cmd("swarm", "update", "--cert-expiry", "15m")
assert.ErrorContains(c, err, "") assert.ErrorContains(c, err, "")
c.Assert(out, checker.Contains, "minimum certificate expiry time") assert.Assert(c, strings.Contains(out, "minimum certificate expiry time") )
spec = getSpec() spec = getSpec()
c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 30*time.Hour) assert.Equal(c, spec.CAConfig.NodeCertExpiry, 30*time.Hour)
// 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,u rl=https://something.org", cli.Docker(cli.Args("swarm", "update", "--external-ca", "protocol=cfssl,u rl=https://something.org",
"--external-ca", "protocol=cfssl,url=https://somethingelse.org,ca cert=fixtures/https/ca.pem"), "--external-ca", "protocol=cfssl,url=https://somethingelse.org,ca cert=fixtures/https/ca.pem"),
cli.Daemon(d)).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")
assert.NilError(c, err) assert.NilError(c, err)
spec = getSpec() spec = getSpec()
c.Assert(spec.CAConfig.ExternalCAs, checker.HasLen, 2) assert.Equal(c, len(spec.CAConfig.ExternalCAs), 2)
c.Assert(spec.CAConfig.ExternalCAs[0].CACert, checker.Equals, "") assert.Equal(c, spec.CAConfig.ExternalCAs[0].CACert, "")
c.Assert(spec.CAConfig.ExternalCAs[1].CACert, checker.Equals, string(expe assert.Equal(c, spec.CAConfig.ExternalCAs[1].CACert, string(expected))
cted))
// passing an invalid external CA fails // passing an invalid external CA fails
tempFile := fs.NewFile(c, "testfile", fs.WithContent("fakecert")) tempFile := fs.NewFile(c, "testfile", fs.WithContent("fakecert"))
defer tempFile.Remove() defer tempFile.Remove()
result := cli.Docker(cli.Args("swarm", "update", result := cli.Docker(cli.Args("swarm", "update",
"--external-ca", fmt.Sprintf("protocol=cfssl,url=https://somethin g.org,cacert=%s", tempFile.Path())), "--external-ca", fmt.Sprintf("protocol=cfssl,url=https://somethin g.org,cacert=%s", tempFile.Path())),
cli.Daemon(d)) 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",
}) })
} }
func (s *DockerSwarmSuite) TestSwarmInit(c *check.C) { func (s *DockerSwarmSuite) TestSwarmInit(c *testing.T) {
d := s.AddDaemon(c, false, false) d := s.AddDaemon(c, false, false)
getSpec := func() swarm.Spec { getSpec := func() swarm.Spec {
sw := d.GetSwarm(c) sw := d.GetSwarm(c)
return sw.Spec return sw.Spec
} }
// passing an invalid external CA fails // passing an invalid external CA fails
tempFile := fs.NewFile(c, "testfile", fs.WithContent("fakecert")) tempFile := fs.NewFile(c, "testfile", fs.WithContent("fakecert"))
defer tempFile.Remove() defer tempFile.Remove()
skipping to change at line 114 skipping to change at line 115
cli.Docker(cli.Args("swarm", "init", "--cert-expiry", "30h", "--dispatche r-heartbeat", "11s", cli.Docker(cli.Args("swarm", "init", "--cert-expiry", "30h", "--dispatche r-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,ca cert=fixtures/https/ca.pem"), "--external-ca", "protocol=cfssl,url=https://somethingelse.org,ca cert=fixtures/https/ca.pem"),
cli.Daemon(d)).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")
assert.NilError(c, err) assert.NilError(c, err)
spec := getSpec() spec := getSpec()
c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 30*time.Hour) assert.Equal(c, spec.CAConfig.NodeCertExpiry, 30*time.Hour)
c.Assert(spec.Dispatcher.HeartbeatPeriod, checker.Equals, 11*time.Second) assert.Equal(c, spec.Dispatcher.HeartbeatPeriod, 11*time.Second)
c.Assert(spec.CAConfig.ExternalCAs, checker.HasLen, 2) assert.Equal(c, len(spec.CAConfig.ExternalCAs), 2)
c.Assert(spec.CAConfig.ExternalCAs[0].CACert, checker.Equals, "") assert.Equal(c, spec.CAConfig.ExternalCAs[0].CACert, "")
c.Assert(spec.CAConfig.ExternalCAs[1].CACert, checker.Equals, string(expe assert.Equal(c, spec.CAConfig.ExternalCAs[1].CACert, string(expected))
cted))
c.Assert(d.SwarmLeave(c, true), checker.IsNil) assert.Assert(c, d.SwarmLeave(c, true) == nil)
cli.Docker(cli.Args("swarm", "init"), cli.Daemon(d)).Assert(c, icmd.Succe ss) cli.Docker(cli.Args("swarm", "init"), cli.Daemon(d)).Assert(c, icmd.Succe ss)
spec = getSpec() spec = getSpec()
c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 90*24*time.Hour) assert.Equal(c, spec.CAConfig.NodeCertExpiry, 90*24*time.Hour)
c.Assert(spec.Dispatcher.HeartbeatPeriod, checker.Equals, 5*time.Second) assert.Equal(c, spec.Dispatcher.HeartbeatPeriod, 5*time.Second)
} }
func (s *DockerSwarmSuite) TestSwarmInitIPv6(c *check.C) { func (s *DockerSwarmSuite) TestSwarmInitIPv6(c *testing.T) {
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(d 1)).Assert(c, icmd.Success) cli.Docker(cli.Args("swarm", "init", "--listen-add", "::1"), cli.Daemon(d 1)).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)).Assert(c, ic md.Success) cli.Docker(cli.Args("swarm", "join", "::1"), cli.Daemon(d2)).Assert(c, ic md.Success)
out := cli.Docker(cli.Args("info"), cli.Daemon(d2)).Assert(c, icmd.Succes s).Combined() out := cli.Docker(cli.Args("info"), cli.Daemon(d2)).Assert(c, icmd.Succes s).Combined()
c.Assert(out, checker.Contains, "Swarm: active") assert.Assert(c, strings.Contains(out, "Swarm: active"))
} }
func (s *DockerSwarmSuite) TestSwarmInitUnspecifiedAdvertiseAddr(c *check.C) { func (s *DockerSwarmSuite) TestSwarmInitUnspecifiedAdvertiseAddr(c *testing.T) {
d := s.AddDaemon(c, false, false) d := s.AddDaemon(c, false, false)
out, err := d.Cmd("swarm", "init", "--advertise-addr", "0.0.0.0") out, err := d.Cmd("swarm", "init", "--advertise-addr", "0.0.0.0")
assert.ErrorContains(c, err, "") assert.ErrorContains(c, err, "")
c.Assert(out, checker.Contains, "advertise address must be a non-zero IP address") assert.Assert(c, strings.Contains(out, "advertise address must be a non-z ero IP address"))
} }
func (s *DockerSwarmSuite) TestSwarmIncompatibleDaemon(c *check.C) { func (s *DockerSwarmSuite) TestSwarmIncompatibleDaemon(c *testing.T) {
// 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 := d.SwarmInfo(c) info := d.SwarmInfo(c)
assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateActive) assert.Equal(c, info.LocalNodeState, 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/s ome/path", "--cluster-advertise=1.1.1.1:2375") err := d.StartWithError("--cluster-store=consul://consuladdr:consulport/s ome/path", "--cluster-advertise=1.1.1.1:2375")
assert.ErrorContains(c, err, "") assert.ErrorContains(c, err, "")
content, err := d.ReadLogFile() content, err := d.ReadLogFile()
assert.NilError(c, err) assert.NilError(c, err)
c.Assert(string(content), checker.Contains, "--cluster-store and --cluste assert.Assert(c, strings.Contains(string(content), "--cluster-store and -
r-advertise daemon configurations are incompatible with swarm mode") -cluster-advertise daemon configurations are incompatible with swarm mode"))
// start a daemon with --live-restore // start a daemon with --live-restore
err = d.StartWithError("--live-restore") err = d.StartWithError("--live-restore")
assert.ErrorContains(c, err, "") assert.ErrorContains(c, err, "")
content, err = d.ReadLogFile() content, err = d.ReadLogFile()
assert.NilError(c, err) assert.NilError(c, err)
c.Assert(string(content), checker.Contains, "--live-restore daemon config uration is incompatible with swarm mode") assert.Assert(c, strings.Contains(string(content), "--live-restore daemon configuration is incompatible with swarm mode"))
// restart for teardown // restart for teardown
d.StartNode(c) d.StartNode(c)
} }
func (s *DockerSwarmSuite) TestSwarmServiceTemplatingHostname(c *check.C) { func (s *DockerSwarmSuite) TestSwarmServiceTemplatingHostname(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
hostname, err := d.Cmd("node", "inspect", "--format", "{{.Description.Hos tname}}", "self") hostname, err := d.Cmd("node", "inspect", "--format", "{{.Description.Hos tname}}", "self")
c.Assert(err, checker.IsNil, check.Commentf("%s", hostname)) assert.Assert(c, err == nil, "%s", hostname)
out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", "test", "--hostname", "{{.Service.Name}}-{{.Task.Slot}}-{{.Node.Hostna me}}", "busybox", "top") out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", "test", "--hostname", "{{.Service.Name}}-{{.Task.Slot}}-{{.Node.Hostna me}}", "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
// make sure task has been deployed. // make sure task has been deployed.
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCoun t, checker.Equals, 1) poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1 )), poll.WithTimeout(defaultReconciliationTimeout))
containers := d.ActiveContainers(c) containers := d.ActiveContainers(c)
out, err = d.Cmd("inspect", "--type", "container", "--format", "{{.Config .Hostname}}", containers[0]) out, err = d.Cmd("inspect", "--type", "container", "--format", "{{.Config .Hostname}}", containers[0])
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(strings.Split(out, "\n")[0], checker.Equals, "test-1-"+strings.S plit(hostname, "\n")[0], check.Commentf("hostname with templating invalid")) assert.Equal(c, strings.Split(out, "\n")[0], "test-1-"+strings.Split(host name, "\n")[0], "hostname with templating invalid")
} }
// Test case for #24270 // Test case for #24270
func (s *DockerSwarmSuite) TestSwarmServiceListFilter(c *check.C) { func (s *DockerSwarmSuite) TestSwarmServiceListFilter(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
name1 := "redis-cluster-md5" name1 := "redis-cluster-md5"
name2 := "redis-cluster" name2 := "redis-cluster"
name3 := "other-cluster" name3 := "other-cluster"
out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name1, "busybox", "top") out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name1, "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
out, err = d.Cmd("service", "create", "--detach", "--no-resolve-image", " --name", name2, "busybox", "top") out, err = d.Cmd("service", "create", "--detach", "--no-resolve-image", " --name", name2, "busybox", "top")
skipping to change at line 213 skipping to change at line 213
out, err = d.Cmd("service", "create", "--detach", "--no-resolve-image", " --name", name3, "busybox", "top") out, err = d.Cmd("service", "create", "--detach", "--no-resolve-image", " --name", name3, "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
filter1 := "name=redis-cluster-md5" filter1 := "name=redis-cluster-md5"
filter2 := "name=redis-cluster" filter2 := "name=redis-cluster"
// We search checker.Contains with `name+" "` to prevent prefix only. // We search checker.Contains with `name+" "` to prevent prefix only.
out, err = d.Cmd("service", "ls", "--filter", filter1) out, err = d.Cmd("service", "ls", "--filter", filter1)
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(out, checker.Contains, name1+" ") assert.Assert(c, strings.Contains(out, name1+" "))
c.Assert(out, checker.Not(checker.Contains), name2+" ") assert.Assert(c, !strings.Contains(out, name2+" "))
c.Assert(out, checker.Not(checker.Contains), name3+" ") assert.Assert(c, !strings.Contains(out, name3+" "))
out, err = d.Cmd("service", "ls", "--filter", filter2) out, err = d.Cmd("service", "ls", "--filter", filter2)
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(out, checker.Contains, name1+" ") assert.Assert(c, strings.Contains(out, name1+" "))
c.Assert(out, checker.Contains, name2+" ") assert.Assert(c, strings.Contains(out, name2+" "))
c.Assert(out, checker.Not(checker.Contains), name3+" ") assert.Assert(c, !strings.Contains(out, name3+" "))
out, err = d.Cmd("service", "ls") out, err = d.Cmd("service", "ls")
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(out, checker.Contains, name1+" ") assert.Assert(c, strings.Contains(out, name1+" "))
c.Assert(out, checker.Contains, name2+" ") assert.Assert(c, strings.Contains(out, name2+" "))
c.Assert(out, checker.Contains, name3+" ") assert.Assert(c, strings.Contains(out, name3+" "))
} }
func (s *DockerSwarmSuite) TestSwarmNodeListFilter(c *check.C) { func (s *DockerSwarmSuite) TestSwarmNodeListFilter(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
out, err := d.Cmd("node", "inspect", "--format", "{{ .Description.Hostnam e }}", "self") out, err := d.Cmd("node", "inspect", "--format", "{{ .Description.Hostnam e }}", "self")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
name := strings.TrimSpace(out) name := strings.TrimSpace(out)
filter := "name=" + name[:4] filter := "name=" + name[:4]
out, err = d.Cmd("node", "ls", "--filter", filter) out, err = d.Cmd("node", "ls", "--filter", filter)
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(out, checker.Contains, name) assert.Assert(c, strings.Contains(out, name))
out, err = d.Cmd("node", "ls", "--filter", "name=none") out, err = d.Cmd("node", "ls", "--filter", "name=none")
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(out, checker.Not(checker.Contains), name) assert.Assert(c, !strings.Contains(out, name))
} }
func (s *DockerSwarmSuite) TestSwarmNodeTaskListFilter(c *check.C) { func (s *DockerSwarmSuite) TestSwarmNodeTaskListFilter(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
name := "redis-cluster-md5" name := "redis-cluster-md5"
out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "--replicas=3", "busybox", "top") out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "--replicas=3", "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
// make sure task has been deployed. // make sure task has been deployed.
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCoun t, checker.Equals, 3) poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(3 )), poll.WithTimeout(defaultReconciliationTimeout))
filter := "name=redis-cluster" filter := "name=redis-cluster"
out, err = d.Cmd("node", "ps", "--filter", filter, "self") out, err = d.Cmd("node", "ps", "--filter", filter, "self")
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(out, checker.Contains, name+".1") assert.Assert(c, strings.Contains(out, name+".1"))
c.Assert(out, checker.Contains, name+".2") assert.Assert(c, strings.Contains(out, name+".2"))
c.Assert(out, checker.Contains, name+".3") assert.Assert(c, strings.Contains(out, name+".3"))
out, err = d.Cmd("node", "ps", "--filter", "name=none", "self") out, err = d.Cmd("node", "ps", "--filter", "name=none", "self")
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(out, checker.Not(checker.Contains), name+".1") assert.Assert(c, !strings.Contains(out, name+".1"))
c.Assert(out, checker.Not(checker.Contains), name+".2") assert.Assert(c, !strings.Contains(out, name+".2"))
c.Assert(out, checker.Not(checker.Contains), name+".3") assert.Assert(c, !strings.Contains(out, name+".3"))
} }
// Test case for #25375 // Test case for #25375
func (s *DockerSwarmSuite) TestSwarmPublishAdd(c *check.C) { func (s *DockerSwarmSuite) TestSwarmPublishAdd(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
name := "top" name := "top"
// this first command does not have to be retried because service creates
// don't return out of sequence errors.
out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "--label", "x=y", "busybox", "top") out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "--label", "x=y", "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
out, err = d.Cmd("service", "update", "--detach", "--publish-add", "80:80 ", name) out, err = d.CmdRetryOutOfSequence("service", "update", "--detach", "--pu blish-add", "80:80", name)
assert.NilError(c, err, out) assert.NilError(c, err, out)
out, err = d.Cmd("service", "update", "--detach", "--publish-add", "80:80 ", name) out, err = d.CmdRetryOutOfSequence("service", "update", "--detach", "--pu blish-add", "80:80", name)
assert.NilError(c, err, out) assert.NilError(c, err, out)
_, err = d.Cmd("service", "update", "--detach", "--publish-add", "80:80", "--publish-add", "80:20", name) _, err = d.CmdRetryOutOfSequence("service", "update", "--detach", "--publ ish-add", "80:80", "--publish-add", "80:20", name)
assert.ErrorContains(c, err, "") assert.ErrorContains(c, err, "")
// this last command does not have to be retried because service inspect
// does not return out of sequence errors.
out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.EndpointSpec .Ports }}", name) out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.EndpointSpec .Ports }}", name)
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Equal(c, strings.TrimSpace(out), "[{ tcp 80 80 ingress}]") assert.Equal(c, strings.TrimSpace(out), "[{ tcp 80 80 ingress}]")
} }
func (s *DockerSwarmSuite) TestSwarmServiceWithGroup(c *check.C) { func (s *DockerSwarmSuite) TestSwarmServiceWithGroup(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
name := "top" name := "top"
out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "--user", "root:root", "--group", "wheel", "--group", "audio", " --group", "staff", "--group", "777", "busybox", "top") out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "--user", "root:root", "--group", "wheel", "--group", "audio", " --group", "staff", "--group", "777", "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
// make sure task has been deployed. // make sure task has been deployed.
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCoun t, checker.Equals, 1) poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1 )), poll.WithTimeout(defaultReconciliationTimeout))
out, err = d.Cmd("ps", "-q") out, err = d.Cmd("ps", "-q")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
container := strings.TrimSpace(out) container := strings.TrimSpace(out)
out, err = d.Cmd("exec", container, "id") out, err = d.Cmd("exec", container, "id")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Equal(c, strings.TrimSpace(out), "uid=0(root) gid=0(root) groups=1 0(wheel),29(audio),50(staff),777") assert.Equal(c, strings.TrimSpace(out), "uid=0(root) gid=0(root) groups=1 0(wheel),29(audio),50(staff),777")
} }
func (s *DockerSwarmSuite) TestSwarmContainerAutoStart(c *check.C) { func (s *DockerSwarmSuite) TestSwarmContainerAutoStart(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
out, err := d.Cmd("network", "create", "--attachable", "-d", "overlay", " foo") out, err := d.Cmd("network", "create", "--attachable", "-d", "overlay", " foo")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
out, err = d.Cmd("run", "-id", "--restart=always", "--net=foo", "--name=t est", "busybox", "top") out, err = d.Cmd("run", "-id", "--restart=always", "--net=foo", "--name=t est", "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
skipping to change at line 342 skipping to change at line 342
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
d.RestartNode(c) d.RestartNode(c)
out, err = d.Cmd("ps", "-q") out, err = d.Cmd("ps", "-q")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
} }
func (s *DockerSwarmSuite) TestSwarmContainerEndpointOptions(c *check.C) { func (s *DockerSwarmSuite) TestSwarmContainerEndpointOptions(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
out, err := d.Cmd("network", "create", "--attachable", "-d", "overlay", " foo") out, err := d.Cmd("network", "create", "--attachable", "-d", "overlay", " foo")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
out, err = d.Cmd("run", "-d", "--net=foo", "--name=first", "--net-alias=f irst-alias", "busybox:glibc", "top") out, err = d.Cmd("run", "-d", "--net=foo", "--name=first", "--net-alias=f irst-alias", "busybox:glibc", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
out, err = d.Cmd("run", "-d", "--net=foo", "--name=second", "busybox:glib c", "top") out, err = d.Cmd("run", "-d", "--net=foo", "--name=second", "busybox:glib c", "top")
skipping to change at line 367 skipping to change at line 367
// ping first container and its alias, also ping third and anonymous cont ainer by its alias // ping first container and its alias, also ping third and anonymous cont ainer by its alias
out, err = d.Cmd("exec", "second", "ping", "-c", "1", "first") out, err = d.Cmd("exec", "second", "ping", "-c", "1", "first")
assert.NilError(c, err, out) assert.NilError(c, err, out)
out, err = d.Cmd("exec", "second", "ping", "-c", "1", "first-alias") out, err = d.Cmd("exec", "second", "ping", "-c", "1", "first-alias")
assert.NilError(c, err, out) assert.NilError(c, err, out)
out, err = d.Cmd("exec", "second", "ping", "-c", "1", "third-alias") out, err = d.Cmd("exec", "second", "ping", "-c", "1", "third-alias")
assert.NilError(c, err, out) assert.NilError(c, err, out)
} }
func (s *DockerSwarmSuite) TestSwarmContainerAttachByNetworkId(c *check.C) { func (s *DockerSwarmSuite) TestSwarmContainerAttachByNetworkId(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
out, err := d.Cmd("network", "create", "--attachable", "-d", "overlay", " testnet") out, err := d.Cmd("network", "create", "--attachable", "-d", "overlay", " testnet")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
networkID := strings.TrimSpace(out) networkID := strings.TrimSpace(out)
out, err = d.Cmd("run", "-d", "--net", networkID, "busybox", "top") out, err = d.Cmd("run", "-d", "--net", networkID, "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
cID := strings.TrimSpace(out) cID := strings.TrimSpace(out)
d.WaitRun(cID) d.WaitRun(cID)
out, err = d.Cmd("rm", "-f", cID) out, err = d.Cmd("rm", "-f", cID)
assert.NilError(c, err, out) assert.NilError(c, err, out)
out, err = d.Cmd("network", "rm", "testnet") out, err = d.Cmd("network", "rm", "testnet")
assert.NilError(c, err, out) assert.NilError(c, err, out)
checkNetwork := func(*check.C) (interface{}, check.CommentInterface) { checkNetwork := func(*testing.T) (interface{}, string) {
out, err := d.Cmd("network", "ls") out, err := d.Cmd("network", "ls")
assert.NilError(c, err) assert.NilError(c, err)
return out, nil return out, ""
} }
waitAndAssert(c, 3*time.Second, checkNetwork, checker.Not(checker.Contain s), "testnet") poll.WaitOn(c, pollCheck(c, checkNetwork, checker.Not(checker.Contains("t estnet"))), poll.WithTimeout(3*time.Second))
} }
func (s *DockerSwarmSuite) TestOverlayAttachable(c *check.C) { func (s *DockerSwarmSuite) TestOverlayAttachable(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
out, err := d.Cmd("network", "create", "-d", "overlay", "--attachable", " ovnet") out, err := d.Cmd("network", "create", "-d", "overlay", "--attachable", " ovnet")
assert.NilError(c, err, out) assert.NilError(c, err, out)
// validate attachable // validate attachable
out, err = d.Cmd("network", "inspect", "--format", "{{json .Attachable}}" , "ovnet") out, err = d.Cmd("network", "inspect", "--format", "{{json .Attachable}}" , "ovnet")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Equal(c, strings.TrimSpace(out), "true") assert.Equal(c, strings.TrimSpace(out), "true")
skipping to change at line 417 skipping to change at line 417
out, err = d.Cmd("run", "-d", "--network", "ovnet", "--name", "c1", "busy box", "top") out, err = d.Cmd("run", "-d", "--network", "ovnet", "--name", "c1", "busy box", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
// redo validation, there was a bug that the value of attachable changes after // redo validation, there was a bug that the value of attachable changes after
// containers attach to the network // containers attach to the network
out, err = d.Cmd("network", "inspect", "--format", "{{json .Attachable}}" , "ovnet") out, err = d.Cmd("network", "inspect", "--format", "{{json .Attachable}}" , "ovnet")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Equal(c, strings.TrimSpace(out), "true") assert.Equal(c, strings.TrimSpace(out), "true")
} }
func (s *DockerSwarmSuite) TestOverlayAttachableOnSwarmLeave(c *check.C) { func (s *DockerSwarmSuite) TestOverlayAttachableOnSwarmLeave(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
// Create an attachable swarm network // Create an attachable swarm network
nwName := "attovl" nwName := "attovl"
out, err := d.Cmd("network", "create", "-d", "overlay", "--attachable", n wName) out, err := d.Cmd("network", "create", "-d", "overlay", "--attachable", n wName)
assert.NilError(c, err, out) assert.NilError(c, err, out)
// Connect a container to the network // Connect a container to the network
out, err = d.Cmd("run", "-d", "--network", nwName, "--name", "c1", "busyb ox", "top") out, err = d.Cmd("run", "-d", "--network", nwName, "--name", "c1", "busyb ox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
// Leave the swarm // Leave the swarm
c.Assert(d.SwarmLeave(c, true), checker.IsNil) assert.Assert(c, d.SwarmLeave(c, true) == nil)
// Check the container is disconnected // Check the container is disconnected
out, err = d.Cmd("inspect", "c1", "--format", "{{.NetworkSettings.Network s."+nwName+"}}") out, err = d.Cmd("inspect", "c1", "--format", "{{.NetworkSettings.Network s."+nwName+"}}")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Equal(c, strings.TrimSpace(out), "<no value>") assert.Equal(c, strings.TrimSpace(out), "<no value>")
// Check the network is gone // Check the network is gone
out, err = d.Cmd("network", "ls", "--format", "{{.Name}}") out, err = d.Cmd("network", "ls", "--format", "{{.Name}}")
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(out, checker.Not(checker.Contains), nwName) assert.Assert(c, !strings.Contains(out, nwName))
} }
func (s *DockerSwarmSuite) TestOverlayAttachableReleaseResourcesOnFailure(c *che ck.C) { func (s *DockerSwarmSuite) TestOverlayAttachableReleaseResourcesOnFailure(c *tes ting.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
// Create attachable network // Create attachable network
out, err := d.Cmd("network", "create", "-d", "overlay", "--attachable", " --subnet", "10.10.9.0/24", "ovnet") out, err := d.Cmd("network", "create", "-d", "overlay", "--attachable", " --subnet", "10.10.9.0/24", "ovnet")
assert.NilError(c, err, out) assert.NilError(c, err, out)
// Attach a container with specific IP // Attach a container with specific IP
out, err = d.Cmd("run", "-d", "--network", "ovnet", "--name", "c1", "--ip ", "10.10.9.33", "busybox", "top") out, err = d.Cmd("run", "-d", "--network", "ovnet", "--name", "c1", "--ip ", "10.10.9.33", "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
skipping to change at line 467 skipping to change at line 467
// Remove first container // Remove first container
out, err = d.Cmd("rm", "-f", "c1") out, err = d.Cmd("rm", "-f", "c1")
assert.NilError(c, err, out) assert.NilError(c, err, out)
// Verify the network can be removed, no phantom network attachment task left over // Verify the network can be removed, no phantom network attachment task left over
out, err = d.Cmd("network", "rm", "ovnet") out, err = d.Cmd("network", "rm", "ovnet")
assert.NilError(c, err, out) assert.NilError(c, err, out)
} }
func (s *DockerSwarmSuite) TestSwarmIngressNetwork(c *check.C) { func (s *DockerSwarmSuite) TestSwarmIngressNetwork(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
// Ingress network can be removed // Ingress network can be removed
removeNetwork := func(name string) *icmd.Result { removeNetwork := func(name string) *icmd.Result {
return cli.Docker( return cli.Docker(
cli.Args("-H", d.Sock(), "network", "rm", name), cli.Args("-H", d.Sock(), "network", "rm", name),
cli.WithStdin(strings.NewReader("Y"))) cli.WithStdin(strings.NewReader("Y")))
} }
result := removeNetwork("ingress") result := removeNetwork("ingress")
result.Assert(c, icmd.Success) result.Assert(c, icmd.Success)
// And recreated // And recreated
out, err := d.Cmd("network", "create", "-d", "overlay", "--ingress", "new -ingress") out, err := d.Cmd("network", "create", "-d", "overlay", "--ingress", "new -ingress")
assert.NilError(c, err, out) assert.NilError(c, err, out)
// But only one is allowed // But only one is allowed
out, err = d.Cmd("network", "create", "-d", "overlay", "--ingress", "anot her-ingress") out, err = d.Cmd("network", "create", "-d", "overlay", "--ingress", "anot her-ingress")
assert.ErrorContains(c, err, "") assert.ErrorContains(c, err, "")
c.Assert(strings.TrimSpace(out), checker.Contains, "is already present") assert.Assert(c, strings.Contains(strings.TrimSpace(out), "is already pre
sent"))
// It cannot be removed if it is being used // It cannot be removed if it is being used
out, err = d.Cmd("service", "create", "--detach", "--no-resolve-image", " --name", "srv1", "-p", "9000:8000", "busybox", "top") out, err = d.Cmd("service", "create", "--detach", "--no-resolve-image", " --name", "srv1", "-p", "9000:8000", "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
result = removeNetwork("new-ingress") result = removeNetwork("new-ingress")
result.Assert(c, icmd.Expected{ result.Assert(c, icmd.Expected{
ExitCode: 1, ExitCode: 1,
Err: "ingress network cannot be removed because service", Err: "ingress network cannot be removed because service",
}) })
// But it can be removed once no more services depend on it // But it can be removed once no more services depend on it
out, err = d.Cmd("service", "update", "--detach", "--publish-rm", "9000:8 000", "srv1") out, err = d.Cmd("service", "update", "--detach", "--publish-rm", "9000:8 000", "srv1")
assert.NilError(c, err, out) assert.NilError(c, err, out)
result = removeNetwork("new-ingress") result = removeNetwork("new-ingress")
result.Assert(c, icmd.Success) result.Assert(c, icmd.Success)
// A service which needs the ingress network cannot be created if no ingr ess is present // A service which needs the ingress network cannot be created if no ingr ess is present
out, err = d.Cmd("service", "create", "--detach", "--no-resolve-image", " --name", "srv2", "-p", "500:500", "busybox", "top") out, err = d.Cmd("service", "create", "--detach", "--no-resolve-image", " --name", "srv2", "-p", "500:500", "busybox", "top")
assert.ErrorContains(c, err, "") assert.ErrorContains(c, err, "")
c.Assert(strings.TrimSpace(out), checker.Contains, "no ingress network is assert.Assert(c, strings.Contains(strings.TrimSpace(out), "no ingress net
present") work is present"))
// An existing service cannot be updated to use the ingress nw if the nw is not present // An existing service cannot be updated to use the ingress nw if the nw is not present
out, err = d.Cmd("service", "update", "--detach", "--publish-add", "9000: 8000", "srv1") out, err = d.Cmd("service", "update", "--detach", "--publish-add", "9000: 8000", "srv1")
assert.ErrorContains(c, err, "") assert.ErrorContains(c, err, "")
c.Assert(strings.TrimSpace(out), checker.Contains, "no ingress network is assert.Assert(c, strings.Contains(strings.TrimSpace(out), "no ingress net
present") work is present"))
// But services which do not need routing mesh can be created regardless // But services which do not need routing mesh can be created regardless
out, err = d.Cmd("service", "create", "--detach", "--no-resolve-image", " --name", "srv3", "--endpoint-mode", "dnsrr", "busybox", "top") out, err = d.Cmd("service", "create", "--detach", "--no-resolve-image", " --name", "srv3", "--endpoint-mode", "dnsrr", "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
} }
func (s *DockerSwarmSuite) TestSwarmCreateServiceWithNoIngressNetwork(c *check.C ) { func (s *DockerSwarmSuite) TestSwarmCreateServiceWithNoIngressNetwork(c *testing .T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
// Remove ingress network // Remove ingress network
result := cli.Docker( result := cli.Docker(
cli.Args("-H", d.Sock(), "network", "rm", "ingress"), cli.Args("-H", d.Sock(), "network", "rm", "ingress"),
cli.WithStdin(strings.NewReader("Y"))) cli.WithStdin(strings.NewReader("Y")))
result.Assert(c, icmd.Success) result.Assert(c, icmd.Success)
// Create a overlay network and launch a service on it // Create a overlay network and launch a service on it
// Make sure nothing panics because ingress network is missing // Make sure nothing panics because ingress network is missing
out, err := d.Cmd("network", "create", "-d", "overlay", "another-network" ) out, err := d.Cmd("network", "create", "-d", "overlay", "another-network" )
assert.NilError(c, err, out) assert.NilError(c, err, out)
out, err = d.Cmd("service", "create", "--detach", "--no-resolve-image", " --name", "srv4", "--network", "another-network", "busybox", "top") out, err = d.Cmd("service", "create", "--detach", "--no-resolve-image", " --name", "srv4", "--network", "another-network", "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
} }
// Test case for #24108, also the case from: // Test case for #24108, also the case from:
// https://github.com/docker/docker/pull/24620#issuecomment-233715656 // https://github.com/docker/docker/pull/24620#issuecomment-233715656
func (s *DockerSwarmSuite) TestSwarmTaskListFilter(c *check.C) { func (s *DockerSwarmSuite) TestSwarmTaskListFilter(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
name := "redis-cluster-md5" name := "redis-cluster-md5"
out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "--replicas=3", "busybox", "top") out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "--replicas=3", "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
filter := "name=redis-cluster" filter := "name=redis-cluster"
checkNumTasks := func(*check.C) (interface{}, check.CommentInterface) { checkNumTasks := func(*testing.T) (interface{}, string) {
out, err := d.Cmd("service", "ps", "--filter", filter, name) out, err := d.Cmd("service", "ps", "--filter", filter, name)
assert.NilError(c, err, out) assert.NilError(c, err, out)
return len(strings.Split(out, "\n")) - 2, nil // includes header and nl in last line return len(strings.Split(out, "\n")) - 2, "" // includes header a nd nl in last line
} }
// wait until all tasks have been created // wait until all tasks have been created
waitAndAssert(c, defaultReconciliationTimeout, checkNumTasks, checker.Equ als, 3) poll.WaitOn(c, pollCheck(c, checkNumTasks, checker.Equals(3)), poll.WithT imeout(defaultReconciliationTimeout))
out, err = d.Cmd("service", "ps", "--filter", filter, name) out, err = d.Cmd("service", "ps", "--filter", filter, name)
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(out, checker.Contains, name+".1") assert.Assert(c, strings.Contains(out, name+".1"))
c.Assert(out, checker.Contains, name+".2") assert.Assert(c, strings.Contains(out, name+".2"))
c.Assert(out, checker.Contains, name+".3") assert.Assert(c, strings.Contains(out, name+".3"))
out, err = d.Cmd("service", "ps", "--filter", "name="+name+".1", name) out, err = d.Cmd("service", "ps", "--filter", "name="+name+".1", name)
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(out, checker.Contains, name+".1") assert.Assert(c, strings.Contains(out, name+".1"))
c.Assert(out, checker.Not(checker.Contains), name+".2") assert.Assert(c, !strings.Contains(out, name+".2"))
c.Assert(out, checker.Not(checker.Contains), name+".3") assert.Assert(c, !strings.Contains(out, name+".3"))
out, err = d.Cmd("service", "ps", "--filter", "name=none", name) out, err = d.Cmd("service", "ps", "--filter", "name=none", name)
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(out, checker.Not(checker.Contains), name+".1") assert.Assert(c, !strings.Contains(out, name+".1"))
c.Assert(out, checker.Not(checker.Contains), name+".2") assert.Assert(c, !strings.Contains(out, name+".2"))
c.Assert(out, checker.Not(checker.Contains), name+".3") assert.Assert(c, !strings.Contains(out, name+".3"))
name = "redis-cluster-sha1" name = "redis-cluster-sha1"
out, err = d.Cmd("service", "create", "--detach", "--no-resolve-image", " --name", name, "--mode=global", "busybox", "top") out, err = d.Cmd("service", "create", "--detach", "--no-resolve-image", " --name", name, "--mode=global", "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
waitAndAssert(c, defaultReconciliationTimeout, checkNumTasks, checker.Equ als, 1) poll.WaitOn(c, pollCheck(c, checkNumTasks, checker.Equals(1)), poll.WithT imeout(defaultReconciliationTimeout))
filter = "name=redis-cluster" filter = "name=redis-cluster"
out, err = d.Cmd("service", "ps", "--filter", filter, name) out, err = d.Cmd("service", "ps", "--filter", filter, name)
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(out, checker.Contains, name) assert.Assert(c, strings.Contains(out, name))
out, err = d.Cmd("service", "ps", "--filter", "name="+name, name) out, err = d.Cmd("service", "ps", "--filter", "name="+name, name)
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(out, checker.Contains, name) assert.Assert(c, strings.Contains(out, name))
out, err = d.Cmd("service", "ps", "--filter", "name=none", name) out, err = d.Cmd("service", "ps", "--filter", "name=none", name)
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(out, checker.Not(checker.Contains), name) assert.Assert(c, !strings.Contains(out, name))
} }
func (s *DockerSwarmSuite) TestPsListContainersFilterIsTask(c *check.C) { func (s *DockerSwarmSuite) TestPsListContainersFilterIsTask(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
// Create a bare container // Create a bare container
out, err := d.Cmd("run", "-d", "--name=bare-container", "busybox", "top") out, err := d.Cmd("run", "-d", "--name=bare-container", "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
bareID := strings.TrimSpace(out)[:12] bareID := strings.TrimSpace(out)[:12]
// Create a service // Create a service
name := "busybox-top" name := "busybox-top"
out, err = d.Cmd("service", "create", "--detach", "--no-resolve-image", " --name", name, "busybox", "top") out, err = d.Cmd("service", "create", "--detach", "--no-resolve-image", " --name", name, "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
// make sure task has been deployed. // make sure task has been deployed.
waitAndAssert(c, defaultReconciliationTimeout, d.CheckServiceRunningTasks (name), checker.Equals, 1) poll.WaitOn(c, pollCheck(c, d.CheckServiceRunningTasks(name), checker.Equ als(1)), poll.WithTimeout(defaultReconciliationTimeout))
// Filter non-tasks // Filter non-tasks
out, err = d.Cmd("ps", "-a", "-q", "--filter=is-task=false") out, err = d.Cmd("ps", "-a", "-q", "--filter=is-task=false")
assert.NilError(c, err, out) assert.NilError(c, err, out)
psOut := strings.TrimSpace(out) psOut := strings.TrimSpace(out)
c.Assert(psOut, checker.Equals, bareID, check.Commentf("Expected id %s, g ot %s for is-task label, output %q", bareID, psOut, out)) assert.Equal(c, psOut, bareID, fmt.Sprintf("Expected id %s, got %s for is -task label, output %q", bareID, psOut, out))
// Filter tasks // Filter tasks
out, err = d.Cmd("ps", "-a", "-q", "--filter=is-task=true") out, err = d.Cmd("ps", "-a", "-q", "--filter=is-task=true")
assert.NilError(c, err, out) assert.NilError(c, err, out)
lines := strings.Split(strings.Trim(out, "\n "), "\n") lines := strings.Split(strings.Trim(out, "\n "), "\n")
assert.Equal(c, len(lines), 1) assert.Equal(c, len(lines), 1)
c.Assert(lines[0], checker.Not(checker.Equals), bareID, check.Commentf("E xpected not %s, but got it for is-task label, output %q", bareID, out)) assert.Assert(c, lines[0] != bareID, "Expected not %s, but got it for is- task label, output %q", bareID, out)
} }
const globalNetworkPlugin = "global-network-plugin" const globalNetworkPlugin = "global-network-plugin"
const globalIPAMPlugin = "global-ipam-plugin" const globalIPAMPlugin = "global-ipam-plugin"
func setupRemoteGlobalNetworkPlugin(c *check.C, mux *http.ServeMux, url, netDrv, ipamDrv string) { func setupRemoteGlobalNetworkPlugin(c *testing.T, mux *http.ServeMux, url, netDr v, ipamDrv string) {
mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Re quest) { mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Re quest) {
w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1 +json") w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1 +json")
fmt.Fprintf(w, `{"Implements": ["%s", "%s"]}`, driverapi.NetworkP luginEndpointType, ipamapi.PluginEndpointType) fmt.Fprintf(w, `{"Implements": ["%s", "%s"]}`, driverapi.NetworkP luginEndpointType, ipamapi.PluginEndpointType)
}) })
// Network driver implementation // Network driver implementation
mux.HandleFunc(fmt.Sprintf("/%s.GetCapabilities", driverapi.NetworkPlugin EndpointType), func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc(fmt.Sprintf("/%s.GetCapabilities", driverapi.NetworkPlugin EndpointType), func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1 +json") w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1 +json")
fmt.Fprintf(w, `{"Scope":"global"}`) fmt.Fprintf(w, `{"Scope":"global"}`)
skipping to change at line 799 skipping to change at line 791
fileName := fmt.Sprintf("/etc/docker/plugins/%s.spec", netDrv) fileName := fmt.Sprintf("/etc/docker/plugins/%s.spec", netDrv)
err = ioutil.WriteFile(fileName, []byte(url), 0644) err = ioutil.WriteFile(fileName, []byte(url), 0644)
assert.NilError(c, err) assert.NilError(c, err)
ipamFileName := fmt.Sprintf("/etc/docker/plugins/%s.spec", ipamDrv) ipamFileName := fmt.Sprintf("/etc/docker/plugins/%s.spec", ipamDrv)
err = ioutil.WriteFile(ipamFileName, []byte(url), 0644) err = ioutil.WriteFile(ipamFileName, []byte(url), 0644)
assert.NilError(c, err) assert.NilError(c, err)
} }
func (s *DockerSwarmSuite) TestSwarmNetworkPlugin(c *check.C) { func (s *DockerSwarmSuite) TestSwarmNetworkPlugin(c *testing.T) {
mux := http.NewServeMux() mux := http.NewServeMux()
s.server = httptest.NewServer(mux) s.server = httptest.NewServer(mux)
c.Assert(s.server, check.NotNil) // check that HTTP server has started assert.Assert(c, s.server != nil) // check that HTTP server has started
setupRemoteGlobalNetworkPlugin(c, mux, s.server.URL, globalNetworkPlugin, globalIPAMPlugin) setupRemoteGlobalNetworkPlugin(c, mux, s.server.URL, globalNetworkPlugin, globalIPAMPlugin)
defer func() { defer func() {
s.server.Close() s.server.Close()
err := os.RemoveAll("/etc/docker/plugins") err := os.RemoveAll("/etc/docker/plugins")
assert.NilError(c, err) assert.NilError(c, err)
}() }()
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
out, err := d.Cmd("network", "create", "-d", globalNetworkPlugin, "foo") out, err := d.Cmd("network", "create", "-d", globalNetworkPlugin, "foo")
assert.ErrorContains(c, err, "", out) assert.ErrorContains(c, err, "", out)
c.Assert(out, checker.Contains, "not supported in swarm mode") assert.Assert(c, strings.Contains(out, "not supported in swarm mode"))
} }
// Test case for #24712 // Test case for #24712
func (s *DockerSwarmSuite) TestSwarmServiceEnvFile(c *check.C) { func (s *DockerSwarmSuite) TestSwarmServiceEnvFile(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
path := filepath.Join(d.Folder, "env.txt") path := filepath.Join(d.Folder, "env.txt")
err := ioutil.WriteFile(path, []byte("VAR1=A\nVAR2=A\n"), 0644) err := ioutil.WriteFile(path, []byte("VAR1=A\nVAR2=A\n"), 0644)
assert.NilError(c, err) assert.NilError(c, err)
name := "worker" name := "worker"
out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--env-file", path, "--env", "VAR1=B", "--env", "VAR1=C", "--env", "VAR2=", "--e nv", "VAR2", "--name", name, "busybox", "top") out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--env-file", path, "--env", "VAR1=B", "--env", "VAR1=C", "--env", "VAR2=", "--e nv", "VAR2", "--name", name, "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
// The complete env is [VAR1=A VAR2=A VAR1=B VAR1=C VAR2= VAR2] and dupli cates will be removed => [VAR1=C VAR2] // The complete env is [VAR1=A VAR2=A VAR1=B VAR1=C VAR2= VAR2] and dupli cates will be removed => [VAR1=C VAR2]
out, err = d.Cmd("inspect", "--format", "{{ .Spec.TaskTemplate.ContainerS pec.Env }}", name) out, err = d.Cmd("inspect", "--format", "{{ .Spec.TaskTemplate.ContainerS pec.Env }}", name)
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(out, checker.Contains, "[VAR1=C VAR2]") assert.Assert(c, strings.Contains(out, "[VAR1=C VAR2]"))
} }
func (s *DockerSwarmSuite) TestSwarmServiceTTY(c *check.C) { func (s *DockerSwarmSuite) TestSwarmServiceTTY(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
name := "top" name := "top"
ttyCheck := "if [ -t 0 ]; then echo TTY > /status && top; else echo none > /status && top; fi" ttyCheck := "if [ -t 0 ]; then echo TTY > /status; else echo none > /stat us; fi; exec top"
// Without --tty // Without --tty
expectedOutput := "none" expectedOutput := "none"
out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "busybox", "sh", "-c", ttyCheck) out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "busybox", "sh", "-c", ttyCheck)
assert.NilError(c, err, out) assert.NilError(c, err, out)
// Make sure task has been deployed. // Make sure task has been deployed.
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCoun t, checker.Equals, 1) poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1 )), poll.WithTimeout(defaultReconciliationTimeout))
// We need to get the container id. // We need to get the container id.
out, err = d.Cmd("ps", "-q", "--no-trunc") out, err = d.Cmd("ps", "-q", "--no-trunc")
assert.NilError(c, err, out) assert.NilError(c, err, out)
id := strings.TrimSpace(out) id := strings.TrimSpace(out)
out, err = d.Cmd("exec", id, "cat", "/status") out, err = d.Cmd("exec", id, "cat", "/status")
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(out, checker.Contains, expectedOutput, check.Commentf("Expected assert.Assert(c, strings.Contains(out, expectedOutput), "Expected '%s', b
'%s', but got %q", expectedOutput, out)) ut got %q", expectedOutput, out)
// Remove service // Remove service
out, err = d.Cmd("service", "rm", name) out, err = d.Cmd("service", "rm", name)
assert.NilError(c, err, out) assert.NilError(c, err, out)
// Make sure container has been destroyed. // Make sure container has been destroyed.
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCoun t, checker.Equals, 0) poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(0 )), poll.WithTimeout(defaultReconciliationTimeout))
// With --tty // With --tty
expectedOutput = "TTY" expectedOutput = "TTY"
out, err = d.Cmd("service", "create", "--detach", "--no-resolve-image", " --name", name, "--tty", "busybox", "sh", "-c", ttyCheck) out, err = d.Cmd("service", "create", "--detach", "--no-resolve-image", " --name", name, "--tty", "busybox", "sh", "-c", ttyCheck)
assert.NilError(c, err, out) assert.NilError(c, err, out)
// Make sure task has been deployed. // Make sure task has been deployed.
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCoun t, checker.Equals, 1) poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1 )), poll.WithTimeout(defaultReconciliationTimeout))
// We need to get the container id. // We need to get the container id.
out, err = d.Cmd("ps", "-q", "--no-trunc") out, err = d.Cmd("ps", "-q", "--no-trunc")
assert.NilError(c, err, out) assert.NilError(c, err, out)
id = strings.TrimSpace(out) id = strings.TrimSpace(out)
out, err = d.Cmd("exec", id, "cat", "/status") out, err = d.Cmd("exec", id, "cat", "/status")
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(out, checker.Contains, expectedOutput, check.Commentf("Expected '%s', but got %q", expectedOutput, out)) assert.Assert(c, strings.Contains(out, expectedOutput), "Expected '%s', b ut got %q", expectedOutput, out)
} }
func (s *DockerSwarmSuite) TestSwarmServiceTTYUpdate(c *check.C) { func (s *DockerSwarmSuite) TestSwarmServiceTTYUpdate(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
// Create a service // Create a service
name := "top" name := "top"
out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "busybox", "top") out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
// Make sure task has been deployed. // Make sure task has been deployed.
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCoun t, checker.Equals, 1) poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1 )), poll.WithTimeout(defaultReconciliationTimeout))
out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.TaskTemplate .ContainerSpec.TTY }}", name) out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.TaskTemplate .ContainerSpec.TTY }}", name)
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Equal(c, strings.TrimSpace(out), "false") assert.Equal(c, strings.TrimSpace(out), "false")
out, err = d.Cmd("service", "update", "--detach", "--tty", name) out, err = d.Cmd("service", "update", "--detach", "--tty", name)
assert.NilError(c, err, out) assert.NilError(c, err, out)
out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.TaskTemplate .ContainerSpec.TTY }}", name) out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.TaskTemplate .ContainerSpec.TTY }}", name)
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Equal(c, strings.TrimSpace(out), "true") assert.Equal(c, strings.TrimSpace(out), "true")
} }
func (s *DockerSwarmSuite) TestSwarmServiceNetworkUpdate(c *check.C) { func (s *DockerSwarmSuite) TestSwarmServiceNetworkUpdate(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
result := icmd.RunCmd(d.Command("network", "create", "-d", "overlay", "fo o")) result := icmd.RunCmd(d.Command("network", "create", "-d", "overlay", "fo o"))
result.Assert(c, icmd.Success) result.Assert(c, icmd.Success)
fooNetwork := strings.TrimSpace(string(result.Combined())) fooNetwork := strings.TrimSpace(string(result.Combined()))
result = icmd.RunCmd(d.Command("network", "create", "-d", "overlay", "bar ")) result = icmd.RunCmd(d.Command("network", "create", "-d", "overlay", "bar "))
result.Assert(c, icmd.Success) result.Assert(c, icmd.Success)
barNetwork := strings.TrimSpace(string(result.Combined())) barNetwork := strings.TrimSpace(string(result.Combined()))
result = icmd.RunCmd(d.Command("network", "create", "-d", "overlay", "baz ")) result = icmd.RunCmd(d.Command("network", "create", "-d", "overlay", "baz "))
result.Assert(c, icmd.Success) result.Assert(c, icmd.Success)
bazNetwork := strings.TrimSpace(string(result.Combined())) bazNetwork := strings.TrimSpace(string(result.Combined()))
// Create a service // Create a service
name := "top" name := "top"
result = icmd.RunCmd(d.Command("service", "create", "--detach", "--no-res olve-image", "--network", "foo", "--network", "bar", "--name", name, "busybox", "top")) result = icmd.RunCmd(d.Command("service", "create", "--detach", "--no-res olve-image", "--network", "foo", "--network", "bar", "--name", name, "busybox", "top"))
result.Assert(c, icmd.Success) result.Assert(c, icmd.Success)
// Make sure task has been deployed. // Make sure task has been deployed.
waitAndAssert(c, defaultReconciliationTimeout, d.CheckRunningTaskNetworks poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskNetworks, checker.DeepEqual
, checker.DeepEquals, s(map[string]int{fooNetwork: 1, barNetwork: 1})), poll.WithTimeout(defaultReconc
map[string]int{fooNetwork: 1, barNetwork: 1}) iliationTimeout))
// Remove a network // Remove a network
result = icmd.RunCmd(d.Command("service", "update", "--detach", "--networ k-rm", "foo", name)) result = icmd.RunCmd(d.Command("service", "update", "--detach", "--networ k-rm", "foo", name))
result.Assert(c, icmd.Success) result.Assert(c, icmd.Success)
waitAndAssert(c, defaultReconciliationTimeout, d.CheckRunningTaskNetworks poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskNetworks, checker.DeepEqual
, checker.DeepEquals, s(map[string]int{barNetwork: 1})), poll.WithTimeout(defaultReconciliationTimeout
map[string]int{barNetwork: 1}) ))
// Add a network // Add a network
result = icmd.RunCmd(d.Command("service", "update", "--detach", "--networ k-add", "baz", name)) result = icmd.RunCmd(d.Command("service", "update", "--detach", "--networ k-add", "baz", name))
result.Assert(c, icmd.Success) result.Assert(c, icmd.Success)
waitAndAssert(c, defaultReconciliationTimeout, d.CheckRunningTaskNetworks poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskNetworks, checker.DeepEqual
, checker.DeepEquals, s(map[string]int{barNetwork: 1, bazNetwork: 1})), poll.WithTimeout(defaultReconc
map[string]int{barNetwork: 1, bazNetwork: 1}) iliationTimeout))
} }
func (s *DockerSwarmSuite) TestDNSConfig(c *check.C) { func (s *DockerSwarmSuite) TestDNSConfig(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
// Create a service // Create a service
name := "top" name := "top"
out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "--dns=1.2.3.4", "--dns-search=example.com", "--dns-option=timeo ut:3", "busybox", "top") out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "--dns=1.2.3.4", "--dns-search=example.com", "--dns-option=timeo ut:3", "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
// Make sure task has been deployed. // Make sure task has been deployed.
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCoun t, checker.Equals, 1) poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1 )), poll.WithTimeout(defaultReconciliationTimeout))
// We need to get the container id. // We need to get the container id.
out, err = d.Cmd("ps", "-a", "-q", "--no-trunc") out, err = d.Cmd("ps", "-a", "-q", "--no-trunc")
assert.NilError(c, err, out) assert.NilError(c, err, out)
id := strings.TrimSpace(out) id := strings.TrimSpace(out)
// Compare against expected output. // Compare against expected output.
expectedOutput1 := "nameserver 1.2.3.4" expectedOutput1 := "nameserver 1.2.3.4"
expectedOutput2 := "search example.com" expectedOutput2 := "search example.com"
expectedOutput3 := "options timeout:3" expectedOutput3 := "options timeout:3"
out, err = d.Cmd("exec", id, "cat", "/etc/resolv.conf") out, err = d.Cmd("exec", id, "cat", "/etc/resolv.conf")
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(out, checker.Contains, expectedOutput1, check.Commentf("Expected assert.Assert(c, strings.Contains(out, expectedOutput1), "Expected '%s',
'%s', but got %q", expectedOutput1, out)) but got %q", expectedOutput1, out)
c.Assert(out, checker.Contains, expectedOutput2, check.Commentf("Expected assert.Assert(c, strings.Contains(out, expectedOutput2), "Expected '%s',
'%s', but got %q", expectedOutput2, out)) but got %q", expectedOutput2, out)
c.Assert(out, checker.Contains, expectedOutput3, check.Commentf("Expected assert.Assert(c, strings.Contains(out, expectedOutput3), "Expected '%s',
'%s', but got %q", expectedOutput3, out)) but got %q", expectedOutput3, out)
} }
func (s *DockerSwarmSuite) TestDNSConfigUpdate(c *check.C) { func (s *DockerSwarmSuite) TestDNSConfigUpdate(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
// Create a service // Create a service
name := "top" name := "top"
out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "busybox", "top") out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
// Make sure task has been deployed. // Make sure task has been deployed.
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCoun t, checker.Equals, 1) poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1 )), poll.WithTimeout(defaultReconciliationTimeout))
out, err = d.Cmd("service", "update", "--detach", "--dns-add=1.2.3.4", "- -dns-search-add=example.com", "--dns-option-add=timeout:3", name) out, err = d.Cmd("service", "update", "--detach", "--dns-add=1.2.3.4", "- -dns-search-add=example.com", "--dns-option-add=timeout:3", name)
assert.NilError(c, err, out) assert.NilError(c, err, out)
out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.TaskTemplate .ContainerSpec.DNSConfig }}", name) out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.TaskTemplate .ContainerSpec.DNSConfig }}", name)
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Equal(c, strings.TrimSpace(out), "{[1.2.3.4] [example.com] [timeou t:3]}") assert.Equal(c, strings.TrimSpace(out), "{[1.2.3.4] [example.com] [timeou t:3]}")
} }
func getNodeStatus(c *check.C, d *daemon.Daemon) swarm.LocalNodeState { func getNodeStatus(c *testing.T, d *daemon.Daemon) swarm.LocalNodeState {
info := d.SwarmInfo(c) info := d.SwarmInfo(c)
return info.LocalNodeState return info.LocalNodeState
} }
func checkKeyIsEncrypted(d *daemon.Daemon) func(*check.C) (interface{}, check.Co func checkKeyIsEncrypted(d *daemon.Daemon) func(*testing.T) (interface{}, string
mmentInterface) { ) {
return func(c *check.C) (interface{}, check.CommentInterface) { return func(c *testing.T) (interface{}, string) {
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 {
return fmt.Errorf("error reading key: %v", err), nil return fmt.Errorf("error reading key: %v", err), ""
} }
keyBlock, _ := pem.Decode(keyBytes) keyBlock, _ := pem.Decode(keyBytes)
if keyBlock == nil { if keyBlock == nil {
return fmt.Errorf("invalid PEM-encoded private key"), nil return fmt.Errorf("invalid PEM-encoded private key"), ""
} }
return keyutils.IsEncryptedPEMBlock(keyBlock), nil return keyutils.IsEncryptedPEMBlock(keyBlock), ""
} }
} }
func checkSwarmLockedToUnlocked(c *check.C, d *daemon.Daemon) { func checkSwarmLockedToUnlocked(c *testing.T, d *daemon.Daemon) {
// Wait for the PEM file to become unencrypted // Wait for the PEM file to become unencrypted
waitAndAssert(c, defaultReconciliationTimeout, checkKeyIsEncrypted(d), ch ecker.Equals, false) poll.WaitOn(c, pollCheck(c, checkKeyIsEncrypted(d), checker.Equals(false) ), poll.WithTimeout(defaultReconciliationTimeout))
d.RestartNode(c) d.RestartNode(c)
waitAndAssert(c, time.Second, d.CheckLocalNodeState, checker.Equals, swar m.LocalNodeStateActive) poll.WaitOn(c, pollCheck(c, d.CheckLocalNodeState, checker.Equals(swarm.L ocalNodeStateActive)), poll.WithTimeout(time.Second))
} }
func checkSwarmUnlockedToLocked(c *check.C, d *daemon.Daemon) { func checkSwarmUnlockedToLocked(c *testing.T, d *daemon.Daemon) {
// Wait for the PEM file to become encrypted // Wait for the PEM file to become encrypted
waitAndAssert(c, defaultReconciliationTimeout, checkKeyIsEncrypted(d), ch ecker.Equals, true) poll.WaitOn(c, pollCheck(c, checkKeyIsEncrypted(d), checker.Equals(true)) , poll.WithTimeout(defaultReconciliationTimeout))
d.RestartNode(c) d.RestartNode(c)
waitAndAssert(c, time.Second, d.CheckLocalNodeState, checker.Equals, swar m.LocalNodeStateLocked) poll.WaitOn(c, pollCheck(c, d.CheckLocalNodeState, checker.Equals(swarm.L ocalNodeStateLocked)), poll.WithTimeout(time.Second))
} }
func (s *DockerSwarmSuite) TestUnlockEngineAndUnlockedSwarm(c *check.C) { func (s *DockerSwarmSuite) TestUnlockEngineAndUnlockedSwarm(c *testing.T) {
d := s.AddDaemon(c, false, false) d := s.AddDaemon(c, false, false)
// unlocking a normal engine should return an error - it does not even as k for the key // unlocking a normal engine should return an error - it does not even as k for the key
cmd := d.Command("swarm", "unlock") cmd := d.Command("swarm", "unlock")
result := icmd.RunCmd(cmd) result := icmd.RunCmd(cmd)
result.Assert(c, icmd.Expected{ result.Assert(c, icmd.Expected{
ExitCode: 1, ExitCode: 1,
}) })
c.Assert(result.Combined(), checker.Contains, "Error: This node is not pa assert.Assert(c, strings.Contains(result.Combined(), "Error: This node is
rt of a swarm") not part of a swarm"))
c.Assert(result.Combined(), checker.Not(checker.Contains), "Please enter assert.Assert(c, !strings.Contains(result.Combined(), "Please enter unloc
unlock key") k key"))
out, err := d.Cmd("swarm", "init") out, err := d.Cmd("swarm", "init")
assert.NilError(c, err, out) assert.NilError(c, err, out)
// unlocking an unlocked swarm should return an error - it does not even ask for the key // unlocking an unlocked swarm should return an error - it does not even ask for the key
cmd = d.Command("swarm", "unlock") cmd = d.Command("swarm", "unlock")
result = icmd.RunCmd(cmd) result = icmd.RunCmd(cmd)
result.Assert(c, icmd.Expected{ result.Assert(c, icmd.Expected{
ExitCode: 1, ExitCode: 1,
}) })
c.Assert(result.Combined(), checker.Contains, "Error: swarm is not locked assert.Assert(c, strings.Contains(result.Combined(), "Error: swarm is not
") locked"))
c.Assert(result.Combined(), checker.Not(checker.Contains), "Please enter assert.Assert(c, !strings.Contains(result.Combined(), "Please enter unloc
unlock key") k key"))
} }
func (s *DockerSwarmSuite) TestSwarmInitLocked(c *check.C) { func (s *DockerSwarmSuite) TestSwarmInitLocked(c *testing.T) {
d := s.AddDaemon(c, false, false) d := s.AddDaemon(c, false, false)
outs, err := d.Cmd("swarm", "init", "--autolock") outs, err := d.Cmd("swarm", "init", "--autolock")
c.Assert(err, checker.IsNil, check.Commentf("%s", outs)) assert.Assert(c, err == nil, "%s", outs)
unlockKey := getUnlockKey(d, c, outs) unlockKey := getUnlockKey(d, c, outs)
c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateActive) assert.Equal(c, getNodeStatus(c, d), swarm.LocalNodeStateActive)
// It starts off locked // It starts off locked
d.RestartNode(c) d.RestartNode(c)
c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateLocked) assert.Equal(c, getNodeStatus(c, d), swarm.LocalNodeStateLocked)
cmd := d.Command("swarm", "unlock") cmd := d.Command("swarm", "unlock")
cmd.Stdin = bytes.NewBufferString("wrong-secret-key") cmd.Stdin = bytes.NewBufferString("wrong-secret-key")
icmd.RunCmd(cmd).Assert(c, icmd.Expected{ icmd.RunCmd(cmd).Assert(c, icmd.Expected{
ExitCode: 1, ExitCode: 1,
Err: "invalid key", Err: "invalid key",
}) })
c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateLocked) assert.Equal(c, getNodeStatus(c, d), swarm.LocalNodeStateLocked)
cmd = d.Command("swarm", "unlock") cmd = d.Command("swarm", "unlock")
cmd.Stdin = bytes.NewBufferString(unlockKey) cmd.Stdin = bytes.NewBufferString(unlockKey)
icmd.RunCmd(cmd).Assert(c, icmd.Success) icmd.RunCmd(cmd).Assert(c, icmd.Success)
c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateActive) assert.Equal(c, getNodeStatus(c, d), swarm.LocalNodeStateActive)
outs, err = d.Cmd("node", "ls") outs, err = d.Cmd("node", "ls")
c.Assert(err, checker.IsNil, check.Commentf("%s", outs)) assert.Assert(c, err == nil, "%s", outs)
c.Assert(outs, checker.Not(checker.Contains), "Swarm is encrypted and nee assert.Assert(c, !strings.Contains(outs, "Swarm is encrypted and needs to
ds to be unlocked") be unlocked"))
outs, err = d.Cmd("swarm", "update", "--autolock=false") outs, err = d.Cmd("swarm", "update", "--autolock=false")
c.Assert(err, checker.IsNil, check.Commentf("%s", outs)) assert.Assert(c, err == nil, "%s", outs)
checkSwarmLockedToUnlocked(c, d) checkSwarmLockedToUnlocked(c, d)
outs, err = d.Cmd("node", "ls") outs, err = d.Cmd("node", "ls")
c.Assert(err, checker.IsNil, check.Commentf("%s", outs)) assert.Assert(c, err == nil, "%s", outs)
c.Assert(outs, checker.Not(checker.Contains), "Swarm is encrypted and nee assert.Assert(c, !strings.Contains(outs, "Swarm is encrypted and needs to
ds to be unlocked") be unlocked"))
} }
func (s *DockerSwarmSuite) TestSwarmLeaveLocked(c *check.C) { func (s *DockerSwarmSuite) TestSwarmLeaveLocked(c *testing.T) {
d := s.AddDaemon(c, false, false) d := s.AddDaemon(c, false, false)
outs, err := d.Cmd("swarm", "init", "--autolock") outs, err := d.Cmd("swarm", "init", "--autolock")
c.Assert(err, checker.IsNil, check.Commentf("%s", outs)) assert.Assert(c, err == nil, "%s", outs)
// It starts off locked // It starts off locked
d.RestartNode(c) d.RestartNode(c)
info := d.SwarmInfo(c) info := d.SwarmInfo(c)
assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateLocked) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateLocked)
outs, _ = d.Cmd("node", "ls") outs, _ = d.Cmd("node", "ls")
c.Assert(outs, checker.Contains, "Swarm is encrypted and needs to be unlo assert.Assert(c, strings.Contains(outs, "Swarm is encrypted and needs to
cked") be unlocked"))
// `docker swarm leave` a locked swarm without --force will return an err or // `docker swarm leave` a locked swarm without --force will return an err or
outs, _ = d.Cmd("swarm", "leave") outs, _ = d.Cmd("swarm", "leave")
c.Assert(outs, checker.Contains, "Swarm is encrypted and locked.") assert.Assert(c, strings.Contains(outs, "Swarm is encrypted and locked.")
)
// It is OK for user to leave a locked swarm with --force // It is OK for user to leave a locked swarm with --force
outs, err = d.Cmd("swarm", "leave", "--force") outs, err = d.Cmd("swarm", "leave", "--force")
c.Assert(err, checker.IsNil, check.Commentf("%s", outs)) assert.Assert(c, err == nil, "%s", outs)
info = d.SwarmInfo(c) info = d.SwarmInfo(c)
assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateInactive) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateInactive)
outs, err = d.Cmd("swarm", "init") outs, err = d.Cmd("swarm", "init")
c.Assert(err, checker.IsNil, check.Commentf("%s", outs)) assert.Assert(c, err == nil, "%s", outs)
info = d.SwarmInfo(c) info = d.SwarmInfo(c)
assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateActive) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateActive)
} }
func (s *DockerSwarmSuite) TestSwarmLockUnlockCluster(c *check.C) { func (s *DockerSwarmSuite) TestSwarmLockUnlockCluster(c *testing.T) {
d1 := s.AddDaemon(c, true, true) d1 := s.AddDaemon(c, true, true)
d2 := s.AddDaemon(c, true, true) d2 := s.AddDaemon(c, true, true)
d3 := s.AddDaemon(c, true, true) d3 := s.AddDaemon(c, true, true)
// they start off unlocked // they start off unlocked
d2.RestartNode(c) d2.RestartNode(c)
c.Assert(getNodeStatus(c, d2), checker.Equals, swarm.LocalNodeStateActive ) assert.Equal(c, getNodeStatus(c, d2), swarm.LocalNodeStateActive)
// stop this one so it does not get autolock info // stop this one so it does not get autolock info
d2.Stop(c) d2.Stop(c)
// enable autolock // enable autolock
outs, err := d1.Cmd("swarm", "update", "--autolock") outs, err := d1.Cmd("swarm", "update", "--autolock")
c.Assert(err, checker.IsNil, check.Commentf("%s", outs)) assert.Assert(c, err == nil, "%s", outs)
unlockKey := getUnlockKey(d1, c, outs) unlockKey := getUnlockKey(d1, c, outs)
// 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.Daemon{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")
cmd.Stdin = bytes.NewBufferString(unlockKey) cmd.Stdin = bytes.NewBufferString(unlockKey)
icmd.RunCmd(cmd).Assert(c, icmd.Success) icmd.RunCmd(cmd).Assert(c, icmd.Success)
c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStat eActive) assert.Equal(c, getNodeStatus(c, d), swarm.LocalNodeStateActive)
} }
// d2 never got the cluster update, so it is still set to unlocked // d2 never got the cluster update, so it is still set to unlocked
d2.StartNode(c) d2.StartNode(c)
c.Assert(getNodeStatus(c, d2), checker.Equals, swarm.LocalNodeStateActive ) assert.Equal(c, getNodeStatus(c, d2), swarm.LocalNodeStateActive)
// d2 is now set to lock // d2 is now set to lock
checkSwarmUnlockedToLocked(c, d2) checkSwarmUnlockedToLocked(c, d2)
// leave it locked, and set the cluster to no longer autolock // leave it locked, and set the cluster to no longer autolock
outs, err = d1.Cmd("swarm", "update", "--autolock=false") outs, err = d1.Cmd("swarm", "update", "--autolock=false")
c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs)) assert.Assert(c, err == nil, "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.Daemon{d1, d3} { for _, d := range []*daemon.Daemon{d1, d3} {
checkSwarmLockedToUnlocked(c, d) checkSwarmLockedToUnlocked(c, d)
} }
// d2 still locked // d2 still locked
c.Assert(getNodeStatus(c, d2), checker.Equals, swarm.LocalNodeStateLocked ) assert.Equal(c, getNodeStatus(c, d2), swarm.LocalNodeStateLocked)
// unlock it // unlock it
cmd := d2.Command("swarm", "unlock") cmd := d2.Command("swarm", "unlock")
cmd.Stdin = bytes.NewBufferString(unlockKey) cmd.Stdin = bytes.NewBufferString(unlockKey)
icmd.RunCmd(cmd).Assert(c, icmd.Success) icmd.RunCmd(cmd).Assert(c, icmd.Success)
c.Assert(getNodeStatus(c, d2), checker.Equals, swarm.LocalNodeStateActive ) assert.Equal(c, getNodeStatus(c, d2), swarm.LocalNodeStateActive)
// once it's caught up, d2 is set to not be locked // once it's caught up, d2 is set to not be locked
checkSwarmLockedToUnlocked(c, d2) checkSwarmLockedToUnlocked(c, d2)
// managers who join now are never set to locked in the first place // managers who join now are never set to locked in the first place
d4 := s.AddDaemon(c, true, true) d4 := s.AddDaemon(c, true, true)
d4.RestartNode(c) d4.RestartNode(c)
c.Assert(getNodeStatus(c, d4), checker.Equals, swarm.LocalNodeStateActive ) assert.Equal(c, getNodeStatus(c, d4), swarm.LocalNodeStateActive)
} }
func (s *DockerSwarmSuite) TestSwarmJoinPromoteLocked(c *check.C) { func (s *DockerSwarmSuite) TestSwarmJoinPromoteLocked(c *testing.T) {
d1 := s.AddDaemon(c, true, true) d1 := s.AddDaemon(c, true, true)
// enable autolock // enable autolock
outs, err := d1.Cmd("swarm", "update", "--autolock") outs, err := d1.Cmd("swarm", "update", "--autolock")
c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs)) assert.Assert(c, err == nil, "out: %v", outs)
unlockKey := getUnlockKey(d1, c, outs) unlockKey := getUnlockKey(d1, c, outs)
// joined workers start off unlocked // joined workers start off unlocked
d2 := s.AddDaemon(c, true, false) d2 := s.AddDaemon(c, true, false)
d2.RestartNode(c) d2.RestartNode(c)
waitAndAssert(c, time.Second, d2.CheckLocalNodeState, checker.Equals, swa rm.LocalNodeStateActive) poll.WaitOn(c, pollCheck(c, d2.CheckLocalNodeState, checker.Equals(swarm. LocalNodeStateActive)), poll.WithTimeout(time.Second))
// promote worker // promote worker
outs, err = d1.Cmd("node", "promote", d2.NodeID()) outs, err = d1.Cmd("node", "promote", d2.NodeID())
assert.NilError(c, err) assert.NilError(c, err)
c.Assert(outs, checker.Contains, "promoted to a manager in the swarm") assert.Assert(c, strings.Contains(outs, "promoted to a manager in the swa
rm"))
// join new manager node // join new manager node
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.Daemon{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")
cmd.Stdin = bytes.NewBufferString(unlockKey) cmd.Stdin = bytes.NewBufferString(unlockKey)
icmd.RunCmd(cmd).Assert(c, icmd.Success) icmd.RunCmd(cmd).Assert(c, icmd.Success)
c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStat eActive) assert.Equal(c, getNodeStatus(c, d), swarm.LocalNodeStateActive)
} }
// 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.NodeID()) outs, err = d1.Cmd("node", "demote", d3.NodeID())
assert.NilError(c, err) assert.NilError(c, err)
c.Assert(outs, checker.Contains, "demoted in the swarm") assert.Assert(c, strings.Contains(outs, "demoted in the swarm"))
// Wait for it to actually be demoted, for the key and cert to be replace d. // Wait for it to actually be demoted, for the key and cert to be replace d.
// Then restart and assert that the node is not locked. If we don't wait for the cert // Then restart and assert that the node is not locked. If we don't wait for the cert
// to be replaced, then the node still has the manager TLS key which is s till locked // to be replaced, then the node still has the manager TLS key which is s till locked
// (because we never want a manager TLS key to be on disk unencrypted if the cluster // (because we never want a manager TLS key to be on disk unencrypted if the cluster
// is set to autolock) // is set to autolock)
waitAndAssert(c, defaultReconciliationTimeout, d3.CheckControlAvailable, poll.WaitOn(c, pollCheck(c, d3.CheckControlAvailable, checker.False()), p
checker.False) oll.WithTimeout(defaultReconciliationTimeout))
waitAndAssert(c, defaultReconciliationTimeout, func(c *check.C) (interfac poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
e{}, check.CommentInterface) {
certBytes, err := ioutil.ReadFile(filepath.Join(d3.Folder, "root" , "swarm", "certificates", "swarm-node.crt")) certBytes, err := ioutil.ReadFile(filepath.Join(d3.Folder, "root" , "swarm", "certificates", "swarm-node.crt"))
if err != nil { if err != nil {
return "", check.Commentf("error: %v", err) return "", fmt.Sprintf("error: %v", err)
} }
certs, err := helpers.ParseCertificatesPEM(certBytes) certs, err := helpers.ParseCertificatesPEM(certBytes)
if err == nil && len(certs) > 0 && len(certs[0].Subject.Organizat ionalUnit) > 0 { if err == nil && len(certs) > 0 && len(certs[0].Subject.Organizat ionalUnit) > 0 {
return certs[0].Subject.OrganizationalUnit[0], nil return certs[0].Subject.OrganizationalUnit[0], ""
} }
return "", check.Commentf("could not get organizational unit from return "", "could not get organizational unit from certificate"
certificate") }, checker.Equals("swarm-worker")), poll.WithTimeout(defaultReconciliatio
}, checker.Equals, "swarm-worker") nTimeout))
// by now, it should *never* be locked on restart // by now, it should *never* be locked on restart
d3.RestartNode(c) d3.RestartNode(c)
waitAndAssert(c, time.Second, d3.CheckLocalNodeState, checker.Equals, swa rm.LocalNodeStateActive) poll.WaitOn(c, pollCheck(c, d3.CheckLocalNodeState, checker.Equals(swarm. LocalNodeStateActive)), poll.WithTimeout(time.Second))
} }
func (s *DockerSwarmSuite) TestSwarmRotateUnlockKey(c *check.C) { func (s *DockerSwarmSuite) TestSwarmRotateUnlockKey(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
outs, err := d.Cmd("swarm", "update", "--autolock") outs, err := d.Cmd("swarm", "update", "--autolock")
c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs)) assert.Assert(c, err == nil, "out: %v", outs)
unlockKey := getUnlockKey(d, c, outs) unlockKey := getUnlockKey(d, c, outs)
// Rotate multiple times // Rotate multiple times
for i := 0; i != 3; i++ { for i := 0; i != 3; i++ {
outs, err = d.Cmd("swarm", "unlock-key", "-q", "--rotate") outs, err = d.Cmd("swarm", "unlock-key", "-q", "--rotate")
c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs)) assert.Assert(c, err == nil, "out: %v", outs)
// Strip \n // Strip \n
newUnlockKey := outs[:len(outs)-1] newUnlockKey := outs[:len(outs)-1]
c.Assert(newUnlockKey, checker.Not(checker.Equals), "") assert.Assert(c, newUnlockKey != "")
c.Assert(newUnlockKey, checker.Not(checker.Equals), unlockKey) assert.Assert(c, newUnlockKey != unlockKey)
d.RestartNode(c) d.RestartNode(c)
c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStat eLocked) assert.Equal(c, getNodeStatus(c, d), swarm.LocalNodeStateLocked)
outs, _ = d.Cmd("node", "ls") outs, _ = d.Cmd("node", "ls")
c.Assert(outs, checker.Contains, "Swarm is encrypted and needs to assert.Assert(c, strings.Contains(outs, "Swarm is encrypted and n
be unlocked") eeds to be unlocked"))
cmd := d.Command("swarm", "unlock") cmd := d.Command("swarm", "unlock")
cmd.Stdin = bytes.NewBufferString(unlockKey) cmd.Stdin = bytes.NewBufferString(unlockKey)
result := icmd.RunCmd(cmd) result := icmd.RunCmd(cmd)
if result.Error == nil { if result.Error == nil {
// On occasion, the daemon may not have finished // On occasion, the daemon may not have finished
// rotating the KEK before restarting. The test is // rotating the KEK before restarting. The test is
// intentionally written to explore this behavior. // intentionally written to explore this behavior.
// When this happens, unlocking with the old key will // When this happens, unlocking with the old key will
// succeed. If we wait for the rotation to happen and // succeed. If we wait for the rotation to happen and
skipping to change at line 1298 skipping to change at line 1280
cmd = d.Command("swarm", "unlock") cmd = d.Command("swarm", "unlock")
cmd.Stdin = bytes.NewBufferString(unlockKey) cmd.Stdin = bytes.NewBufferString(unlockKey)
result = icmd.RunCmd(cmd) result = icmd.RunCmd(cmd)
} }
result.Assert(c, icmd.Expected{ result.Assert(c, icmd.Expected{
ExitCode: 1, ExitCode: 1,
Err: "invalid key", Err: "invalid key",
}) })
outs, _ = d.Cmd("node", "ls") outs, _ = d.Cmd("node", "ls")
c.Assert(outs, checker.Contains, "Swarm is encrypted and needs to assert.Assert(c, strings.Contains(outs, "Swarm is encrypted and n
be unlocked") eeds to be unlocked"))
cmd = d.Command("swarm", "unlock") cmd = d.Command("swarm", "unlock")
cmd.Stdin = bytes.NewBufferString(newUnlockKey) cmd.Stdin = bytes.NewBufferString(newUnlockKey)
icmd.RunCmd(cmd).Assert(c, icmd.Success) icmd.RunCmd(cmd).Assert(c, icmd.Success)
c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStat eActive) assert.Equal(c, getNodeStatus(c, d), swarm.LocalNodeStateActive)
outs, err = d.Cmd("node", "ls") retry := 0
assert.NilError(c, err) for {
c.Assert(outs, checker.Not(checker.Contains), "Swarm is encrypted // an issue sometimes prevents leader to be available rig
and needs to be unlocked") ht away
outs, err = d.Cmd("node", "ls")
if err != nil && retry < 5 {
if strings.Contains(outs, "swarm does not have a
leader") {
retry++
time.Sleep(3 * time.Second)
continue
}
}
assert.NilError(c, err)
assert.Assert(c, !strings.Contains(outs, "Swarm is encryp
ted and needs to be unlocked"))
break
}
unlockKey = newUnlockKey unlockKey = newUnlockKey
} }
} }
// This differs from `TestSwarmRotateUnlockKey` because that one rotates a singl e node, which is the leader. // This differs from `TestSwarmRotateUnlockKey` because that one rotates a singl e node, which is the leader.
// This one keeps the leader up, and asserts that other manager nodes in the clu ster also have their unlock // This one keeps the leader up, and asserts that other manager nodes in the clu ster also have their unlock
// key rotated. // key rotated.
func (s *DockerSwarmSuite) TestSwarmClusterRotateUnlockKey(c *check.C) { func (s *DockerSwarmSuite) TestSwarmClusterRotateUnlockKey(c *testing.T) {
if runtime.GOARCH == "s390x" { if runtime.GOARCH == "s390x" {
c.Skip("Disabled on s390x") c.Skip("Disabled on s390x")
} }
if runtime.GOARCH == "ppc64le" { if runtime.GOARCH == "ppc64le" {
c.Skip("Disabled on ppc64le") c.Skip("Disabled on ppc64le")
} }
d1 := s.AddDaemon(c, true, true) // leader - don't restart this one, we d on't want leader election delays d1 := s.AddDaemon(c, true, true) // leader - don't restart this one, we d on't want leader election delays
d2 := s.AddDaemon(c, true, true) d2 := s.AddDaemon(c, true, true)
d3 := s.AddDaemon(c, true, true) d3 := s.AddDaemon(c, true, true)
outs, err := d1.Cmd("swarm", "update", "--autolock") outs, err := d1.Cmd("swarm", "update", "--autolock")
c.Assert(err, checker.IsNil, check.Commentf("%s", outs)) assert.Assert(c, err == nil, "%s", outs)
unlockKey := getUnlockKey(d1, c, outs) unlockKey := getUnlockKey(d1, c, outs)
// Rotate multiple times // Rotate multiple times
for i := 0; i != 3; i++ { for i := 0; i != 3; i++ {
outs, err = d1.Cmd("swarm", "unlock-key", "-q", "--rotate") outs, err = d1.Cmd("swarm", "unlock-key", "-q", "--rotate")
c.Assert(err, checker.IsNil, check.Commentf("%s", outs)) assert.Assert(c, err == nil, "%s", outs)
// Strip \n // Strip \n
newUnlockKey := outs[:len(outs)-1] newUnlockKey := outs[:len(outs)-1]
c.Assert(newUnlockKey, checker.Not(checker.Equals), "") assert.Assert(c, newUnlockKey != "")
c.Assert(newUnlockKey, checker.Not(checker.Equals), unlockKey) assert.Assert(c, newUnlockKey != unlockKey)
d2.RestartNode(c) d2.RestartNode(c)
d3.RestartNode(c) d3.RestartNode(c)
for _, d := range []*daemon.Daemon{d2, d3} { for _, d := range []*daemon.Daemon{d2, d3} {
c.Assert(getNodeStatus(c, d), checker.Equals, swarm.Local NodeStateLocked) assert.Equal(c, getNodeStatus(c, d), swarm.LocalNodeState Locked)
outs, _ := d.Cmd("node", "ls") outs, _ := d.Cmd("node", "ls")
c.Assert(outs, checker.Contains, "Swarm is encrypted and assert.Assert(c, strings.Contains(outs, "Swarm is encrypt
needs to be unlocked") ed and needs to be unlocked"))
cmd := d.Command("swarm", "unlock") cmd := d.Command("swarm", "unlock")
cmd.Stdin = bytes.NewBufferString(unlockKey) cmd.Stdin = bytes.NewBufferString(unlockKey)
result := icmd.RunCmd(cmd) result := icmd.RunCmd(cmd)
if result.Error == nil { if result.Error == nil {
// On occasion, the daemon may not have finished // On occasion, the daemon may not have finished
// rotating the KEK before restarting. The test i s // rotating the KEK before restarting. The test i s
// intentionally written to explore this behavior . // intentionally written to explore this behavior .
// When this happens, unlocking with the old key will // When this happens, unlocking with the old key will
// succeed. If we wait for the rotation to happen and // succeed. If we wait for the rotation to happen and
skipping to change at line 1378 skipping to change at line 1370
cmd = d.Command("swarm", "unlock") cmd = d.Command("swarm", "unlock")
cmd.Stdin = bytes.NewBufferString(unlockKey) cmd.Stdin = bytes.NewBufferString(unlockKey)
result = icmd.RunCmd(cmd) result = icmd.RunCmd(cmd)
} }
result.Assert(c, icmd.Expected{ result.Assert(c, icmd.Expected{
ExitCode: 1, ExitCode: 1,
Err: "invalid key", Err: "invalid key",
}) })
outs, _ = d.Cmd("node", "ls") outs, _ = d.Cmd("node", "ls")
c.Assert(outs, checker.Contains, "Swarm is encrypted and assert.Assert(c, strings.Contains(outs, "Swarm is encrypt
needs to be unlocked") ed and needs to be unlocked"))
cmd = d.Command("swarm", "unlock") cmd = d.Command("swarm", "unlock")
cmd.Stdin = bytes.NewBufferString(newUnlockKey) cmd.Stdin = bytes.NewBufferString(newUnlockKey)
icmd.RunCmd(cmd).Assert(c, icmd.Success) icmd.RunCmd(cmd).Assert(c, icmd.Success)
c.Assert(getNodeStatus(c, d), checker.Equals, swarm.Local NodeStateActive) assert.Equal(c, getNodeStatus(c, d), swarm.LocalNodeState Active)
outs, err = d.Cmd("node", "ls") retry := 0
c.Assert(err, checker.IsNil, check.Commentf("%s", outs)) for {
c.Assert(outs, checker.Not(checker.Contains), "Swarm is e // an issue sometimes prevents leader to be avail
ncrypted and needs to be unlocked") able right away
outs, err = d.Cmd("node", "ls")
if err != nil && retry < 5 {
if strings.Contains(outs, "swarm does not
have a leader") {
retry++
time.Sleep(3 * time.Second)
continue
}
}
assert.Assert(c, err == nil, "%s", outs)
assert.Assert(c, !strings.Contains(outs, "Swarm i
s encrypted and needs to be unlocked"))
break
}
} }
unlockKey = newUnlockKey unlockKey = newUnlockKey
} }
} }
func (s *DockerSwarmSuite) TestSwarmAlternateLockUnlock(c *check.C) { func (s *DockerSwarmSuite) TestSwarmAlternateLockUnlock(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
for i := 0; i < 2; i++ { for i := 0; i < 2; i++ {
// set to lock // set to lock
outs, err := d.Cmd("swarm", "update", "--autolock") outs, err := d.Cmd("swarm", "update", "--autolock")
c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs)) assert.Assert(c, err == nil, "out: %v", outs)
c.Assert(outs, checker.Contains, "docker swarm unlock") assert.Assert(c, strings.Contains(outs, "docker swarm unlock"))
unlockKey := getUnlockKey(d, c, outs) unlockKey := getUnlockKey(d, c, outs)
checkSwarmUnlockedToLocked(c, d) checkSwarmUnlockedToLocked(c, d)
cmd := d.Command("swarm", "unlock") cmd := d.Command("swarm", "unlock")
cmd.Stdin = bytes.NewBufferString(unlockKey) cmd.Stdin = bytes.NewBufferString(unlockKey)
icmd.RunCmd(cmd).Assert(c, icmd.Success) icmd.RunCmd(cmd).Assert(c, icmd.Success)
c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStat eActive) assert.Equal(c, getNodeStatus(c, d), swarm.LocalNodeStateActive)
outs, err = d.Cmd("swarm", "update", "--autolock=false") outs, err = d.Cmd("swarm", "update", "--autolock=false")
c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs)) assert.Assert(c, err == nil, "out: %v", outs)
checkSwarmLockedToUnlocked(c, d) checkSwarmLockedToUnlocked(c, d)
} }
} }
func (s *DockerSwarmSuite) TestExtraHosts(c *check.C) { func (s *DockerSwarmSuite) TestExtraHosts(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
// Create a service // Create a service
name := "top" name := "top"
out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "--host=example.com:1.2.3.4", "busybox", "top") out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "--host=example.com:1.2.3.4", "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
// Make sure task has been deployed. // Make sure task has been deployed.
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCoun t, checker.Equals, 1) poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1 )), poll.WithTimeout(defaultReconciliationTimeout))
// We need to get the container id. // We need to get the container id.
out, err = d.Cmd("ps", "-a", "-q", "--no-trunc") out, err = d.Cmd("ps", "-a", "-q", "--no-trunc")
assert.NilError(c, err, out) assert.NilError(c, err, out)
id := strings.TrimSpace(out) id := strings.TrimSpace(out)
// Compare against expected output. // Compare against expected output.
expectedOutput := "1.2.3.4\texample.com" expectedOutput := "1.2.3.4\texample.com"
out, err = d.Cmd("exec", id, "cat", "/etc/hosts") out, err = d.Cmd("exec", id, "cat", "/etc/hosts")
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(out, checker.Contains, expectedOutput, check.Commentf("Expected '%s', but got %q", expectedOutput, out)) assert.Assert(c, strings.Contains(out, expectedOutput), "Expected '%s', b ut got %q", expectedOutput, out)
} }
func (s *DockerSwarmSuite) TestSwarmManagerAddress(c *check.C) { func (s *DockerSwarmSuite) TestSwarmManagerAddress(c *testing.T) {
d1 := s.AddDaemon(c, true, true) d1 := s.AddDaemon(c, true, true)
d2 := s.AddDaemon(c, true, false) d2 := s.AddDaemon(c, true, false)
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. SwarmPort) expectedOutput := fmt.Sprintf("Manager Addresses:\n 127.0.0.1:%d\n", d1. SwarmPort)
out, err := d1.Cmd("info") out, err := d1.Cmd("info")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Assert(c, strings.Contains(out, expectedOutput)) assert.Assert(c, strings.Contains(out, expectedOutput))
out, err = d2.Cmd("info") out, err = d2.Cmd("info")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Assert(c, strings.Contains(out, expectedOutput)) assert.Assert(c, strings.Contains(out, expectedOutput))
out, err = d3.Cmd("info") out, err = d3.Cmd("info")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Assert(c, strings.Contains(out, expectedOutput)) assert.Assert(c, strings.Contains(out, expectedOutput))
} }
func (s *DockerSwarmSuite) TestSwarmNetworkIPAMOptions(c *check.C) { func (s *DockerSwarmSuite) TestSwarmNetworkIPAMOptions(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
out, err := d.Cmd("network", "create", "-d", "overlay", "--ipam-opt", "fo o=bar", "foo") out, err := d.Cmd("network", "create", "-d", "overlay", "--ipam-opt", "fo o=bar", "foo")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
out, err = d.Cmd("network", "inspect", "--format", "{{.IPAM.Options}}", " foo") out, err = d.Cmd("network", "inspect", "--format", "{{.IPAM.Options}}", " foo")
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(strings.TrimSpace(out), checker.Contains, "foo:bar") assert.Assert(c, strings.Contains(strings.TrimSpace(out), "foo:bar"))
c.Assert(strings.TrimSpace(out), checker.Contains, "com.docker.network.ip assert.Assert(c, strings.Contains(strings.TrimSpace(out), "com.docker.net
am.serial:true") work.ipam.serial:true"))
out, err = d.Cmd("service", "create", "--detach", "--no-resolve-image", " --network=foo", "--name", "top", "busybox", "top") out, err = d.Cmd("service", "create", "--detach", "--no-resolve-image", " --network=foo", "--name", "top", "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
// make sure task has been deployed. // make sure task has been deployed.
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCoun t, checker.Equals, 1) poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1 )), poll.WithTimeout(defaultReconciliationTimeout))
out, err = d.Cmd("network", "inspect", "--format", "{{.IPAM.Options}}", " foo") out, err = d.Cmd("network", "inspect", "--format", "{{.IPAM.Options}}", " foo")
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(strings.TrimSpace(out), checker.Contains, "foo:bar") assert.Assert(c, strings.Contains(strings.TrimSpace(out), "foo:bar"))
c.Assert(strings.TrimSpace(out), checker.Contains, "com.docker.network.ip assert.Assert(c, strings.Contains(strings.TrimSpace(out), "com.docker.net
am.serial:true") work.ipam.serial:true"))
} }
// Test case for issue #27866, which did not allow NW name that is the prefix of a swarm NW ID. // Test case for issue #27866, which did not allow NW name that is the prefix of a swarm NW ID.
// e.g. if the ingress ID starts with "n1", it was impossible to create a NW nam ed "n1". // e.g. if the ingress ID starts with "n1", it was impossible to create a NW nam ed "n1".
func (s *DockerSwarmSuite) TestSwarmNetworkCreateIssue27866(c *check.C) { func (s *DockerSwarmSuite) TestSwarmNetworkCreateIssue27866(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
out, err := d.Cmd("network", "inspect", "-f", "{{.Id}}", "ingress") out, err := d.Cmd("network", "inspect", "-f", "{{.Id}}", "ingress")
assert.NilError(c, err, "out: %v", out) assert.NilError(c, err, "out: %v", out)
ingressID := strings.TrimSpace(out) ingressID := strings.TrimSpace(out)
c.Assert(ingressID, checker.Not(checker.Equals), "") assert.Assert(c, ingressID != "")
// create a network of which name is the prefix of the ID of an overlay n etwork // create a network of which name is the prefix of the ID of an overlay n etwork
// (ingressID in this case) // (ingressID in this case)
newNetName := ingressID[0:2] newNetName := ingressID[0:2]
out, err = d.Cmd("network", "create", "--driver", "overlay", newNetName) out, err = d.Cmd("network", "create", "--driver", "overlay", newNetName)
// In #27866, it was failing because of "network with name %s already exi sts" // In #27866, it was failing because of "network with name %s already exi sts"
assert.NilError(c, err, "out: %v", out) assert.NilError(c, err, "out: %v", out)
out, err = d.Cmd("network", "rm", newNetName) out, err = d.Cmd("network", "rm", newNetName)
assert.NilError(c, err, "out: %v", out) assert.NilError(c, err, "out: %v", out)
} }
// Test case for https://github.com/docker/docker/pull/27938#issuecomment-265768 303 // Test case for https://github.com/docker/docker/pull/27938#issuecomment-265768 303
// This test creates two networks with the same name sequentially, with various drivers. // This test creates two networks with the same name sequentially, with various drivers.
// Since the operations in this test are done sequentially, the 2nd call should fail with // Since the operations in this test are done sequentially, the 2nd call should fail with
// "network with name FOO already exists". // "network with name FOO already exists".
// Note that it is to ok have multiple networks with the same name if the operat ions are done // Note that it is to ok have multiple networks with the same name if the operat ions are done
// in parallel. (#18864) // in parallel. (#18864)
func (s *DockerSwarmSuite) TestSwarmNetworkCreateDup(c *check.C) { func (s *DockerSwarmSuite) TestSwarmNetworkCreateDup(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
drivers := []string{"bridge", "overlay"} drivers := []string{"bridge", "overlay"}
for i, driver1 := range drivers { for i, driver1 := range drivers {
nwName := fmt.Sprintf("network-test-%d", i) nwName := fmt.Sprintf("network-test-%d", i)
for _, driver2 := range drivers { for _, driver2 := range drivers {
c.Logf("Creating a network named %q with %q, then %q", c.Logf("Creating a network named %q with %q, then %q",
nwName, driver1, driver2) nwName, driver1, driver2)
out, err := d.Cmd("network", "create", "--driver", driver 1, nwName) out, err := d.Cmd("network", "create", "--driver", driver 1, nwName)
assert.NilError(c, err, "out: %v", out) assert.NilError(c, err, "out: %v", out)
out, err = d.Cmd("network", "create", "--driver", driver2 , nwName) out, err = d.Cmd("network", "create", "--driver", driver2 , nwName)
c.Assert(out, checker.Contains, assert.Assert(c, strings.Contains(out, fmt.Sprintf("netwo
fmt.Sprintf("network with name %s already exists" rk with name %s already exists", nwName)))
, nwName))
assert.ErrorContains(c, err, "") assert.ErrorContains(c, err, "")
c.Logf("As expected, the attempt to network %q with %q fa iled: %s", c.Logf("As expected, the attempt to network %q with %q fa iled: %s",
nwName, driver2, out) nwName, driver2, out)
out, err = d.Cmd("network", "rm", nwName) out, err = d.Cmd("network", "rm", nwName)
assert.NilError(c, err, "out: %v", out) assert.NilError(c, err, "out: %v", out)
} }
} }
} }
func (s *DockerSwarmSuite) TestSwarmPublishDuplicatePorts(c *check.C) { func (s *DockerSwarmSuite) TestSwarmPublishDuplicatePorts(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
out, err := d.Cmd("service", "create", "--no-resolve-image", "--detach=tr ue", "--publish", "5005:80", "--publish", "5006:80", "--publish", "80", "--publi sh", "80", "busybox", "top") out, err := d.Cmd("service", "create", "--no-resolve-image", "--detach=tr ue", "--publish", "5005:80", "--publish", "5006:80", "--publish", "80", "--publi sh", "80", "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
id := strings.TrimSpace(out) id := strings.TrimSpace(out)
// make sure task has been deployed. // make sure task has been deployed.
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCoun t, checker.Equals, 1) poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1 )), poll.WithTimeout(defaultReconciliationTimeout))
// Total len = 4, with 2 dynamic ports and 2 non-dynamic ports // Total len = 4, with 2 dynamic ports and 2 non-dynamic ports
// Dynamic ports are likely to be 30000 and 30001 but doesn't matter // Dynamic ports are likely to be 30000 and 30001 but doesn't matter
out, err = d.Cmd("service", "inspect", "--format", "{{.Endpoint.Ports}} l en={{len .Endpoint.Ports}}", id) out, err = d.Cmd("service", "inspect", "--format", "{{.Endpoint.Ports}} l en={{len .Endpoint.Ports}}", id)
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(out, checker.Contains, "len=4") assert.Assert(c, strings.Contains(out, "len=4"))
c.Assert(out, checker.Contains, "{ tcp 80 5005 ingress}") assert.Assert(c, strings.Contains(out, "{ tcp 80 5005 ingress}"))
c.Assert(out, checker.Contains, "{ tcp 80 5006 ingress}") assert.Assert(c, strings.Contains(out, "{ tcp 80 5006 ingress}"))
} }
func (s *DockerSwarmSuite) TestSwarmJoinWithDrain(c *check.C) { func (s *DockerSwarmSuite) TestSwarmJoinWithDrain(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
out, err := d.Cmd("node", "ls") out, err := d.Cmd("node", "ls")
assert.NilError(c, err) assert.NilError(c, err)
c.Assert(out, checker.Not(checker.Contains), "Drain") assert.Assert(c, !strings.Contains(out, "Drain"))
out, err = d.Cmd("swarm", "join-token", "-q", "manager") out, err = d.Cmd("swarm", "join-token", "-q", "manager")
assert.NilError(c, err) assert.NilError(c, err)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
token := strings.TrimSpace(out) token := strings.TrimSpace(out)
d1 := s.AddDaemon(c, false, false) d1 := s.AddDaemon(c, false, false)
out, err = d1.Cmd("swarm", "join", "--availability=drain", "--token", tok en, d.SwarmListenAddr()) out, err = d1.Cmd("swarm", "join", "--availability=drain", "--token", tok en, d.SwarmListenAddr())
assert.NilError(c, err) assert.NilError(c, err)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
out, err = d.Cmd("node", "ls") out, err = d.Cmd("node", "ls")
assert.NilError(c, err) assert.NilError(c, err)
c.Assert(out, checker.Contains, "Drain") assert.Assert(c, strings.Contains(out, "Drain"))
out, err = d1.Cmd("node", "ls") out, err = d1.Cmd("node", "ls")
assert.NilError(c, err) assert.NilError(c, err)
c.Assert(out, checker.Contains, "Drain") assert.Assert(c, strings.Contains(out, "Drain"))
} }
func (s *DockerSwarmSuite) TestSwarmInitWithDrain(c *check.C) { func (s *DockerSwarmSuite) TestSwarmInitWithDrain(c *testing.T) {
d := s.AddDaemon(c, false, false) d := s.AddDaemon(c, false, false)
out, err := d.Cmd("swarm", "init", "--availability", "drain") out, err := d.Cmd("swarm", "init", "--availability", "drain")
assert.NilError(c, err, "out: %v", out) assert.NilError(c, err, "out: %v", out)
out, err = d.Cmd("node", "ls") out, err = d.Cmd("node", "ls")
assert.NilError(c, err) assert.NilError(c, err)
c.Assert(out, checker.Contains, "Drain") assert.Assert(c, strings.Contains(out, "Drain"))
} }
func (s *DockerSwarmSuite) TestSwarmReadonlyRootfs(c *check.C) { func (s *DockerSwarmSuite) TestSwarmReadonlyRootfs(c *testing.T) {
testRequires(c, DaemonIsLinux, UserNamespaceROMount) testRequires(c, DaemonIsLinux, UserNamespaceROMount)
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", "top", "--read-only", "busybox", "top") out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", "top", "--read-only", "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
// make sure task has been deployed. // make sure task has been deployed.
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCoun t, checker.Equals, 1) poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1 )), poll.WithTimeout(defaultReconciliationTimeout))
out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.TaskTemplate .ContainerSpec.ReadOnly }}", "top") out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.TaskTemplate .ContainerSpec.ReadOnly }}", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Equal(c, strings.TrimSpace(out), "true") assert.Equal(c, strings.TrimSpace(out), "true")
containers := d.ActiveContainers(c) containers := d.ActiveContainers(c)
out, err = d.Cmd("inspect", "--type", "container", "--format", "{{.HostCo nfig.ReadonlyRootfs}}", containers[0]) out, err = d.Cmd("inspect", "--type", "container", "--format", "{{.HostCo nfig.ReadonlyRootfs}}", containers[0])
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Equal(c, strings.TrimSpace(out), "true") assert.Equal(c, strings.TrimSpace(out), "true")
} }
func (s *DockerSwarmSuite) TestNetworkInspectWithDuplicateNames(c *check.C) { func (s *DockerSwarmSuite) TestNetworkInspectWithDuplicateNames(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
name := "foo" name := "foo"
options := types.NetworkCreate{ options := types.NetworkCreate{
CheckDuplicate: false, CheckDuplicate: false,
Driver: "bridge", Driver: "bridge",
} }
cli := d.NewClientT(c) cli := d.NewClientT(c)
defer cli.Close() defer cli.Close()
skipping to change at line 1653 skipping to change at line 1652
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Equal(c, strings.TrimSpace(out), n1.ID) assert.Equal(c, strings.TrimSpace(out), n1.ID)
out, err = d.Cmd("network", "inspect", "--format", "{{.ID}}", n2.ID) out, err = d.Cmd("network", "inspect", "--format", "{{.ID}}", n2.ID)
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Equal(c, strings.TrimSpace(out), n2.ID) assert.Equal(c, strings.TrimSpace(out), n2.ID)
// Name with duplicates // Name with duplicates
out, err = d.Cmd("network", "inspect", "--format", "{{.ID}}", name) out, err = d.Cmd("network", "inspect", "--format", "{{.ID}}", name)
assert.ErrorContains(c, err, "", out) assert.ErrorContains(c, err, "", out)
c.Assert(out, checker.Contains, "2 matches found based on name") assert.Assert(c, strings.Contains(out, "2 matches found based on name"))
out, err = d.Cmd("network", "rm", n2.ID) out, err = d.Cmd("network", "rm", n2.ID)
assert.NilError(c, err, out) assert.NilError(c, err, out)
// Duplicates with name but with different driver // Duplicates with name but with different driver
options.Driver = "overlay" options.Driver = "overlay"
n2, err = cli.NetworkCreate(context.Background(), name, options) n2, err = cli.NetworkCreate(context.Background(), name, options)
assert.NilError(c, err) assert.NilError(c, err)
// Full ID always works // Full ID always works
skipping to change at line 1676 skipping to change at line 1674
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Equal(c, strings.TrimSpace(out), n1.ID) assert.Equal(c, strings.TrimSpace(out), n1.ID)
out, err = d.Cmd("network", "inspect", "--format", "{{.ID}}", n2.ID) out, err = d.Cmd("network", "inspect", "--format", "{{.ID}}", n2.ID)
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Equal(c, strings.TrimSpace(out), n2.ID) assert.Equal(c, strings.TrimSpace(out), n2.ID)
// Name with duplicates // Name with duplicates
out, err = d.Cmd("network", "inspect", "--format", "{{.ID}}", name) out, err = d.Cmd("network", "inspect", "--format", "{{.ID}}", name)
assert.ErrorContains(c, err, "", out) assert.ErrorContains(c, err, "", out)
c.Assert(out, checker.Contains, "2 matches found based on name") assert.Assert(c, strings.Contains(out, "2 matches found based on name"))
} }
func (s *DockerSwarmSuite) TestSwarmStopSignal(c *check.C) { func (s *DockerSwarmSuite) TestSwarmStopSignal(c *testing.T) {
testRequires(c, DaemonIsLinux, UserNamespaceROMount) testRequires(c, DaemonIsLinux, UserNamespaceROMount)
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", "top", "--stop-signal=SIGHUP", "busybox", "top") out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", "top", "--stop-signal=SIGHUP", "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
// make sure task has been deployed. // make sure task has been deployed.
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCoun t, checker.Equals, 1) poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1 )), poll.WithTimeout(defaultReconciliationTimeout))
out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.TaskTemplate .ContainerSpec.StopSignal }}", "top") out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.TaskTemplate .ContainerSpec.StopSignal }}", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Equal(c, strings.TrimSpace(out), "SIGHUP") assert.Equal(c, strings.TrimSpace(out), "SIGHUP")
containers := d.ActiveContainers(c) containers := d.ActiveContainers(c)
out, err = d.Cmd("inspect", "--type", "container", "--format", "{{.Config .StopSignal}}", containers[0]) out, err = d.Cmd("inspect", "--type", "container", "--format", "{{.Config .StopSignal}}", containers[0])
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Equal(c, strings.TrimSpace(out), "SIGHUP") assert.Equal(c, strings.TrimSpace(out), "SIGHUP")
out, err = d.Cmd("service", "update", "--detach", "--stop-signal=SIGUSR1" , "top") out, err = d.Cmd("service", "update", "--detach", "--stop-signal=SIGUSR1" , "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.TaskTemplate .ContainerSpec.StopSignal }}", "top") out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.TaskTemplate .ContainerSpec.StopSignal }}", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Equal(c, strings.TrimSpace(out), "SIGUSR1") assert.Equal(c, strings.TrimSpace(out), "SIGUSR1")
} }
func (s *DockerSwarmSuite) TestSwarmServiceLsFilterMode(c *check.C) { func (s *DockerSwarmSuite) TestSwarmServiceLsFilterMode(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", "top1", "busybox", "top") out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", "top1", "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
out, err = d.Cmd("service", "create", "--detach", "--no-resolve-image", " --name", "top2", "--mode=global", "busybox", "top") out, err = d.Cmd("service", "create", "--detach", "--no-resolve-image", " --name", "top2", "--mode=global", "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
// make sure task has been deployed. // make sure task has been deployed.
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCoun t, checker.Equals, 2) poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(2 )), poll.WithTimeout(defaultReconciliationTimeout))
out, err = d.Cmd("service", "ls") out, err = d.Cmd("service", "ls")
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(out, checker.Contains, "top1") assert.Assert(c, strings.Contains(out, "top1"))
c.Assert(out, checker.Contains, "top2") assert.Assert(c, strings.Contains(out, "top2"))
c.Assert(out, checker.Not(checker.Contains), "localnet") assert.Assert(c, !strings.Contains(out, "localnet"))
out, err = d.Cmd("service", "ls", "--filter", "mode=global") out, err = d.Cmd("service", "ls", "--filter", "mode=global")
c.Assert(out, checker.Not(checker.Contains), "top1") assert.Assert(c, !strings.Contains(out, "top1"))
c.Assert(out, checker.Contains, "top2") assert.Assert(c, strings.Contains(out, "top2"))
assert.NilError(c, err, out) assert.NilError(c, err, out)
out, err = d.Cmd("service", "ls", "--filter", "mode=replicated") out, err = d.Cmd("service", "ls", "--filter", "mode=replicated")
assert.NilError(c, err, out) assert.NilError(c, err, out)
c.Assert(out, checker.Contains, "top1") assert.Assert(c, strings.Contains(out, "top1"))
c.Assert(out, checker.Not(checker.Contains), "top2") assert.Assert(c, !strings.Contains(out, "top2"))
} }
func (s *DockerSwarmSuite) TestSwarmInitUnspecifiedDataPathAddr(c *check.C) { func (s *DockerSwarmSuite) TestSwarmInitUnspecifiedDataPathAddr(c *testing.T) {
d := s.AddDaemon(c, false, false) d := s.AddDaemon(c, false, false)
out, err := d.Cmd("swarm", "init", "--data-path-addr", "0.0.0.0") out, err := d.Cmd("swarm", "init", "--data-path-addr", "0.0.0.0")
assert.ErrorContains(c, err, "") assert.ErrorContains(c, err, "")
c.Assert(out, checker.Contains, "data path address must be a non-zero IP" assert.Assert(c, strings.Contains(out, "data path address must be a non-z
) ero IP"))
out, err = d.Cmd("swarm", "init", "--data-path-addr", "0.0.0.0:2000") out, err = d.Cmd("swarm", "init", "--data-path-addr", "0.0.0.0:2000")
assert.ErrorContains(c, err, "") assert.ErrorContains(c, err, "")
c.Assert(out, checker.Contains, "data path address must be a non-zero IP" ) assert.Assert(c, strings.Contains(out, "data path address must be a non-z ero IP"))
} }
func (s *DockerSwarmSuite) TestSwarmJoinLeave(c *check.C) { func (s *DockerSwarmSuite) TestSwarmJoinLeave(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
out, err := d.Cmd("swarm", "join-token", "-q", "worker") out, err := d.Cmd("swarm", "join-token", "-q", "worker")
assert.NilError(c, err) assert.NilError(c, err)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
token := strings.TrimSpace(out) token := strings.TrimSpace(out)
// 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)
skipping to change at line 1773 skipping to change at line 1769
assert.NilError(c, err) assert.NilError(c, err)
assert.Assert(c, strings.TrimSpace(out) != "") assert.Assert(c, strings.TrimSpace(out) != "")
_, err = d1.Cmd("swarm", "leave") _, err = d1.Cmd("swarm", "leave")
assert.NilError(c, err) assert.NilError(c, err)
} }
} }
const defaultRetryCount = 10 const defaultRetryCount = 10
func waitForEvent(c *check.C, d *daemon.Daemon, since string, filter string, eve nt string, retry int) string { func waitForEvent(c *testing.T, d *daemon.Daemon, since string, filter string, e vent 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 ""
} }
var out string var out string
for i := 0; i < retry; i++ { for i := 0; i < retry; i++ {
until := daemonUnixTime(c) until := daemonUnixTime(c)
var err error var err error
if len(filter) > 0 { if len(filter) > 0 {
out, err = d.Cmd("events", "--since", since, "--until", u ntil, filter) out, err = d.Cmd("events", "--since", since, "--until", u ntil, filter)
skipping to change at line 1800 skipping to change at line 1796
} }
// no need to sleep after last retry // no need to sleep after last retry
if i < retry-1 { if i < retry-1 {
time.Sleep(200 * time.Millisecond) time.Sleep(200 * time.Millisecond)
} }
} }
c.Fatalf("docker events output '%s' doesn't contain event '%s'", out, eve nt) c.Fatalf("docker events output '%s' doesn't contain event '%s'", out, eve nt)
return "" return ""
} }
func (s *DockerSwarmSuite) TestSwarmClusterEventsSource(c *check.C) { func (s *DockerSwarmSuite) TestSwarmClusterEventsSource(c *testing.T) {
d1 := s.AddDaemon(c, true, true) d1 := s.AddDaemon(c, true, true)
d2 := s.AddDaemon(c, true, true) d2 := s.AddDaemon(c, true, true)
d3 := s.AddDaemon(c, true, false) d3 := s.AddDaemon(c, true, false)
// create a network // create a network
out, err := d1.Cmd("network", "create", "--attachable", "-d", "overlay", "foo") out, err := d1.Cmd("network", "create", "--attachable", "-d", "overlay", "foo")
assert.NilError(c, err, out) assert.NilError(c, err, out)
networkID := strings.TrimSpace(out) networkID := strings.TrimSpace(out)
c.Assert(networkID, checker.Not(checker.Equals), "") assert.Assert(c, networkID != "")
// d1, d2 are managers that can get swarm events // d1, d2 are managers that can get swarm events
waitForEvent(c, d1, "0", "-f scope=swarm", "network create "+networkID, d efaultRetryCount) waitForEvent(c, d1, "0", "-f scope=swarm", "network create "+networkID, d efaultRetryCount)
waitForEvent(c, d2, "0", "-f scope=swarm", "network create "+networkID, d efaultRetryCount) waitForEvent(c, d2, "0", "-f scope=swarm", "network create "+networkID, d efaultRetryCount)
// d3 is a worker, not able to get cluster events // d3 is a worker, not able to get cluster events
out = waitForEvent(c, d3, "0", "-f scope=swarm", "", 1) out = waitForEvent(c, d3, "0", "-f scope=swarm", "", 1)
c.Assert(out, checker.Not(checker.Contains), "network create ") assert.Assert(c, !strings.Contains(out, "network create "))
} }
func (s *DockerSwarmSuite) TestSwarmClusterEventsScope(c *check.C) { func (s *DockerSwarmSuite) TestSwarmClusterEventsScope(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
// create a service // create a service
out, err := d.Cmd("service", "create", "--no-resolve-image", "--name", "t est", "--detach=false", "busybox", "top") out, err := d.Cmd("service", "create", "--no-resolve-image", "--name", "t est", "--detach=false", "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
serviceID := strings.Split(out, "\n")[0] serviceID := strings.Split(out, "\n")[0]
// scope swarm filters cluster events // scope swarm filters cluster events
out = waitForEvent(c, d, "0", "-f scope=swarm", "service create "+service ID, defaultRetryCount) out = waitForEvent(c, d, "0", "-f scope=swarm", "service create "+service ID, defaultRetryCount)
c.Assert(out, checker.Not(checker.Contains), "container create ") assert.Assert(c, !strings.Contains(out, "container create "))
// all events are returned if scope is not specified // all events are returned if scope is not specified
waitForEvent(c, d, "0", "", "service create "+serviceID, 1) waitForEvent(c, d, "0", "", "service create "+serviceID, 1)
waitForEvent(c, d, "0", "", "container create ", defaultRetryCount) waitForEvent(c, d, "0", "", "container create ", defaultRetryCount)
// scope local only shows non-cluster events // scope local only shows non-cluster events
out = waitForEvent(c, d, "0", "-f scope=local", "container create ", 1) out = waitForEvent(c, d, "0", "-f scope=local", "container create ", 1)
c.Assert(out, checker.Not(checker.Contains), "service create ") assert.Assert(c, !strings.Contains(out, "service create "))
} }
func (s *DockerSwarmSuite) TestSwarmClusterEventsType(c *check.C) { func (s *DockerSwarmSuite) TestSwarmClusterEventsType(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
// create a service // create a service
out, err := d.Cmd("service", "create", "--no-resolve-image", "--name", "t est", "--detach=false", "busybox", "top") out, err := d.Cmd("service", "create", "--no-resolve-image", "--name", "t est", "--detach=false", "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
serviceID := strings.Split(out, "\n")[0] serviceID := strings.Split(out, "\n")[0]
// create a network // create a network
out, err = d.Cmd("network", "create", "--attachable", "-d", "overlay", "f oo") out, err = d.Cmd("network", "create", "--attachable", "-d", "overlay", "f oo")
assert.NilError(c, err, out) assert.NilError(c, err, out)
networkID := strings.TrimSpace(out) networkID := strings.TrimSpace(out)
c.Assert(networkID, checker.Not(checker.Equals), "") assert.Assert(c, networkID != "")
// filter by service // filter by service
out = waitForEvent(c, d, "0", "-f type=service", "service create "+servic eID, defaultRetryCount) out = waitForEvent(c, d, "0", "-f type=service", "service create "+servic eID, defaultRetryCount)
c.Assert(out, checker.Not(checker.Contains), "network create") assert.Assert(c, !strings.Contains(out, "network create"))
// filter by network // filter by network
out = waitForEvent(c, d, "0", "-f type=network", "network create "+networ kID, defaultRetryCount) out = waitForEvent(c, d, "0", "-f type=network", "network create "+networ kID, defaultRetryCount)
c.Assert(out, checker.Not(checker.Contains), "service create") assert.Assert(c, !strings.Contains(out, "service create"))
} }
func (s *DockerSwarmSuite) TestSwarmClusterEventsService(c *check.C) { func (s *DockerSwarmSuite) TestSwarmClusterEventsService(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
// create a service // create a service
out, err := d.Cmd("service", "create", "--no-resolve-image", "--name", "t est", "--detach=false", "busybox", "top") out, err := d.Cmd("service", "create", "--no-resolve-image", "--name", "t est", "--detach=false", "busybox", "top")
assert.NilError(c, err, out) assert.NilError(c, err, out)
serviceID := strings.Split(out, "\n")[0] serviceID := strings.Split(out, "\n")[0]
// validate service create event // validate service create event
waitForEvent(c, d, "0", "-f scope=swarm", "service create "+serviceID, de faultRetryCount) waitForEvent(c, d, "0", "-f scope=swarm", "service create "+serviceID, de faultRetryCount)
t1 := daemonUnixTime(c) t1 := daemonUnixTime(c)
out, err = d.Cmd("service", "update", "--force", "--detach=false", "test" ) out, err = d.Cmd("service", "update", "--force", "--detach=false", "test" )
assert.NilError(c, err, out) assert.NilError(c, err, out)
// wait for service update start // wait for service update start
out = waitForEvent(c, d, t1, "-f scope=swarm", "service update "+serviceI D, defaultRetryCount) out = waitForEvent(c, d, t1, "-f scope=swarm", "service update "+serviceI D, defaultRetryCount)
c.Assert(out, checker.Contains, "updatestate.new=updating") assert.Assert(c, strings.Contains(out, "updatestate.new=updating"))
// allow service update complete. This is a service with 1 instance // allow service update complete. This is a service with 1 instance
time.Sleep(400 * time.Millisecond) time.Sleep(400 * time.Millisecond)
out = waitForEvent(c, d, t1, "-f scope=swarm", "service update "+serviceI D, defaultRetryCount) out = waitForEvent(c, d, t1, "-f scope=swarm", "service update "+serviceI D, defaultRetryCount)
c.Assert(out, checker.Contains, "updatestate.new=completed, updatestate.o assert.Assert(c, strings.Contains(out, "updatestate.new=completed, update
ld=updating") state.old=updating"))
// scale service // scale service
t2 := daemonUnixTime(c) t2 := daemonUnixTime(c)
out, err = d.Cmd("service", "scale", "test=3") out, err = d.Cmd("service", "scale", "test=3")
assert.NilError(c, err, out) assert.NilError(c, err, out)
out = waitForEvent(c, d, t2, "-f scope=swarm", "service update "+serviceI D, defaultRetryCount) out = waitForEvent(c, d, t2, "-f scope=swarm", "service update "+serviceI D, defaultRetryCount)
c.Assert(out, checker.Contains, "replicas.new=3, replicas.old=1") assert.Assert(c, strings.Contains(out, "replicas.new=3, replicas.old=1"))
// remove service // remove service
t3 := daemonUnixTime(c) t3 := daemonUnixTime(c)
out, err = d.Cmd("service", "rm", "test") out, err = d.Cmd("service", "rm", "test")
assert.NilError(c, err, out) assert.NilError(c, err, out)
waitForEvent(c, d, t3, "-f scope=swarm", "service remove "+serviceID, def aultRetryCount) waitForEvent(c, d, t3, "-f scope=swarm", "service remove "+serviceID, def aultRetryCount)
} }
func (s *DockerSwarmSuite) TestSwarmClusterEventsNode(c *check.C) { func (s *DockerSwarmSuite) TestSwarmClusterEventsNode(c *testing.T) {
d1 := s.AddDaemon(c, true, true) d1 := s.AddDaemon(c, true, true)
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, defaultRe tryCount) waitForEvent(c, d1, "0", "-f scope=swarm", "node create "+d3ID, defaultRe tryCount)
t1 := daemonUnixTime(c) t1 := daemonUnixTime(c)
out, err := d1.Cmd("node", "update", "--availability=pause", d3ID) out, err := d1.Cmd("node", "update", "--availability=pause", d3ID)
assert.NilError(c, err, out) assert.NilError(c, err, out)
// filter by type // filter by type
out = waitForEvent(c, d1, t1, "-f type=node", "node update "+d3ID, defaul tRetryCount) out = waitForEvent(c, d1, t1, "-f type=node", "node update "+d3ID, defaul tRetryCount)
c.Assert(out, checker.Contains, "availability.new=pause, availability.old assert.Assert(c, strings.Contains(out, "availability.new=pause, availabil
=active") ity.old=active"))
t2 := daemonUnixTime(c) t2 := daemonUnixTime(c)
out, err = d1.Cmd("node", "demote", d3ID) out, err = d1.Cmd("node", "demote", d3ID)
assert.NilError(c, err, out) assert.NilError(c, err, out)
waitForEvent(c, d1, t2, "-f type=node", "node update "+d3ID, defaultRetry Count) waitForEvent(c, d1, t2, "-f type=node", "node update "+d3ID, defaultRetry Count)
t3 := daemonUnixTime(c) t3 := daemonUnixTime(c)
out, err = d1.Cmd("node", "rm", "-f", d3ID) out, err = d1.Cmd("node", "rm", "-f", d3ID)
assert.NilError(c, err, out) assert.NilError(c, err, out)
// filter by scope // filter by scope
waitForEvent(c, d1, t3, "-f scope=swarm", "node remove "+d3ID, defaultRet ryCount) waitForEvent(c, d1, t3, "-f scope=swarm", "node remove "+d3ID, defaultRet ryCount)
} }
func (s *DockerSwarmSuite) TestSwarmClusterEventsNetwork(c *check.C) { func (s *DockerSwarmSuite) TestSwarmClusterEventsNetwork(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
// create a network // create a network
out, err := d.Cmd("network", "create", "--attachable", "-d", "overlay", " foo") out, err := d.Cmd("network", "create", "--attachable", "-d", "overlay", " foo")
assert.NilError(c, err, out) assert.NilError(c, err, out)
networkID := strings.TrimSpace(out) networkID := strings.TrimSpace(out)
waitForEvent(c, d, "0", "-f scope=swarm", "network create "+networkID, de faultRetryCount) waitForEvent(c, d, "0", "-f scope=swarm", "network create "+networkID, de faultRetryCount)
// remove network // remove network
t1 := daemonUnixTime(c) t1 := daemonUnixTime(c)
out, err = d.Cmd("network", "rm", "foo") out, err = d.Cmd("network", "rm", "foo")
assert.NilError(c, err, out) assert.NilError(c, err, out)
// filtered by network // filtered by network
waitForEvent(c, d, t1, "-f type=network", "network remove "+networkID, de faultRetryCount) waitForEvent(c, d, t1, "-f type=network", "network remove "+networkID, de faultRetryCount)
} }
func (s *DockerSwarmSuite) TestSwarmClusterEventsSecret(c *check.C) { func (s *DockerSwarmSuite) TestSwarmClusterEventsSecret(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
testName := "test_secret" testName := "test_secret"
id := d.CreateSecret(c, swarm.SecretSpec{ id := d.CreateSecret(c, swarm.SecretSpec{
Annotations: swarm.Annotations{ Annotations: swarm.Annotations{
Name: testName, Name: testName,
}, },
Data: []byte("TESTINGDATA"), Data: []byte("TESTINGDATA"),
}) })
c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("secrets: %s ", id)) assert.Assert(c, id != "", "secrets: %s", id)
waitForEvent(c, d, "0", "-f scope=swarm", "secret create "+id, defaultRet ryCount) waitForEvent(c, d, "0", "-f scope=swarm", "secret create "+id, defaultRet ryCount)
t1 := daemonUnixTime(c) t1 := daemonUnixTime(c)
d.DeleteSecret(c, id) d.DeleteSecret(c, id)
// filtered by secret // filtered by secret
waitForEvent(c, d, t1, "-f type=secret", "secret remove "+id, defaultRetr yCount) waitForEvent(c, d, t1, "-f type=secret", "secret remove "+id, defaultRetr yCount)
} }
func (s *DockerSwarmSuite) TestSwarmClusterEventsConfig(c *check.C) { func (s *DockerSwarmSuite) TestSwarmClusterEventsConfig(c *testing.T) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
testName := "test_config" testName := "test_config"
id := d.CreateConfig(c, swarm.ConfigSpec{ id := d.CreateConfig(c, swarm.ConfigSpec{
Annotations: swarm.Annotations{ Annotations: swarm.Annotations{
Name: testName, Name: testName,
}, },
Data: []byte("TESTINGDATA"), Data: []byte("TESTINGDATA"),
}) })
c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("configs: %s ", id)) assert.Assert(c, id != "", "configs: %s", id)
waitForEvent(c, d, "0", "-f scope=swarm", "config create "+id, defaultRet ryCount) waitForEvent(c, d, "0", "-f scope=swarm", "config create "+id, defaultRet ryCount)
t1 := daemonUnixTime(c) t1 := daemonUnixTime(c)
d.DeleteConfig(c, id) d.DeleteConfig(c, id)
// filtered by config // filtered by config
waitForEvent(c, d, t1, "-f type=config", "config remove "+id, defaultRetr yCount) waitForEvent(c, d, t1, "-f type=config", "config remove "+id, defaultRetr yCount)
} }
func getUnlockKey(d *daemon.Daemon, c *check.C, autolockOutput string) string { func getUnlockKey(d *daemon.Daemon, c *testing.T, autolockOutput string) string {
unlockKey, err := d.Cmd("swarm", "unlock-key", "-q") unlockKey, err := d.Cmd("swarm", "unlock-key", "-q")
c.Assert(err, checker.IsNil, check.Commentf("%s", unlockKey)) assert.Assert(c, err == nil, "%s", unlockKey)
unlockKey = strings.TrimSuffix(unlockKey, "\n") unlockKey = strings.TrimSuffix(unlockKey, "\n")
// Check that "docker swarm init --autolock" or "docker swarm update --au tolock" // Check that "docker swarm init --autolock" or "docker swarm update --au tolock"
// contains all the expected strings, including the unlock key // contains all the expected strings, including the unlock key
c.Assert(autolockOutput, checker.Contains, "docker swarm unlock") assert.Assert(c, strings.Contains(autolockOutput, "docker swarm unlock"))
c.Assert(autolockOutput, checker.Contains, unlockKey) assert.Assert(c, strings.Contains(autolockOutput, unlockKey))
return unlockKey return unlockKey
} }
 End of changes. 230 change blocks. 
351 lines changed or deleted 347 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)