Signed-off-by: allencloud <allen.sun@daocloud.io>
| 1 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,40 +0,0 @@ |
| 1 |
-// +build !windows |
|
| 2 |
- |
|
| 3 |
-package main |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "github.com/docker/docker/api/types/swarm" |
|
| 7 |
- "github.com/docker/docker/integration-cli/checker" |
|
| 8 |
- "github.com/docker/docker/integration-cli/daemon" |
|
| 9 |
- "github.com/go-check/check" |
|
| 10 |
-) |
|
| 11 |
- |
|
| 12 |
-func setPortConfig(portConfig []swarm.PortConfig) daemon.ServiceConstructor {
|
|
| 13 |
- return func(s *swarm.Service) {
|
|
| 14 |
- if s.Spec.EndpointSpec == nil {
|
|
| 15 |
- s.Spec.EndpointSpec = &swarm.EndpointSpec{}
|
|
| 16 |
- } |
|
| 17 |
- s.Spec.EndpointSpec.Ports = portConfig |
|
| 18 |
- } |
|
| 19 |
-} |
|
| 20 |
- |
|
| 21 |
-func (s *DockerSwarmSuite) TestAPIServiceUpdatePort(c *check.C) {
|
|
| 22 |
- d := s.AddDaemon(c, true, true) |
|
| 23 |
- |
|
| 24 |
- // Create a service with a port mapping of 8080:8081. |
|
| 25 |
- portConfig := []swarm.PortConfig{{TargetPort: 8081, PublishedPort: 8080}}
|
|
| 26 |
- serviceID := d.CreateService(c, simpleTestService, setInstances(1), setPortConfig(portConfig)) |
|
| 27 |
- waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1) |
|
| 28 |
- |
|
| 29 |
- // Update the service: changed the port mapping from 8080:8081 to 8082:8083. |
|
| 30 |
- updatedPortConfig := []swarm.PortConfig{{TargetPort: 8083, PublishedPort: 8082}}
|
|
| 31 |
- remoteService := d.GetService(c, serviceID) |
|
| 32 |
- d.UpdateService(c, remoteService, setPortConfig(updatedPortConfig)) |
|
| 33 |
- |
|
| 34 |
- // Inspect the service and verify port mapping. |
|
| 35 |
- updatedService := d.GetService(c, serviceID) |
|
| 36 |
- c.Assert(updatedService.Spec.EndpointSpec, check.NotNil) |
|
| 37 |
- c.Assert(len(updatedService.Spec.EndpointSpec.Ports), check.Equals, 1) |
|
| 38 |
- c.Assert(updatedService.Spec.EndpointSpec.Ports[0].TargetPort, check.Equals, uint32(8083)) |
|
| 39 |
- c.Assert(updatedService.Spec.EndpointSpec.Ports[0].PublishedPort, check.Equals, uint32(8082)) |
|
| 40 |
-} |
| 41 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,128 @@ |
| 0 |
+// +build !windows |
|
| 1 |
+ |
|
| 2 |
+package main |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "time" |
|
| 6 |
+ |
|
| 7 |
+ "github.com/docker/docker/api/types/swarm" |
|
| 8 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 9 |
+ "github.com/docker/docker/integration-cli/daemon" |
|
| 10 |
+ "github.com/go-check/check" |
|
| 11 |
+) |
|
| 12 |
+ |
|
| 13 |
+func (s *DockerSwarmSuite) TestAPISwarmListNodes(c *check.C) {
|
|
| 14 |
+ d1 := s.AddDaemon(c, true, true) |
|
| 15 |
+ d2 := s.AddDaemon(c, true, false) |
|
| 16 |
+ d3 := s.AddDaemon(c, true, false) |
|
| 17 |
+ |
|
| 18 |
+ nodes := d1.ListNodes(c) |
|
| 19 |
+ c.Assert(len(nodes), checker.Equals, 3, check.Commentf("nodes: %#v", nodes))
|
|
| 20 |
+ |
|
| 21 |
+loop0: |
|
| 22 |
+ for _, n := range nodes {
|
|
| 23 |
+ for _, d := range []*daemon.Swarm{d1, d2, d3} {
|
|
| 24 |
+ if n.ID == d.NodeID {
|
|
| 25 |
+ continue loop0 |
|
| 26 |
+ } |
|
| 27 |
+ } |
|
| 28 |
+ c.Errorf("unknown nodeID %v", n.ID)
|
|
| 29 |
+ } |
|
| 30 |
+} |
|
| 31 |
+ |
|
| 32 |
+func (s *DockerSwarmSuite) TestAPISwarmNodeUpdate(c *check.C) {
|
|
| 33 |
+ d := s.AddDaemon(c, true, true) |
|
| 34 |
+ |
|
| 35 |
+ nodes := d.ListNodes(c) |
|
| 36 |
+ |
|
| 37 |
+ d.UpdateNode(c, nodes[0].ID, func(n *swarm.Node) {
|
|
| 38 |
+ n.Spec.Availability = swarm.NodeAvailabilityPause |
|
| 39 |
+ }) |
|
| 40 |
+ |
|
| 41 |
+ n := d.GetNode(c, nodes[0].ID) |
|
| 42 |
+ c.Assert(n.Spec.Availability, checker.Equals, swarm.NodeAvailabilityPause) |
|
| 43 |
+} |
|
| 44 |
+ |
|
| 45 |
+func (s *DockerSwarmSuite) TestAPISwarmNodeRemove(c *check.C) {
|
|
| 46 |
+ testRequires(c, Network) |
|
| 47 |
+ d1 := s.AddDaemon(c, true, true) |
|
| 48 |
+ d2 := s.AddDaemon(c, true, false) |
|
| 49 |
+ _ = s.AddDaemon(c, true, false) |
|
| 50 |
+ |
|
| 51 |
+ nodes := d1.ListNodes(c) |
|
| 52 |
+ c.Assert(len(nodes), checker.Equals, 3, check.Commentf("nodes: %#v", nodes))
|
|
| 53 |
+ |
|
| 54 |
+ // Getting the info so we can take the NodeID |
|
| 55 |
+ d2Info, err := d2.SwarmInfo() |
|
| 56 |
+ c.Assert(err, checker.IsNil) |
|
| 57 |
+ |
|
| 58 |
+ // forceful removal of d2 should work |
|
| 59 |
+ d1.RemoveNode(c, d2Info.NodeID, true) |
|
| 60 |
+ |
|
| 61 |
+ nodes = d1.ListNodes(c) |
|
| 62 |
+ c.Assert(len(nodes), checker.Equals, 2, check.Commentf("nodes: %#v", nodes))
|
|
| 63 |
+ |
|
| 64 |
+ // Restart the node that was removed |
|
| 65 |
+ d2.Restart(c) |
|
| 66 |
+ |
|
| 67 |
+ // Give some time for the node to rejoin |
|
| 68 |
+ time.Sleep(1 * time.Second) |
|
| 69 |
+ |
|
| 70 |
+ // Make sure the node didn't rejoin |
|
| 71 |
+ nodes = d1.ListNodes(c) |
|
| 72 |
+ c.Assert(len(nodes), checker.Equals, 2, check.Commentf("nodes: %#v", nodes))
|
|
| 73 |
+} |
|
| 74 |
+ |
|
| 75 |
+func (s *DockerSwarmSuite) TestAPISwarmNodeDrainPause(c *check.C) {
|
|
| 76 |
+ d1 := s.AddDaemon(c, true, true) |
|
| 77 |
+ d2 := s.AddDaemon(c, true, false) |
|
| 78 |
+ |
|
| 79 |
+ time.Sleep(1 * time.Second) // make sure all daemons are ready to accept tasks |
|
| 80 |
+ |
|
| 81 |
+ // start a service, expect balanced distribution |
|
| 82 |
+ instances := 8 |
|
| 83 |
+ id := d1.CreateService(c, simpleTestService, setInstances(instances)) |
|
| 84 |
+ |
|
| 85 |
+ waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.GreaterThan, 0) |
|
| 86 |
+ waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.GreaterThan, 0) |
|
| 87 |
+ waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals, instances) |
|
| 88 |
+ |
|
| 89 |
+ // drain d2, all containers should move to d1 |
|
| 90 |
+ d1.UpdateNode(c, d2.NodeID, func(n *swarm.Node) {
|
|
| 91 |
+ n.Spec.Availability = swarm.NodeAvailabilityDrain |
|
| 92 |
+ }) |
|
| 93 |
+ waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.Equals, instances) |
|
| 94 |
+ waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.Equals, 0) |
|
| 95 |
+ |
|
| 96 |
+ // set d2 back to active |
|
| 97 |
+ d1.UpdateNode(c, d2.NodeID, func(n *swarm.Node) {
|
|
| 98 |
+ n.Spec.Availability = swarm.NodeAvailabilityActive |
|
| 99 |
+ }) |
|
| 100 |
+ |
|
| 101 |
+ instances = 1 |
|
| 102 |
+ d1.UpdateService(c, d1.GetService(c, id), setInstances(instances)) |
|
| 103 |
+ |
|
| 104 |
+ waitAndAssert(c, defaultReconciliationTimeout*2, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals, instances) |
|
| 105 |
+ |
|
| 106 |
+ instances = 8 |
|
| 107 |
+ d1.UpdateService(c, d1.GetService(c, id), setInstances(instances)) |
|
| 108 |
+ |
|
| 109 |
+ // drained node first so we don't get any old containers |
|
| 110 |
+ waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.GreaterThan, 0) |
|
| 111 |
+ waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.GreaterThan, 0) |
|
| 112 |
+ waitAndAssert(c, defaultReconciliationTimeout*2, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals, instances) |
|
| 113 |
+ |
|
| 114 |
+ d2ContainerCount := len(d2.ActiveContainers()) |
|
| 115 |
+ |
|
| 116 |
+ // set d2 to paused, scale service up, only d1 gets new tasks |
|
| 117 |
+ d1.UpdateNode(c, d2.NodeID, func(n *swarm.Node) {
|
|
| 118 |
+ n.Spec.Availability = swarm.NodeAvailabilityPause |
|
| 119 |
+ }) |
|
| 120 |
+ |
|
| 121 |
+ instances = 14 |
|
| 122 |
+ d1.UpdateService(c, d1.GetService(c, id), setInstances(instances)) |
|
| 123 |
+ |
|
| 124 |
+ waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.Equals, instances-d2ContainerCount) |
|
| 125 |
+ waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.Equals, d2ContainerCount) |
|
| 126 |
+ |
|
| 127 |
+} |
| 0 | 128 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,58 @@ |
| 0 |
+// +build !windows |
|
| 1 |
+ |
|
| 2 |
+package main |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "net/http" |
|
| 6 |
+ |
|
| 7 |
+ "github.com/docker/docker/api/types/swarm" |
|
| 8 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 9 |
+ "github.com/go-check/check" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+func (s *DockerSwarmSuite) TestAPISwarmSecretsEmptyList(c *check.C) {
|
|
| 13 |
+ d := s.AddDaemon(c, true, true) |
|
| 14 |
+ |
|
| 15 |
+ secrets := d.ListSecrets(c) |
|
| 16 |
+ c.Assert(secrets, checker.NotNil) |
|
| 17 |
+ c.Assert(len(secrets), checker.Equals, 0, check.Commentf("secrets: %#v", secrets))
|
|
| 18 |
+} |
|
| 19 |
+ |
|
| 20 |
+func (s *DockerSwarmSuite) TestAPISwarmSecretsCreate(c *check.C) {
|
|
| 21 |
+ d := s.AddDaemon(c, true, true) |
|
| 22 |
+ |
|
| 23 |
+ testName := "test_secret" |
|
| 24 |
+ id := d.CreateSecret(c, swarm.SecretSpec{
|
|
| 25 |
+ swarm.Annotations{
|
|
| 26 |
+ Name: testName, |
|
| 27 |
+ }, |
|
| 28 |
+ []byte("TESTINGDATA"),
|
|
| 29 |
+ }) |
|
| 30 |
+ c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("secrets: %s", id))
|
|
| 31 |
+ |
|
| 32 |
+ secrets := d.ListSecrets(c) |
|
| 33 |
+ c.Assert(len(secrets), checker.Equals, 1, check.Commentf("secrets: %#v", secrets))
|
|
| 34 |
+ name := secrets[0].Spec.Annotations.Name |
|
| 35 |
+ c.Assert(name, checker.Equals, testName, check.Commentf("secret: %s", name))
|
|
| 36 |
+} |
|
| 37 |
+ |
|
| 38 |
+func (s *DockerSwarmSuite) TestAPISwarmSecretsDelete(c *check.C) {
|
|
| 39 |
+ d := s.AddDaemon(c, true, true) |
|
| 40 |
+ |
|
| 41 |
+ testName := "test_secret" |
|
| 42 |
+ id := d.CreateSecret(c, swarm.SecretSpec{
|
|
| 43 |
+ swarm.Annotations{
|
|
| 44 |
+ Name: testName, |
|
| 45 |
+ }, |
|
| 46 |
+ []byte("TESTINGDATA"),
|
|
| 47 |
+ }) |
|
| 48 |
+ c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("secrets: %s", id))
|
|
| 49 |
+ |
|
| 50 |
+ secret := d.GetSecret(c, id) |
|
| 51 |
+ c.Assert(secret.ID, checker.Equals, id, check.Commentf("secret: %v", secret))
|
|
| 52 |
+ |
|
| 53 |
+ d.DeleteSecret(c, secret.ID) |
|
| 54 |
+ status, out, err := d.SockRequest("GET", "/secrets/"+id, nil)
|
|
| 55 |
+ c.Assert(err, checker.IsNil) |
|
| 56 |
+ c.Assert(status, checker.Equals, http.StatusNotFound, check.Commentf("secret delete: %s", string(out)))
|
|
| 57 |
+} |
| 0 | 58 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,440 @@ |
| 0 |
+// +build !windows |
|
| 1 |
+ |
|
| 2 |
+package main |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "fmt" |
|
| 6 |
+ "strconv" |
|
| 7 |
+ "strings" |
|
| 8 |
+ "syscall" |
|
| 9 |
+ "time" |
|
| 10 |
+ |
|
| 11 |
+ "github.com/docker/docker/api/types/swarm" |
|
| 12 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 13 |
+ "github.com/docker/docker/integration-cli/daemon" |
|
| 14 |
+ "github.com/go-check/check" |
|
| 15 |
+) |
|
| 16 |
+ |
|
| 17 |
+func setPortConfig(portConfig []swarm.PortConfig) daemon.ServiceConstructor {
|
|
| 18 |
+ return func(s *swarm.Service) {
|
|
| 19 |
+ if s.Spec.EndpointSpec == nil {
|
|
| 20 |
+ s.Spec.EndpointSpec = &swarm.EndpointSpec{}
|
|
| 21 |
+ } |
|
| 22 |
+ s.Spec.EndpointSpec.Ports = portConfig |
|
| 23 |
+ } |
|
| 24 |
+} |
|
| 25 |
+ |
|
| 26 |
+func (s *DockerSwarmSuite) TestAPIServiceUpdatePort(c *check.C) {
|
|
| 27 |
+ d := s.AddDaemon(c, true, true) |
|
| 28 |
+ |
|
| 29 |
+ // Create a service with a port mapping of 8080:8081. |
|
| 30 |
+ portConfig := []swarm.PortConfig{{TargetPort: 8081, PublishedPort: 8080}}
|
|
| 31 |
+ serviceID := d.CreateService(c, simpleTestService, setInstances(1), setPortConfig(portConfig)) |
|
| 32 |
+ waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1) |
|
| 33 |
+ |
|
| 34 |
+ // Update the service: changed the port mapping from 8080:8081 to 8082:8083. |
|
| 35 |
+ updatedPortConfig := []swarm.PortConfig{{TargetPort: 8083, PublishedPort: 8082}}
|
|
| 36 |
+ remoteService := d.GetService(c, serviceID) |
|
| 37 |
+ d.UpdateService(c, remoteService, setPortConfig(updatedPortConfig)) |
|
| 38 |
+ |
|
| 39 |
+ // Inspect the service and verify port mapping. |
|
| 40 |
+ updatedService := d.GetService(c, serviceID) |
|
| 41 |
+ c.Assert(updatedService.Spec.EndpointSpec, check.NotNil) |
|
| 42 |
+ c.Assert(len(updatedService.Spec.EndpointSpec.Ports), check.Equals, 1) |
|
| 43 |
+ c.Assert(updatedService.Spec.EndpointSpec.Ports[0].TargetPort, check.Equals, uint32(8083)) |
|
| 44 |
+ c.Assert(updatedService.Spec.EndpointSpec.Ports[0].PublishedPort, check.Equals, uint32(8082)) |
|
| 45 |
+} |
|
| 46 |
+ |
|
| 47 |
+func (s *DockerSwarmSuite) TestAPISwarmServicesEmptyList(c *check.C) {
|
|
| 48 |
+ d := s.AddDaemon(c, true, true) |
|
| 49 |
+ |
|
| 50 |
+ services := d.ListServices(c) |
|
| 51 |
+ c.Assert(services, checker.NotNil) |
|
| 52 |
+ c.Assert(len(services), checker.Equals, 0, check.Commentf("services: %#v", services))
|
|
| 53 |
+} |
|
| 54 |
+ |
|
| 55 |
+func (s *DockerSwarmSuite) TestAPISwarmServicesCreate(c *check.C) {
|
|
| 56 |
+ d := s.AddDaemon(c, true, true) |
|
| 57 |
+ |
|
| 58 |
+ instances := 2 |
|
| 59 |
+ id := d.CreateService(c, simpleTestService, setInstances(instances)) |
|
| 60 |
+ waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances) |
|
| 61 |
+ |
|
| 62 |
+ service := d.GetService(c, id) |
|
| 63 |
+ instances = 5 |
|
| 64 |
+ d.UpdateService(c, service, setInstances(instances)) |
|
| 65 |
+ waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances) |
|
| 66 |
+ |
|
| 67 |
+ d.RemoveService(c, service.ID) |
|
| 68 |
+ waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 0) |
|
| 69 |
+} |
|
| 70 |
+ |
|
| 71 |
+func (s *DockerSwarmSuite) TestAPISwarmServicesMultipleAgents(c *check.C) {
|
|
| 72 |
+ d1 := s.AddDaemon(c, true, true) |
|
| 73 |
+ d2 := s.AddDaemon(c, true, false) |
|
| 74 |
+ d3 := s.AddDaemon(c, true, false) |
|
| 75 |
+ |
|
| 76 |
+ time.Sleep(1 * time.Second) // make sure all daemons are ready to accept tasks |
|
| 77 |
+ |
|
| 78 |
+ instances := 9 |
|
| 79 |
+ id := d1.CreateService(c, simpleTestService, setInstances(instances)) |
|
| 80 |
+ |
|
| 81 |
+ waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.GreaterThan, 0) |
|
| 82 |
+ waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.GreaterThan, 0) |
|
| 83 |
+ waitAndAssert(c, defaultReconciliationTimeout, d3.CheckActiveContainerCount, checker.GreaterThan, 0) |
|
| 84 |
+ |
|
| 85 |
+ waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals, instances) |
|
| 86 |
+ |
|
| 87 |
+ // reconciliation on d2 node down |
|
| 88 |
+ d2.Stop(c) |
|
| 89 |
+ |
|
| 90 |
+ waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals, instances) |
|
| 91 |
+ |
|
| 92 |
+ // test downscaling |
|
| 93 |
+ instances = 5 |
|
| 94 |
+ d1.UpdateService(c, d1.GetService(c, id), setInstances(instances)) |
|
| 95 |
+ waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals, instances) |
|
| 96 |
+ |
|
| 97 |
+} |
|
| 98 |
+ |
|
| 99 |
+func (s *DockerSwarmSuite) TestAPISwarmServicesCreateGlobal(c *check.C) {
|
|
| 100 |
+ d1 := s.AddDaemon(c, true, true) |
|
| 101 |
+ d2 := s.AddDaemon(c, true, false) |
|
| 102 |
+ d3 := s.AddDaemon(c, true, false) |
|
| 103 |
+ |
|
| 104 |
+ d1.CreateService(c, simpleTestService, setGlobalMode) |
|
| 105 |
+ |
|
| 106 |
+ waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.Equals, 1) |
|
| 107 |
+ waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.Equals, 1) |
|
| 108 |
+ waitAndAssert(c, defaultReconciliationTimeout, d3.CheckActiveContainerCount, checker.Equals, 1) |
|
| 109 |
+ |
|
| 110 |
+ d4 := s.AddDaemon(c, true, false) |
|
| 111 |
+ d5 := s.AddDaemon(c, true, false) |
|
| 112 |
+ |
|
| 113 |
+ waitAndAssert(c, defaultReconciliationTimeout, d4.CheckActiveContainerCount, checker.Equals, 1) |
|
| 114 |
+ waitAndAssert(c, defaultReconciliationTimeout, d5.CheckActiveContainerCount, checker.Equals, 1) |
|
| 115 |
+} |
|
| 116 |
+ |
|
| 117 |
+func (s *DockerSwarmSuite) TestAPISwarmServicesUpdate(c *check.C) {
|
|
| 118 |
+ const nodeCount = 3 |
|
| 119 |
+ var daemons [nodeCount]*daemon.Swarm |
|
| 120 |
+ for i := 0; i < nodeCount; i++ {
|
|
| 121 |
+ daemons[i] = s.AddDaemon(c, true, i == 0) |
|
| 122 |
+ } |
|
| 123 |
+ // wait for nodes ready |
|
| 124 |
+ waitAndAssert(c, 5*time.Second, daemons[0].CheckNodeReadyCount, checker.Equals, nodeCount) |
|
| 125 |
+ |
|
| 126 |
+ // service image at start |
|
| 127 |
+ image1 := "busybox:latest" |
|
| 128 |
+ // target image in update |
|
| 129 |
+ image2 := "busybox:test" |
|
| 130 |
+ |
|
| 131 |
+ // create a different tag |
|
| 132 |
+ for _, d := range daemons {
|
|
| 133 |
+ out, err := d.Cmd("tag", image1, image2)
|
|
| 134 |
+ c.Assert(err, checker.IsNil, check.Commentf(out)) |
|
| 135 |
+ } |
|
| 136 |
+ |
|
| 137 |
+ // create service |
|
| 138 |
+ instances := 5 |
|
| 139 |
+ parallelism := 2 |
|
| 140 |
+ id := daemons[0].CreateService(c, serviceForUpdate, setInstances(instances)) |
|
| 141 |
+ |
|
| 142 |
+ // wait for tasks ready |
|
| 143 |
+ waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals, |
|
| 144 |
+ map[string]int{image1: instances})
|
|
| 145 |
+ |
|
| 146 |
+ // issue service update |
|
| 147 |
+ service := daemons[0].GetService(c, id) |
|
| 148 |
+ daemons[0].UpdateService(c, service, setImage(image2)) |
|
| 149 |
+ |
|
| 150 |
+ // first batch |
|
| 151 |
+ waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals, |
|
| 152 |
+ map[string]int{image1: instances - parallelism, image2: parallelism})
|
|
| 153 |
+ |
|
| 154 |
+ // 2nd batch |
|
| 155 |
+ waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals, |
|
| 156 |
+ map[string]int{image1: instances - 2*parallelism, image2: 2 * parallelism})
|
|
| 157 |
+ |
|
| 158 |
+ // 3nd batch |
|
| 159 |
+ waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals, |
|
| 160 |
+ map[string]int{image2: instances})
|
|
| 161 |
+ |
|
| 162 |
+ // Roll back to the previous version. This uses the CLI because |
|
| 163 |
+ // rollback is a client-side operation. |
|
| 164 |
+ out, err := daemons[0].Cmd("service", "update", "--rollback", id)
|
|
| 165 |
+ c.Assert(err, checker.IsNil, check.Commentf(out)) |
|
| 166 |
+ |
|
| 167 |
+ // first batch |
|
| 168 |
+ waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals, |
|
| 169 |
+ map[string]int{image2: instances - parallelism, image1: parallelism})
|
|
| 170 |
+ |
|
| 171 |
+ // 2nd batch |
|
| 172 |
+ waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals, |
|
| 173 |
+ map[string]int{image2: instances - 2*parallelism, image1: 2 * parallelism})
|
|
| 174 |
+ |
|
| 175 |
+ // 3nd batch |
|
| 176 |
+ waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals, |
|
| 177 |
+ map[string]int{image1: instances})
|
|
| 178 |
+} |
|
| 179 |
+ |
|
| 180 |
+func (s *DockerSwarmSuite) TestAPISwarmServicesFailedUpdate(c *check.C) {
|
|
| 181 |
+ const nodeCount = 3 |
|
| 182 |
+ var daemons [nodeCount]*daemon.Swarm |
|
| 183 |
+ for i := 0; i < nodeCount; i++ {
|
|
| 184 |
+ daemons[i] = s.AddDaemon(c, true, i == 0) |
|
| 185 |
+ } |
|
| 186 |
+ // wait for nodes ready |
|
| 187 |
+ waitAndAssert(c, 5*time.Second, daemons[0].CheckNodeReadyCount, checker.Equals, nodeCount) |
|
| 188 |
+ |
|
| 189 |
+ // service image at start |
|
| 190 |
+ image1 := "busybox:latest" |
|
| 191 |
+ // target image in update |
|
| 192 |
+ image2 := "busybox:badtag" |
|
| 193 |
+ |
|
| 194 |
+ // create service |
|
| 195 |
+ instances := 5 |
|
| 196 |
+ id := daemons[0].CreateService(c, serviceForUpdate, setInstances(instances)) |
|
| 197 |
+ |
|
| 198 |
+ // wait for tasks ready |
|
| 199 |
+ waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals, |
|
| 200 |
+ map[string]int{image1: instances})
|
|
| 201 |
+ |
|
| 202 |
+ // issue service update |
|
| 203 |
+ service := daemons[0].GetService(c, id) |
|
| 204 |
+ daemons[0].UpdateService(c, service, setImage(image2), setFailureAction(swarm.UpdateFailureActionPause), setMaxFailureRatio(0.25), setParallelism(1)) |
|
| 205 |
+ |
|
| 206 |
+ // should update 2 tasks and then pause |
|
| 207 |
+ waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceUpdateState(id), checker.Equals, swarm.UpdateStatePaused) |
|
| 208 |
+ v, _ := daemons[0].CheckServiceRunningTasks(id)(c) |
|
| 209 |
+ c.Assert(v, checker.Equals, instances-2) |
|
| 210 |
+ |
|
| 211 |
+ // Roll back to the previous version. This uses the CLI because |
|
| 212 |
+ // rollback is a client-side operation. |
|
| 213 |
+ out, err := daemons[0].Cmd("service", "update", "--rollback", id)
|
|
| 214 |
+ c.Assert(err, checker.IsNil, check.Commentf(out)) |
|
| 215 |
+ |
|
| 216 |
+ waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals, |
|
| 217 |
+ map[string]int{image1: instances})
|
|
| 218 |
+} |
|
| 219 |
+ |
|
| 220 |
+func (s *DockerSwarmSuite) TestAPISwarmServiceConstraintRole(c *check.C) {
|
|
| 221 |
+ const nodeCount = 3 |
|
| 222 |
+ var daemons [nodeCount]*daemon.Swarm |
|
| 223 |
+ for i := 0; i < nodeCount; i++ {
|
|
| 224 |
+ daemons[i] = s.AddDaemon(c, true, i == 0) |
|
| 225 |
+ } |
|
| 226 |
+ // wait for nodes ready |
|
| 227 |
+ waitAndAssert(c, 5*time.Second, daemons[0].CheckNodeReadyCount, checker.Equals, nodeCount) |
|
| 228 |
+ |
|
| 229 |
+ // create service |
|
| 230 |
+ constraints := []string{"node.role==worker"}
|
|
| 231 |
+ instances := 3 |
|
| 232 |
+ id := daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances)) |
|
| 233 |
+ // wait for tasks ready |
|
| 234 |
+ waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceRunningTasks(id), checker.Equals, instances) |
|
| 235 |
+ // validate tasks are running on worker nodes |
|
| 236 |
+ tasks := daemons[0].GetServiceTasks(c, id) |
|
| 237 |
+ for _, task := range tasks {
|
|
| 238 |
+ node := daemons[0].GetNode(c, task.NodeID) |
|
| 239 |
+ c.Assert(node.Spec.Role, checker.Equals, swarm.NodeRoleWorker) |
|
| 240 |
+ } |
|
| 241 |
+ //remove service |
|
| 242 |
+ daemons[0].RemoveService(c, id) |
|
| 243 |
+ |
|
| 244 |
+ // create service |
|
| 245 |
+ constraints = []string{"node.role!=worker"}
|
|
| 246 |
+ id = daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances)) |
|
| 247 |
+ // wait for tasks ready |
|
| 248 |
+ waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceRunningTasks(id), checker.Equals, instances) |
|
| 249 |
+ tasks = daemons[0].GetServiceTasks(c, id) |
|
| 250 |
+ // validate tasks are running on manager nodes |
|
| 251 |
+ for _, task := range tasks {
|
|
| 252 |
+ node := daemons[0].GetNode(c, task.NodeID) |
|
| 253 |
+ c.Assert(node.Spec.Role, checker.Equals, swarm.NodeRoleManager) |
|
| 254 |
+ } |
|
| 255 |
+ //remove service |
|
| 256 |
+ daemons[0].RemoveService(c, id) |
|
| 257 |
+ |
|
| 258 |
+ // create service |
|
| 259 |
+ constraints = []string{"node.role==nosuchrole"}
|
|
| 260 |
+ id = daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances)) |
|
| 261 |
+ // wait for tasks created |
|
| 262 |
+ waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceTasks(id), checker.Equals, instances) |
|
| 263 |
+ // let scheduler try |
|
| 264 |
+ time.Sleep(250 * time.Millisecond) |
|
| 265 |
+ // validate tasks are not assigned to any node |
|
| 266 |
+ tasks = daemons[0].GetServiceTasks(c, id) |
|
| 267 |
+ for _, task := range tasks {
|
|
| 268 |
+ c.Assert(task.NodeID, checker.Equals, "") |
|
| 269 |
+ } |
|
| 270 |
+} |
|
| 271 |
+ |
|
| 272 |
+func (s *DockerSwarmSuite) TestAPISwarmServiceConstraintLabel(c *check.C) {
|
|
| 273 |
+ const nodeCount = 3 |
|
| 274 |
+ var daemons [nodeCount]*daemon.Swarm |
|
| 275 |
+ for i := 0; i < nodeCount; i++ {
|
|
| 276 |
+ daemons[i] = s.AddDaemon(c, true, i == 0) |
|
| 277 |
+ } |
|
| 278 |
+ // wait for nodes ready |
|
| 279 |
+ waitAndAssert(c, 5*time.Second, daemons[0].CheckNodeReadyCount, checker.Equals, nodeCount) |
|
| 280 |
+ nodes := daemons[0].ListNodes(c) |
|
| 281 |
+ c.Assert(len(nodes), checker.Equals, nodeCount) |
|
| 282 |
+ |
|
| 283 |
+ // add labels to nodes |
|
| 284 |
+ daemons[0].UpdateNode(c, nodes[0].ID, func(n *swarm.Node) {
|
|
| 285 |
+ n.Spec.Annotations.Labels = map[string]string{
|
|
| 286 |
+ "security": "high", |
|
| 287 |
+ } |
|
| 288 |
+ }) |
|
| 289 |
+ for i := 1; i < nodeCount; i++ {
|
|
| 290 |
+ daemons[0].UpdateNode(c, nodes[i].ID, func(n *swarm.Node) {
|
|
| 291 |
+ n.Spec.Annotations.Labels = map[string]string{
|
|
| 292 |
+ "security": "low", |
|
| 293 |
+ } |
|
| 294 |
+ }) |
|
| 295 |
+ } |
|
| 296 |
+ |
|
| 297 |
+ // create service |
|
| 298 |
+ instances := 3 |
|
| 299 |
+ constraints := []string{"node.labels.security==high"}
|
|
| 300 |
+ id := daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances)) |
|
| 301 |
+ // wait for tasks ready |
|
| 302 |
+ waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceRunningTasks(id), checker.Equals, instances) |
|
| 303 |
+ tasks := daemons[0].GetServiceTasks(c, id) |
|
| 304 |
+ // validate all tasks are running on nodes[0] |
|
| 305 |
+ for _, task := range tasks {
|
|
| 306 |
+ c.Assert(task.NodeID, checker.Equals, nodes[0].ID) |
|
| 307 |
+ } |
|
| 308 |
+ //remove service |
|
| 309 |
+ daemons[0].RemoveService(c, id) |
|
| 310 |
+ |
|
| 311 |
+ // create service |
|
| 312 |
+ constraints = []string{"node.labels.security!=high"}
|
|
| 313 |
+ id = daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances)) |
|
| 314 |
+ // wait for tasks ready |
|
| 315 |
+ waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceRunningTasks(id), checker.Equals, instances) |
|
| 316 |
+ tasks = daemons[0].GetServiceTasks(c, id) |
|
| 317 |
+ // validate all tasks are NOT running on nodes[0] |
|
| 318 |
+ for _, task := range tasks {
|
|
| 319 |
+ c.Assert(task.NodeID, checker.Not(checker.Equals), nodes[0].ID) |
|
| 320 |
+ } |
|
| 321 |
+ //remove service |
|
| 322 |
+ daemons[0].RemoveService(c, id) |
|
| 323 |
+ |
|
| 324 |
+ constraints = []string{"node.labels.security==medium"}
|
|
| 325 |
+ id = daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances)) |
|
| 326 |
+ // wait for tasks created |
|
| 327 |
+ waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceTasks(id), checker.Equals, instances) |
|
| 328 |
+ // let scheduler try |
|
| 329 |
+ time.Sleep(250 * time.Millisecond) |
|
| 330 |
+ tasks = daemons[0].GetServiceTasks(c, id) |
|
| 331 |
+ // validate tasks are not assigned |
|
| 332 |
+ for _, task := range tasks {
|
|
| 333 |
+ c.Assert(task.NodeID, checker.Equals, "") |
|
| 334 |
+ } |
|
| 335 |
+ //remove service |
|
| 336 |
+ daemons[0].RemoveService(c, id) |
|
| 337 |
+ |
|
| 338 |
+ // multiple constraints |
|
| 339 |
+ constraints = []string{
|
|
| 340 |
+ "node.labels.security==high", |
|
| 341 |
+ fmt.Sprintf("node.id==%s", nodes[1].ID),
|
|
| 342 |
+ } |
|
| 343 |
+ id = daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances)) |
|
| 344 |
+ // wait for tasks created |
|
| 345 |
+ waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceTasks(id), checker.Equals, instances) |
|
| 346 |
+ // let scheduler try |
|
| 347 |
+ time.Sleep(250 * time.Millisecond) |
|
| 348 |
+ tasks = daemons[0].GetServiceTasks(c, id) |
|
| 349 |
+ // validate tasks are not assigned |
|
| 350 |
+ for _, task := range tasks {
|
|
| 351 |
+ c.Assert(task.NodeID, checker.Equals, "") |
|
| 352 |
+ } |
|
| 353 |
+ // make nodes[1] fulfills the constraints |
|
| 354 |
+ daemons[0].UpdateNode(c, nodes[1].ID, func(n *swarm.Node) {
|
|
| 355 |
+ n.Spec.Annotations.Labels = map[string]string{
|
|
| 356 |
+ "security": "high", |
|
| 357 |
+ } |
|
| 358 |
+ }) |
|
| 359 |
+ // wait for tasks ready |
|
| 360 |
+ waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceRunningTasks(id), checker.Equals, instances) |
|
| 361 |
+ tasks = daemons[0].GetServiceTasks(c, id) |
|
| 362 |
+ for _, task := range tasks {
|
|
| 363 |
+ c.Assert(task.NodeID, checker.Equals, nodes[1].ID) |
|
| 364 |
+ } |
|
| 365 |
+} |
|
| 366 |
+ |
|
| 367 |
+func (s *DockerSwarmSuite) TestAPISwarmServicesStateReporting(c *check.C) {
|
|
| 368 |
+ testRequires(c, SameHostDaemon) |
|
| 369 |
+ testRequires(c, DaemonIsLinux) |
|
| 370 |
+ |
|
| 371 |
+ d1 := s.AddDaemon(c, true, true) |
|
| 372 |
+ d2 := s.AddDaemon(c, true, true) |
|
| 373 |
+ d3 := s.AddDaemon(c, true, false) |
|
| 374 |
+ |
|
| 375 |
+ time.Sleep(1 * time.Second) // make sure all daemons are ready to accept |
|
| 376 |
+ |
|
| 377 |
+ instances := 9 |
|
| 378 |
+ d1.CreateService(c, simpleTestService, setInstances(instances)) |
|
| 379 |
+ |
|
| 380 |
+ waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals, instances) |
|
| 381 |
+ |
|
| 382 |
+ getContainers := func() map[string]*daemon.Swarm {
|
|
| 383 |
+ m := make(map[string]*daemon.Swarm) |
|
| 384 |
+ for _, d := range []*daemon.Swarm{d1, d2, d3} {
|
|
| 385 |
+ for _, id := range d.ActiveContainers() {
|
|
| 386 |
+ m[id] = d |
|
| 387 |
+ } |
|
| 388 |
+ } |
|
| 389 |
+ return m |
|
| 390 |
+ } |
|
| 391 |
+ |
|
| 392 |
+ containers := getContainers() |
|
| 393 |
+ c.Assert(containers, checker.HasLen, instances) |
|
| 394 |
+ var toRemove string |
|
| 395 |
+ for i := range containers {
|
|
| 396 |
+ toRemove = i |
|
| 397 |
+ } |
|
| 398 |
+ |
|
| 399 |
+ _, err := containers[toRemove].Cmd("stop", toRemove)
|
|
| 400 |
+ c.Assert(err, checker.IsNil) |
|
| 401 |
+ |
|
| 402 |
+ waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals, instances) |
|
| 403 |
+ |
|
| 404 |
+ containers2 := getContainers() |
|
| 405 |
+ c.Assert(containers2, checker.HasLen, instances) |
|
| 406 |
+ for i := range containers {
|
|
| 407 |
+ if i == toRemove {
|
|
| 408 |
+ c.Assert(containers2[i], checker.IsNil) |
|
| 409 |
+ } else {
|
|
| 410 |
+ c.Assert(containers2[i], checker.NotNil) |
|
| 411 |
+ } |
|
| 412 |
+ } |
|
| 413 |
+ |
|
| 414 |
+ containers = containers2 |
|
| 415 |
+ for i := range containers {
|
|
| 416 |
+ toRemove = i |
|
| 417 |
+ } |
|
| 418 |
+ |
|
| 419 |
+ // try with killing process outside of docker |
|
| 420 |
+ pidStr, err := containers[toRemove].Cmd("inspect", "-f", "{{.State.Pid}}", toRemove)
|
|
| 421 |
+ c.Assert(err, checker.IsNil) |
|
| 422 |
+ pid, err := strconv.Atoi(strings.TrimSpace(pidStr)) |
|
| 423 |
+ c.Assert(err, checker.IsNil) |
|
| 424 |
+ c.Assert(syscall.Kill(pid, syscall.SIGKILL), checker.IsNil) |
|
| 425 |
+ |
|
| 426 |
+ time.Sleep(time.Second) // give some time to handle the signal |
|
| 427 |
+ |
|
| 428 |
+ waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals, instances) |
|
| 429 |
+ |
|
| 430 |
+ containers2 = getContainers() |
|
| 431 |
+ c.Assert(containers2, checker.HasLen, instances) |
|
| 432 |
+ for i := range containers {
|
|
| 433 |
+ if i == toRemove {
|
|
| 434 |
+ c.Assert(containers2[i], checker.IsNil) |
|
| 435 |
+ } else {
|
|
| 436 |
+ c.Assert(containers2[i], checker.NotNil) |
|
| 437 |
+ } |
|
| 438 |
+ } |
|
| 439 |
+} |
| ... | ... |
@@ -9,10 +9,8 @@ import ( |
| 9 | 9 |
"net/http" |
| 10 | 10 |
"os" |
| 11 | 11 |
"path/filepath" |
| 12 |
- "strconv" |
|
| 13 | 12 |
"strings" |
| 14 | 13 |
"sync" |
| 15 |
- "syscall" |
|
| 16 | 14 |
"time" |
| 17 | 15 |
|
| 18 | 16 |
"github.com/docker/docker/api/types" |
| ... | ... |
@@ -199,400 +197,6 @@ func (s *DockerSwarmSuite) TestAPISwarmPromoteDemote(c *check.C) {
|
| 199 | 199 |
waitAndAssert(c, defaultReconciliationTimeout, d2.CheckControlAvailable, checker.True) |
| 200 | 200 |
} |
| 201 | 201 |
|
| 202 |
-func (s *DockerSwarmSuite) TestAPISwarmServicesEmptyList(c *check.C) {
|
|
| 203 |
- d := s.AddDaemon(c, true, true) |
|
| 204 |
- |
|
| 205 |
- services := d.ListServices(c) |
|
| 206 |
- c.Assert(services, checker.NotNil) |
|
| 207 |
- c.Assert(len(services), checker.Equals, 0, check.Commentf("services: %#v", services))
|
|
| 208 |
-} |
|
| 209 |
- |
|
| 210 |
-func (s *DockerSwarmSuite) TestAPISwarmServicesCreate(c *check.C) {
|
|
| 211 |
- d := s.AddDaemon(c, true, true) |
|
| 212 |
- |
|
| 213 |
- instances := 2 |
|
| 214 |
- id := d.CreateService(c, simpleTestService, setInstances(instances)) |
|
| 215 |
- waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances) |
|
| 216 |
- |
|
| 217 |
- service := d.GetService(c, id) |
|
| 218 |
- instances = 5 |
|
| 219 |
- d.UpdateService(c, service, setInstances(instances)) |
|
| 220 |
- waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances) |
|
| 221 |
- |
|
| 222 |
- d.RemoveService(c, service.ID) |
|
| 223 |
- waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 0) |
|
| 224 |
-} |
|
| 225 |
- |
|
| 226 |
-func (s *DockerSwarmSuite) TestAPISwarmServicesMultipleAgents(c *check.C) {
|
|
| 227 |
- d1 := s.AddDaemon(c, true, true) |
|
| 228 |
- d2 := s.AddDaemon(c, true, false) |
|
| 229 |
- d3 := s.AddDaemon(c, true, false) |
|
| 230 |
- |
|
| 231 |
- time.Sleep(1 * time.Second) // make sure all daemons are ready to accept tasks |
|
| 232 |
- |
|
| 233 |
- instances := 9 |
|
| 234 |
- id := d1.CreateService(c, simpleTestService, setInstances(instances)) |
|
| 235 |
- |
|
| 236 |
- waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.GreaterThan, 0) |
|
| 237 |
- waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.GreaterThan, 0) |
|
| 238 |
- waitAndAssert(c, defaultReconciliationTimeout, d3.CheckActiveContainerCount, checker.GreaterThan, 0) |
|
| 239 |
- |
|
| 240 |
- waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals, instances) |
|
| 241 |
- |
|
| 242 |
- // reconciliation on d2 node down |
|
| 243 |
- d2.Stop(c) |
|
| 244 |
- |
|
| 245 |
- waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals, instances) |
|
| 246 |
- |
|
| 247 |
- // test downscaling |
|
| 248 |
- instances = 5 |
|
| 249 |
- d1.UpdateService(c, d1.GetService(c, id), setInstances(instances)) |
|
| 250 |
- waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals, instances) |
|
| 251 |
- |
|
| 252 |
-} |
|
| 253 |
- |
|
| 254 |
-func (s *DockerSwarmSuite) TestAPISwarmServicesCreateGlobal(c *check.C) {
|
|
| 255 |
- d1 := s.AddDaemon(c, true, true) |
|
| 256 |
- d2 := s.AddDaemon(c, true, false) |
|
| 257 |
- d3 := s.AddDaemon(c, true, false) |
|
| 258 |
- |
|
| 259 |
- d1.CreateService(c, simpleTestService, setGlobalMode) |
|
| 260 |
- |
|
| 261 |
- waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.Equals, 1) |
|
| 262 |
- waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.Equals, 1) |
|
| 263 |
- waitAndAssert(c, defaultReconciliationTimeout, d3.CheckActiveContainerCount, checker.Equals, 1) |
|
| 264 |
- |
|
| 265 |
- d4 := s.AddDaemon(c, true, false) |
|
| 266 |
- d5 := s.AddDaemon(c, true, false) |
|
| 267 |
- |
|
| 268 |
- waitAndAssert(c, defaultReconciliationTimeout, d4.CheckActiveContainerCount, checker.Equals, 1) |
|
| 269 |
- waitAndAssert(c, defaultReconciliationTimeout, d5.CheckActiveContainerCount, checker.Equals, 1) |
|
| 270 |
-} |
|
| 271 |
- |
|
| 272 |
-func (s *DockerSwarmSuite) TestAPISwarmServicesUpdate(c *check.C) {
|
|
| 273 |
- const nodeCount = 3 |
|
| 274 |
- var daemons [nodeCount]*daemon.Swarm |
|
| 275 |
- for i := 0; i < nodeCount; i++ {
|
|
| 276 |
- daemons[i] = s.AddDaemon(c, true, i == 0) |
|
| 277 |
- } |
|
| 278 |
- // wait for nodes ready |
|
| 279 |
- waitAndAssert(c, 5*time.Second, daemons[0].CheckNodeReadyCount, checker.Equals, nodeCount) |
|
| 280 |
- |
|
| 281 |
- // service image at start |
|
| 282 |
- image1 := "busybox:latest" |
|
| 283 |
- // target image in update |
|
| 284 |
- image2 := "busybox:test" |
|
| 285 |
- |
|
| 286 |
- // create a different tag |
|
| 287 |
- for _, d := range daemons {
|
|
| 288 |
- out, err := d.Cmd("tag", image1, image2)
|
|
| 289 |
- c.Assert(err, checker.IsNil, check.Commentf(out)) |
|
| 290 |
- } |
|
| 291 |
- |
|
| 292 |
- // create service |
|
| 293 |
- instances := 5 |
|
| 294 |
- parallelism := 2 |
|
| 295 |
- id := daemons[0].CreateService(c, serviceForUpdate, setInstances(instances)) |
|
| 296 |
- |
|
| 297 |
- // wait for tasks ready |
|
| 298 |
- waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals, |
|
| 299 |
- map[string]int{image1: instances})
|
|
| 300 |
- |
|
| 301 |
- // issue service update |
|
| 302 |
- service := daemons[0].GetService(c, id) |
|
| 303 |
- daemons[0].UpdateService(c, service, setImage(image2)) |
|
| 304 |
- |
|
| 305 |
- // first batch |
|
| 306 |
- waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals, |
|
| 307 |
- map[string]int{image1: instances - parallelism, image2: parallelism})
|
|
| 308 |
- |
|
| 309 |
- // 2nd batch |
|
| 310 |
- waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals, |
|
| 311 |
- map[string]int{image1: instances - 2*parallelism, image2: 2 * parallelism})
|
|
| 312 |
- |
|
| 313 |
- // 3nd batch |
|
| 314 |
- waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals, |
|
| 315 |
- map[string]int{image2: instances})
|
|
| 316 |
- |
|
| 317 |
- // Roll back to the previous version. This uses the CLI because |
|
| 318 |
- // rollback is a client-side operation. |
|
| 319 |
- out, err := daemons[0].Cmd("service", "update", "--rollback", id)
|
|
| 320 |
- c.Assert(err, checker.IsNil, check.Commentf(out)) |
|
| 321 |
- |
|
| 322 |
- // first batch |
|
| 323 |
- waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals, |
|
| 324 |
- map[string]int{image2: instances - parallelism, image1: parallelism})
|
|
| 325 |
- |
|
| 326 |
- // 2nd batch |
|
| 327 |
- waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals, |
|
| 328 |
- map[string]int{image2: instances - 2*parallelism, image1: 2 * parallelism})
|
|
| 329 |
- |
|
| 330 |
- // 3nd batch |
|
| 331 |
- waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals, |
|
| 332 |
- map[string]int{image1: instances})
|
|
| 333 |
-} |
|
| 334 |
- |
|
| 335 |
-func (s *DockerSwarmSuite) TestAPISwarmServicesFailedUpdate(c *check.C) {
|
|
| 336 |
- const nodeCount = 3 |
|
| 337 |
- var daemons [nodeCount]*daemon.Swarm |
|
| 338 |
- for i := 0; i < nodeCount; i++ {
|
|
| 339 |
- daemons[i] = s.AddDaemon(c, true, i == 0) |
|
| 340 |
- } |
|
| 341 |
- // wait for nodes ready |
|
| 342 |
- waitAndAssert(c, 5*time.Second, daemons[0].CheckNodeReadyCount, checker.Equals, nodeCount) |
|
| 343 |
- |
|
| 344 |
- // service image at start |
|
| 345 |
- image1 := "busybox:latest" |
|
| 346 |
- // target image in update |
|
| 347 |
- image2 := "busybox:badtag" |
|
| 348 |
- |
|
| 349 |
- // create service |
|
| 350 |
- instances := 5 |
|
| 351 |
- id := daemons[0].CreateService(c, serviceForUpdate, setInstances(instances)) |
|
| 352 |
- |
|
| 353 |
- // wait for tasks ready |
|
| 354 |
- waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals, |
|
| 355 |
- map[string]int{image1: instances})
|
|
| 356 |
- |
|
| 357 |
- // issue service update |
|
| 358 |
- service := daemons[0].GetService(c, id) |
|
| 359 |
- daemons[0].UpdateService(c, service, setImage(image2), setFailureAction(swarm.UpdateFailureActionPause), setMaxFailureRatio(0.25), setParallelism(1)) |
|
| 360 |
- |
|
| 361 |
- // should update 2 tasks and then pause |
|
| 362 |
- waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceUpdateState(id), checker.Equals, swarm.UpdateStatePaused) |
|
| 363 |
- v, _ := daemons[0].CheckServiceRunningTasks(id)(c) |
|
| 364 |
- c.Assert(v, checker.Equals, instances-2) |
|
| 365 |
- |
|
| 366 |
- // Roll back to the previous version. This uses the CLI because |
|
| 367 |
- // rollback is a client-side operation. |
|
| 368 |
- out, err := daemons[0].Cmd("service", "update", "--rollback", id)
|
|
| 369 |
- c.Assert(err, checker.IsNil, check.Commentf(out)) |
|
| 370 |
- |
|
| 371 |
- waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals, |
|
| 372 |
- map[string]int{image1: instances})
|
|
| 373 |
-} |
|
| 374 |
- |
|
| 375 |
-func (s *DockerSwarmSuite) TestAPISwarmServiceConstraintRole(c *check.C) {
|
|
| 376 |
- const nodeCount = 3 |
|
| 377 |
- var daemons [nodeCount]*daemon.Swarm |
|
| 378 |
- for i := 0; i < nodeCount; i++ {
|
|
| 379 |
- daemons[i] = s.AddDaemon(c, true, i == 0) |
|
| 380 |
- } |
|
| 381 |
- // wait for nodes ready |
|
| 382 |
- waitAndAssert(c, 5*time.Second, daemons[0].CheckNodeReadyCount, checker.Equals, nodeCount) |
|
| 383 |
- |
|
| 384 |
- // create service |
|
| 385 |
- constraints := []string{"node.role==worker"}
|
|
| 386 |
- instances := 3 |
|
| 387 |
- id := daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances)) |
|
| 388 |
- // wait for tasks ready |
|
| 389 |
- waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceRunningTasks(id), checker.Equals, instances) |
|
| 390 |
- // validate tasks are running on worker nodes |
|
| 391 |
- tasks := daemons[0].GetServiceTasks(c, id) |
|
| 392 |
- for _, task := range tasks {
|
|
| 393 |
- node := daemons[0].GetNode(c, task.NodeID) |
|
| 394 |
- c.Assert(node.Spec.Role, checker.Equals, swarm.NodeRoleWorker) |
|
| 395 |
- } |
|
| 396 |
- //remove service |
|
| 397 |
- daemons[0].RemoveService(c, id) |
|
| 398 |
- |
|
| 399 |
- // create service |
|
| 400 |
- constraints = []string{"node.role!=worker"}
|
|
| 401 |
- id = daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances)) |
|
| 402 |
- // wait for tasks ready |
|
| 403 |
- waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceRunningTasks(id), checker.Equals, instances) |
|
| 404 |
- tasks = daemons[0].GetServiceTasks(c, id) |
|
| 405 |
- // validate tasks are running on manager nodes |
|
| 406 |
- for _, task := range tasks {
|
|
| 407 |
- node := daemons[0].GetNode(c, task.NodeID) |
|
| 408 |
- c.Assert(node.Spec.Role, checker.Equals, swarm.NodeRoleManager) |
|
| 409 |
- } |
|
| 410 |
- //remove service |
|
| 411 |
- daemons[0].RemoveService(c, id) |
|
| 412 |
- |
|
| 413 |
- // create service |
|
| 414 |
- constraints = []string{"node.role==nosuchrole"}
|
|
| 415 |
- id = daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances)) |
|
| 416 |
- // wait for tasks created |
|
| 417 |
- waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceTasks(id), checker.Equals, instances) |
|
| 418 |
- // let scheduler try |
|
| 419 |
- time.Sleep(250 * time.Millisecond) |
|
| 420 |
- // validate tasks are not assigned to any node |
|
| 421 |
- tasks = daemons[0].GetServiceTasks(c, id) |
|
| 422 |
- for _, task := range tasks {
|
|
| 423 |
- c.Assert(task.NodeID, checker.Equals, "") |
|
| 424 |
- } |
|
| 425 |
-} |
|
| 426 |
- |
|
| 427 |
-func (s *DockerSwarmSuite) TestAPISwarmServiceConstraintLabel(c *check.C) {
|
|
| 428 |
- const nodeCount = 3 |
|
| 429 |
- var daemons [nodeCount]*daemon.Swarm |
|
| 430 |
- for i := 0; i < nodeCount; i++ {
|
|
| 431 |
- daemons[i] = s.AddDaemon(c, true, i == 0) |
|
| 432 |
- } |
|
| 433 |
- // wait for nodes ready |
|
| 434 |
- waitAndAssert(c, 5*time.Second, daemons[0].CheckNodeReadyCount, checker.Equals, nodeCount) |
|
| 435 |
- nodes := daemons[0].ListNodes(c) |
|
| 436 |
- c.Assert(len(nodes), checker.Equals, nodeCount) |
|
| 437 |
- |
|
| 438 |
- // add labels to nodes |
|
| 439 |
- daemons[0].UpdateNode(c, nodes[0].ID, func(n *swarm.Node) {
|
|
| 440 |
- n.Spec.Annotations.Labels = map[string]string{
|
|
| 441 |
- "security": "high", |
|
| 442 |
- } |
|
| 443 |
- }) |
|
| 444 |
- for i := 1; i < nodeCount; i++ {
|
|
| 445 |
- daemons[0].UpdateNode(c, nodes[i].ID, func(n *swarm.Node) {
|
|
| 446 |
- n.Spec.Annotations.Labels = map[string]string{
|
|
| 447 |
- "security": "low", |
|
| 448 |
- } |
|
| 449 |
- }) |
|
| 450 |
- } |
|
| 451 |
- |
|
| 452 |
- // create service |
|
| 453 |
- instances := 3 |
|
| 454 |
- constraints := []string{"node.labels.security==high"}
|
|
| 455 |
- id := daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances)) |
|
| 456 |
- // wait for tasks ready |
|
| 457 |
- waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceRunningTasks(id), checker.Equals, instances) |
|
| 458 |
- tasks := daemons[0].GetServiceTasks(c, id) |
|
| 459 |
- // validate all tasks are running on nodes[0] |
|
| 460 |
- for _, task := range tasks {
|
|
| 461 |
- c.Assert(task.NodeID, checker.Equals, nodes[0].ID) |
|
| 462 |
- } |
|
| 463 |
- //remove service |
|
| 464 |
- daemons[0].RemoveService(c, id) |
|
| 465 |
- |
|
| 466 |
- // create service |
|
| 467 |
- constraints = []string{"node.labels.security!=high"}
|
|
| 468 |
- id = daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances)) |
|
| 469 |
- // wait for tasks ready |
|
| 470 |
- waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceRunningTasks(id), checker.Equals, instances) |
|
| 471 |
- tasks = daemons[0].GetServiceTasks(c, id) |
|
| 472 |
- // validate all tasks are NOT running on nodes[0] |
|
| 473 |
- for _, task := range tasks {
|
|
| 474 |
- c.Assert(task.NodeID, checker.Not(checker.Equals), nodes[0].ID) |
|
| 475 |
- } |
|
| 476 |
- //remove service |
|
| 477 |
- daemons[0].RemoveService(c, id) |
|
| 478 |
- |
|
| 479 |
- constraints = []string{"node.labels.security==medium"}
|
|
| 480 |
- id = daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances)) |
|
| 481 |
- // wait for tasks created |
|
| 482 |
- waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceTasks(id), checker.Equals, instances) |
|
| 483 |
- // let scheduler try |
|
| 484 |
- time.Sleep(250 * time.Millisecond) |
|
| 485 |
- tasks = daemons[0].GetServiceTasks(c, id) |
|
| 486 |
- // validate tasks are not assigned |
|
| 487 |
- for _, task := range tasks {
|
|
| 488 |
- c.Assert(task.NodeID, checker.Equals, "") |
|
| 489 |
- } |
|
| 490 |
- //remove service |
|
| 491 |
- daemons[0].RemoveService(c, id) |
|
| 492 |
- |
|
| 493 |
- // multiple constraints |
|
| 494 |
- constraints = []string{
|
|
| 495 |
- "node.labels.security==high", |
|
| 496 |
- fmt.Sprintf("node.id==%s", nodes[1].ID),
|
|
| 497 |
- } |
|
| 498 |
- id = daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances)) |
|
| 499 |
- // wait for tasks created |
|
| 500 |
- waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceTasks(id), checker.Equals, instances) |
|
| 501 |
- // let scheduler try |
|
| 502 |
- time.Sleep(250 * time.Millisecond) |
|
| 503 |
- tasks = daemons[0].GetServiceTasks(c, id) |
|
| 504 |
- // validate tasks are not assigned |
|
| 505 |
- for _, task := range tasks {
|
|
| 506 |
- c.Assert(task.NodeID, checker.Equals, "") |
|
| 507 |
- } |
|
| 508 |
- // make nodes[1] fulfills the constraints |
|
| 509 |
- daemons[0].UpdateNode(c, nodes[1].ID, func(n *swarm.Node) {
|
|
| 510 |
- n.Spec.Annotations.Labels = map[string]string{
|
|
| 511 |
- "security": "high", |
|
| 512 |
- } |
|
| 513 |
- }) |
|
| 514 |
- // wait for tasks ready |
|
| 515 |
- waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceRunningTasks(id), checker.Equals, instances) |
|
| 516 |
- tasks = daemons[0].GetServiceTasks(c, id) |
|
| 517 |
- for _, task := range tasks {
|
|
| 518 |
- c.Assert(task.NodeID, checker.Equals, nodes[1].ID) |
|
| 519 |
- } |
|
| 520 |
-} |
|
| 521 |
- |
|
| 522 |
-func (s *DockerSwarmSuite) TestAPISwarmServicesStateReporting(c *check.C) {
|
|
| 523 |
- testRequires(c, SameHostDaemon) |
|
| 524 |
- testRequires(c, DaemonIsLinux) |
|
| 525 |
- |
|
| 526 |
- d1 := s.AddDaemon(c, true, true) |
|
| 527 |
- d2 := s.AddDaemon(c, true, true) |
|
| 528 |
- d3 := s.AddDaemon(c, true, false) |
|
| 529 |
- |
|
| 530 |
- time.Sleep(1 * time.Second) // make sure all daemons are ready to accept |
|
| 531 |
- |
|
| 532 |
- instances := 9 |
|
| 533 |
- d1.CreateService(c, simpleTestService, setInstances(instances)) |
|
| 534 |
- |
|
| 535 |
- waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals, instances) |
|
| 536 |
- |
|
| 537 |
- getContainers := func() map[string]*daemon.Swarm {
|
|
| 538 |
- m := make(map[string]*daemon.Swarm) |
|
| 539 |
- for _, d := range []*daemon.Swarm{d1, d2, d3} {
|
|
| 540 |
- for _, id := range d.ActiveContainers() {
|
|
| 541 |
- m[id] = d |
|
| 542 |
- } |
|
| 543 |
- } |
|
| 544 |
- return m |
|
| 545 |
- } |
|
| 546 |
- |
|
| 547 |
- containers := getContainers() |
|
| 548 |
- c.Assert(containers, checker.HasLen, instances) |
|
| 549 |
- var toRemove string |
|
| 550 |
- for i := range containers {
|
|
| 551 |
- toRemove = i |
|
| 552 |
- } |
|
| 553 |
- |
|
| 554 |
- _, err := containers[toRemove].Cmd("stop", toRemove)
|
|
| 555 |
- c.Assert(err, checker.IsNil) |
|
| 556 |
- |
|
| 557 |
- waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals, instances) |
|
| 558 |
- |
|
| 559 |
- containers2 := getContainers() |
|
| 560 |
- c.Assert(containers2, checker.HasLen, instances) |
|
| 561 |
- for i := range containers {
|
|
| 562 |
- if i == toRemove {
|
|
| 563 |
- c.Assert(containers2[i], checker.IsNil) |
|
| 564 |
- } else {
|
|
| 565 |
- c.Assert(containers2[i], checker.NotNil) |
|
| 566 |
- } |
|
| 567 |
- } |
|
| 568 |
- |
|
| 569 |
- containers = containers2 |
|
| 570 |
- for i := range containers {
|
|
| 571 |
- toRemove = i |
|
| 572 |
- } |
|
| 573 |
- |
|
| 574 |
- // try with killing process outside of docker |
|
| 575 |
- pidStr, err := containers[toRemove].Cmd("inspect", "-f", "{{.State.Pid}}", toRemove)
|
|
| 576 |
- c.Assert(err, checker.IsNil) |
|
| 577 |
- pid, err := strconv.Atoi(strings.TrimSpace(pidStr)) |
|
| 578 |
- c.Assert(err, checker.IsNil) |
|
| 579 |
- c.Assert(syscall.Kill(pid, syscall.SIGKILL), checker.IsNil) |
|
| 580 |
- |
|
| 581 |
- time.Sleep(time.Second) // give some time to handle the signal |
|
| 582 |
- |
|
| 583 |
- waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals, instances) |
|
| 584 |
- |
|
| 585 |
- containers2 = getContainers() |
|
| 586 |
- c.Assert(containers2, checker.HasLen, instances) |
|
| 587 |
- for i := range containers {
|
|
| 588 |
- if i == toRemove {
|
|
| 589 |
- c.Assert(containers2[i], checker.IsNil) |
|
| 590 |
- } else {
|
|
| 591 |
- c.Assert(containers2[i], checker.NotNil) |
|
| 592 |
- } |
|
| 593 |
- } |
|
| 594 |
-} |
|
| 595 |
- |
|
| 596 | 202 |
func (s *DockerSwarmSuite) TestAPISwarmLeaderProxy(c *check.C) {
|
| 597 | 203 |
// add three managers, one of these is leader |
| 598 | 204 |
d1 := s.AddDaemon(c, true, true) |
| ... | ... |
@@ -719,122 +323,6 @@ func (s *DockerSwarmSuite) TestAPISwarmRaftQuorum(c *check.C) {
|
| 719 | 719 |
}) |
| 720 | 720 |
} |
| 721 | 721 |
|
| 722 |
-func (s *DockerSwarmSuite) TestAPISwarmListNodes(c *check.C) {
|
|
| 723 |
- d1 := s.AddDaemon(c, true, true) |
|
| 724 |
- d2 := s.AddDaemon(c, true, false) |
|
| 725 |
- d3 := s.AddDaemon(c, true, false) |
|
| 726 |
- |
|
| 727 |
- nodes := d1.ListNodes(c) |
|
| 728 |
- c.Assert(len(nodes), checker.Equals, 3, check.Commentf("nodes: %#v", nodes))
|
|
| 729 |
- |
|
| 730 |
-loop0: |
|
| 731 |
- for _, n := range nodes {
|
|
| 732 |
- for _, d := range []*daemon.Swarm{d1, d2, d3} {
|
|
| 733 |
- if n.ID == d.NodeID {
|
|
| 734 |
- continue loop0 |
|
| 735 |
- } |
|
| 736 |
- } |
|
| 737 |
- c.Errorf("unknown nodeID %v", n.ID)
|
|
| 738 |
- } |
|
| 739 |
-} |
|
| 740 |
- |
|
| 741 |
-func (s *DockerSwarmSuite) TestAPISwarmNodeUpdate(c *check.C) {
|
|
| 742 |
- d := s.AddDaemon(c, true, true) |
|
| 743 |
- |
|
| 744 |
- nodes := d.ListNodes(c) |
|
| 745 |
- |
|
| 746 |
- d.UpdateNode(c, nodes[0].ID, func(n *swarm.Node) {
|
|
| 747 |
- n.Spec.Availability = swarm.NodeAvailabilityPause |
|
| 748 |
- }) |
|
| 749 |
- |
|
| 750 |
- n := d.GetNode(c, nodes[0].ID) |
|
| 751 |
- c.Assert(n.Spec.Availability, checker.Equals, swarm.NodeAvailabilityPause) |
|
| 752 |
-} |
|
| 753 |
- |
|
| 754 |
-func (s *DockerSwarmSuite) TestAPISwarmNodeRemove(c *check.C) {
|
|
| 755 |
- testRequires(c, Network) |
|
| 756 |
- d1 := s.AddDaemon(c, true, true) |
|
| 757 |
- d2 := s.AddDaemon(c, true, false) |
|
| 758 |
- _ = s.AddDaemon(c, true, false) |
|
| 759 |
- |
|
| 760 |
- nodes := d1.ListNodes(c) |
|
| 761 |
- c.Assert(len(nodes), checker.Equals, 3, check.Commentf("nodes: %#v", nodes))
|
|
| 762 |
- |
|
| 763 |
- // Getting the info so we can take the NodeID |
|
| 764 |
- d2Info, err := d2.SwarmInfo() |
|
| 765 |
- c.Assert(err, checker.IsNil) |
|
| 766 |
- |
|
| 767 |
- // forceful removal of d2 should work |
|
| 768 |
- d1.RemoveNode(c, d2Info.NodeID, true) |
|
| 769 |
- |
|
| 770 |
- nodes = d1.ListNodes(c) |
|
| 771 |
- c.Assert(len(nodes), checker.Equals, 2, check.Commentf("nodes: %#v", nodes))
|
|
| 772 |
- |
|
| 773 |
- // Restart the node that was removed |
|
| 774 |
- d2.Restart(c) |
|
| 775 |
- |
|
| 776 |
- // Give some time for the node to rejoin |
|
| 777 |
- time.Sleep(1 * time.Second) |
|
| 778 |
- |
|
| 779 |
- // Make sure the node didn't rejoin |
|
| 780 |
- nodes = d1.ListNodes(c) |
|
| 781 |
- c.Assert(len(nodes), checker.Equals, 2, check.Commentf("nodes: %#v", nodes))
|
|
| 782 |
-} |
|
| 783 |
- |
|
| 784 |
-func (s *DockerSwarmSuite) TestAPISwarmNodeDrainPause(c *check.C) {
|
|
| 785 |
- d1 := s.AddDaemon(c, true, true) |
|
| 786 |
- d2 := s.AddDaemon(c, true, false) |
|
| 787 |
- |
|
| 788 |
- time.Sleep(1 * time.Second) // make sure all daemons are ready to accept tasks |
|
| 789 |
- |
|
| 790 |
- // start a service, expect balanced distribution |
|
| 791 |
- instances := 8 |
|
| 792 |
- id := d1.CreateService(c, simpleTestService, setInstances(instances)) |
|
| 793 |
- |
|
| 794 |
- waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.GreaterThan, 0) |
|
| 795 |
- waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.GreaterThan, 0) |
|
| 796 |
- waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals, instances) |
|
| 797 |
- |
|
| 798 |
- // drain d2, all containers should move to d1 |
|
| 799 |
- d1.UpdateNode(c, d2.NodeID, func(n *swarm.Node) {
|
|
| 800 |
- n.Spec.Availability = swarm.NodeAvailabilityDrain |
|
| 801 |
- }) |
|
| 802 |
- waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.Equals, instances) |
|
| 803 |
- waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.Equals, 0) |
|
| 804 |
- |
|
| 805 |
- // set d2 back to active |
|
| 806 |
- d1.UpdateNode(c, d2.NodeID, func(n *swarm.Node) {
|
|
| 807 |
- n.Spec.Availability = swarm.NodeAvailabilityActive |
|
| 808 |
- }) |
|
| 809 |
- |
|
| 810 |
- instances = 1 |
|
| 811 |
- d1.UpdateService(c, d1.GetService(c, id), setInstances(instances)) |
|
| 812 |
- |
|
| 813 |
- waitAndAssert(c, defaultReconciliationTimeout*2, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals, instances) |
|
| 814 |
- |
|
| 815 |
- instances = 8 |
|
| 816 |
- d1.UpdateService(c, d1.GetService(c, id), setInstances(instances)) |
|
| 817 |
- |
|
| 818 |
- // drained node first so we don't get any old containers |
|
| 819 |
- waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.GreaterThan, 0) |
|
| 820 |
- waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.GreaterThan, 0) |
|
| 821 |
- waitAndAssert(c, defaultReconciliationTimeout*2, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals, instances) |
|
| 822 |
- |
|
| 823 |
- d2ContainerCount := len(d2.ActiveContainers()) |
|
| 824 |
- |
|
| 825 |
- // set d2 to paused, scale service up, only d1 gets new tasks |
|
| 826 |
- d1.UpdateNode(c, d2.NodeID, func(n *swarm.Node) {
|
|
| 827 |
- n.Spec.Availability = swarm.NodeAvailabilityPause |
|
| 828 |
- }) |
|
| 829 |
- |
|
| 830 |
- instances = 14 |
|
| 831 |
- d1.UpdateService(c, d1.GetService(c, id), setInstances(instances)) |
|
| 832 |
- |
|
| 833 |
- waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.Equals, instances-d2ContainerCount) |
|
| 834 |
- waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.Equals, d2ContainerCount) |
|
| 835 |
- |
|
| 836 |
-} |
|
| 837 |
- |
|
| 838 | 722 |
func (s *DockerSwarmSuite) TestAPISwarmLeaveRemovesContainer(c *check.C) {
|
| 839 | 723 |
d := s.AddDaemon(c, true, true) |
| 840 | 724 |
|
| ... | ... |
@@ -1267,53 +755,6 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesUpdateWithName(c *check.C) {
|
| 1267 | 1267 |
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances) |
| 1268 | 1268 |
} |
| 1269 | 1269 |
|
| 1270 |
-func (s *DockerSwarmSuite) TestAPISwarmSecretsEmptyList(c *check.C) {
|
|
| 1271 |
- d := s.AddDaemon(c, true, true) |
|
| 1272 |
- |
|
| 1273 |
- secrets := d.ListSecrets(c) |
|
| 1274 |
- c.Assert(secrets, checker.NotNil) |
|
| 1275 |
- c.Assert(len(secrets), checker.Equals, 0, check.Commentf("secrets: %#v", secrets))
|
|
| 1276 |
-} |
|
| 1277 |
- |
|
| 1278 |
-func (s *DockerSwarmSuite) TestAPISwarmSecretsCreate(c *check.C) {
|
|
| 1279 |
- d := s.AddDaemon(c, true, true) |
|
| 1280 |
- |
|
| 1281 |
- testName := "test_secret" |
|
| 1282 |
- id := d.CreateSecret(c, swarm.SecretSpec{
|
|
| 1283 |
- swarm.Annotations{
|
|
| 1284 |
- Name: testName, |
|
| 1285 |
- }, |
|
| 1286 |
- []byte("TESTINGDATA"),
|
|
| 1287 |
- }) |
|
| 1288 |
- c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("secrets: %s", id))
|
|
| 1289 |
- |
|
| 1290 |
- secrets := d.ListSecrets(c) |
|
| 1291 |
- c.Assert(len(secrets), checker.Equals, 1, check.Commentf("secrets: %#v", secrets))
|
|
| 1292 |
- name := secrets[0].Spec.Annotations.Name |
|
| 1293 |
- c.Assert(name, checker.Equals, testName, check.Commentf("secret: %s", name))
|
|
| 1294 |
-} |
|
| 1295 |
- |
|
| 1296 |
-func (s *DockerSwarmSuite) TestAPISwarmSecretsDelete(c *check.C) {
|
|
| 1297 |
- d := s.AddDaemon(c, true, true) |
|
| 1298 |
- |
|
| 1299 |
- testName := "test_secret" |
|
| 1300 |
- id := d.CreateSecret(c, swarm.SecretSpec{
|
|
| 1301 |
- swarm.Annotations{
|
|
| 1302 |
- Name: testName, |
|
| 1303 |
- }, |
|
| 1304 |
- []byte("TESTINGDATA"),
|
|
| 1305 |
- }) |
|
| 1306 |
- c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("secrets: %s", id))
|
|
| 1307 |
- |
|
| 1308 |
- secret := d.GetSecret(c, id) |
|
| 1309 |
- c.Assert(secret.ID, checker.Equals, id, check.Commentf("secret: %v", secret))
|
|
| 1310 |
- |
|
| 1311 |
- d.DeleteSecret(c, secret.ID) |
|
| 1312 |
- status, out, err := d.SockRequest("GET", "/secrets/"+id, nil)
|
|
| 1313 |
- c.Assert(err, checker.IsNil) |
|
| 1314 |
- c.Assert(status, checker.Equals, http.StatusNotFound, check.Commentf("secret delete: %s", string(out)))
|
|
| 1315 |
-} |
|
| 1316 |
- |
|
| 1317 | 1270 |
// Unlocking an unlocked swarm results in an error |
| 1318 | 1271 |
func (s *DockerSwarmSuite) TestAPISwarmUnlockNotLocked(c *check.C) {
|
| 1319 | 1272 |
d := s.AddDaemon(c, true, true) |