github.com/noxiouz/docker@v0.7.3-0.20160629055221-3d231c78e8c5/integration-cli/docker_api_swarm_test.go (about) 1 // +build !windows 2 3 package main 4 5 import ( 6 "net/http" 7 "strconv" 8 "strings" 9 "syscall" 10 "time" 11 12 "github.com/docker/docker/pkg/integration/checker" 13 "github.com/docker/engine-api/types/swarm" 14 "github.com/go-check/check" 15 ) 16 17 var defaultReconciliationTimeout = 30 * time.Second 18 19 func (s *DockerSwarmSuite) TestApiSwarmInit(c *check.C) { 20 // todo: should find a better way to verify that components are running than /info 21 d1 := s.AddDaemon(c, true, true) 22 info, err := d1.info() 23 c.Assert(err, checker.IsNil) 24 c.Assert(info.ControlAvailable, checker.Equals, true) 25 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) 26 27 d2 := s.AddDaemon(c, true, false) 28 info, err = d2.info() 29 c.Assert(err, checker.IsNil) 30 c.Assert(info.ControlAvailable, checker.Equals, false) 31 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) 32 33 // Leaving cluster 34 c.Assert(d2.Leave(false), checker.IsNil) 35 36 info, err = d2.info() 37 c.Assert(err, checker.IsNil) 38 c.Assert(info.ControlAvailable, checker.Equals, false) 39 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive) 40 41 c.Assert(d2.Join(d1.listenAddr, "", "", false), checker.IsNil) 42 43 info, err = d2.info() 44 c.Assert(err, checker.IsNil) 45 c.Assert(info.ControlAvailable, checker.Equals, false) 46 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) 47 48 // Current state restoring after restarts 49 err = d1.Stop() 50 c.Assert(err, checker.IsNil) 51 err = d2.Stop() 52 c.Assert(err, checker.IsNil) 53 54 err = d1.Start() 55 c.Assert(err, checker.IsNil) 56 err = d2.Start() 57 c.Assert(err, checker.IsNil) 58 59 info, err = d1.info() 60 c.Assert(err, checker.IsNil) 61 c.Assert(info.ControlAvailable, checker.Equals, true) 62 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) 63 64 info, err = d2.info() 65 c.Assert(err, checker.IsNil) 66 c.Assert(info.ControlAvailable, checker.Equals, false) 67 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) 68 } 69 70 func (s *DockerSwarmSuite) TestApiSwarmManualAcceptance(c *check.C) { 71 s.testAPISwarmManualAcceptance(c, "") 72 } 73 func (s *DockerSwarmSuite) TestApiSwarmManualAcceptanceSecret(c *check.C) { 74 s.testAPISwarmManualAcceptance(c, "foobaz") 75 } 76 77 func (s *DockerSwarmSuite) testAPISwarmManualAcceptance(c *check.C, secret string) { 78 d1 := s.AddDaemon(c, false, false) 79 c.Assert(d1.Init(map[string]bool{}, secret), checker.IsNil) 80 81 d2 := s.AddDaemon(c, false, false) 82 err := d2.Join(d1.listenAddr, "", "", false) 83 c.Assert(err, checker.NotNil) 84 if secret == "" { 85 c.Assert(err.Error(), checker.Contains, "needs to be accepted") 86 info, err := d2.info() 87 c.Assert(err, checker.IsNil) 88 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStatePending) 89 c.Assert(d2.Leave(false), checker.IsNil) 90 info, err = d2.info() 91 c.Assert(err, checker.IsNil) 92 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive) 93 } else { 94 c.Assert(err.Error(), checker.Contains, "valid secret token is necessary") 95 info, err := d2.info() 96 c.Assert(err, checker.IsNil) 97 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive) 98 } 99 d3 := s.AddDaemon(c, false, false) 100 c.Assert(d3.Join(d1.listenAddr, secret, "", false), checker.NotNil) 101 info, err := d3.info() 102 c.Assert(err, checker.IsNil) 103 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStatePending) 104 c.Assert(len(info.NodeID), checker.GreaterThan, 5) 105 d1.updateNode(c, info.NodeID, func(n *swarm.Node) { 106 n.Spec.Membership = swarm.NodeMembershipAccepted 107 }) 108 for i := 0; ; i++ { 109 info, err := d3.info() 110 c.Assert(err, checker.IsNil) 111 if info.LocalNodeState == swarm.LocalNodeStateActive { 112 break 113 } 114 if i > 100 { 115 c.Fatalf("node did not become active") 116 } 117 time.Sleep(200 * time.Millisecond) 118 } 119 } 120 121 func (s *DockerSwarmSuite) TestApiSwarmSecretAcceptance(c *check.C) { 122 d1 := s.AddDaemon(c, false, false) 123 aa := make(map[string]bool) 124 aa["worker"] = true 125 c.Assert(d1.Init(aa, "foobar"), checker.IsNil) 126 127 d2 := s.AddDaemon(c, false, false) 128 err := d2.Join(d1.listenAddr, "", "", false) 129 c.Assert(err, checker.NotNil) 130 c.Assert(err.Error(), checker.Contains, "secret token is necessary") 131 info, err := d2.info() 132 c.Assert(err, checker.IsNil) 133 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive) 134 135 err = d2.Join(d1.listenAddr, "foobaz", "", false) 136 c.Assert(err, checker.NotNil) 137 c.Assert(err.Error(), checker.Contains, "secret token is necessary") 138 info, err = d2.info() 139 c.Assert(err, checker.IsNil) 140 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive) 141 142 c.Assert(d2.Join(d1.listenAddr, "foobar", "", false), checker.IsNil) 143 info, err = d2.info() 144 c.Assert(err, checker.IsNil) 145 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) 146 c.Assert(d2.Leave(false), checker.IsNil) 147 info, err = d2.info() 148 c.Assert(err, checker.IsNil) 149 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive) 150 151 // change secret 152 d1.updateSwarm(c, func(s *swarm.Spec) { 153 for i := range s.AcceptancePolicy.Policies { 154 p := "foobaz" 155 s.AcceptancePolicy.Policies[i].Secret = &p 156 } 157 }) 158 159 err = d2.Join(d1.listenAddr, "foobar", "", false) 160 c.Assert(err, checker.NotNil) 161 c.Assert(err.Error(), checker.Contains, "secret token is necessary") 162 info, err = d2.info() 163 c.Assert(err, checker.IsNil) 164 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive) 165 166 c.Assert(d2.Join(d1.listenAddr, "foobaz", "", false), checker.IsNil) 167 info, err = d2.info() 168 c.Assert(err, checker.IsNil) 169 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) 170 c.Assert(d2.Leave(false), checker.IsNil) 171 info, err = d2.info() 172 c.Assert(err, checker.IsNil) 173 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive) 174 175 // change policy, don't change secret 176 d1.updateSwarm(c, func(s *swarm.Spec) { 177 for i, p := range s.AcceptancePolicy.Policies { 178 if p.Role == swarm.NodeRoleManager { 179 s.AcceptancePolicy.Policies[i].Autoaccept = false 180 } 181 s.AcceptancePolicy.Policies[i].Secret = nil 182 } 183 }) 184 185 err = d2.Join(d1.listenAddr, "", "", false) 186 c.Assert(err, checker.NotNil) 187 c.Assert(err.Error(), checker.Contains, "secret token is necessary") 188 info, err = d2.info() 189 c.Assert(err, checker.IsNil) 190 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive) 191 192 c.Assert(d2.Join(d1.listenAddr, "foobaz", "", false), checker.IsNil) 193 info, err = d2.info() 194 c.Assert(err, checker.IsNil) 195 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) 196 c.Assert(d2.Leave(false), checker.IsNil) 197 info, err = d2.info() 198 c.Assert(err, checker.IsNil) 199 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive) 200 201 // clear secret 202 d1.updateSwarm(c, func(s *swarm.Spec) { 203 for i := range s.AcceptancePolicy.Policies { 204 p := "" 205 s.AcceptancePolicy.Policies[i].Secret = &p 206 } 207 }) 208 209 c.Assert(d2.Join(d1.listenAddr, "", "", false), checker.IsNil) 210 info, err = d2.info() 211 c.Assert(err, checker.IsNil) 212 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) 213 c.Assert(d2.Leave(false), checker.IsNil) 214 info, err = d2.info() 215 c.Assert(err, checker.IsNil) 216 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive) 217 218 } 219 220 func (s *DockerSwarmSuite) TestApiSwarmCAHash(c *check.C) { 221 d1 := s.AddDaemon(c, true, true) 222 d2 := s.AddDaemon(c, false, false) 223 err := d2.Join(d1.listenAddr, "", "foobar", false) 224 c.Assert(err, checker.NotNil) 225 c.Assert(err.Error(), checker.Contains, "invalid checksum digest format") 226 227 c.Assert(len(d1.CACertHash), checker.GreaterThan, 0) 228 c.Assert(d2.Join(d1.listenAddr, "", d1.CACertHash, false), checker.IsNil) 229 } 230 231 func (s *DockerSwarmSuite) TestApiSwarmPromoteDemote(c *check.C) { 232 d1 := s.AddDaemon(c, false, false) 233 c.Assert(d1.Init(map[string]bool{"worker": true}, ""), checker.IsNil) 234 d2 := s.AddDaemon(c, true, false) 235 236 info, err := d2.info() 237 c.Assert(err, checker.IsNil) 238 c.Assert(info.ControlAvailable, checker.Equals, false) 239 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) 240 241 d1.updateNode(c, d2.NodeID, func(n *swarm.Node) { 242 n.Spec.Role = swarm.NodeRoleManager 243 }) 244 245 for i := 0; ; i++ { 246 info, err := d2.info() 247 c.Assert(err, checker.IsNil) 248 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) 249 if info.ControlAvailable { 250 break 251 } 252 if i > 100 { 253 c.Errorf("node did not turn into manager") 254 } else { 255 break 256 } 257 time.Sleep(100 * time.Millisecond) 258 } 259 260 d1.updateNode(c, d2.NodeID, func(n *swarm.Node) { 261 n.Spec.Role = swarm.NodeRoleWorker 262 }) 263 264 for i := 0; ; i++ { 265 info, err := d2.info() 266 c.Assert(err, checker.IsNil) 267 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) 268 if !info.ControlAvailable { 269 break 270 } 271 if i > 100 { 272 c.Errorf("node did not turn into manager") 273 } else { 274 break 275 } 276 time.Sleep(100 * time.Millisecond) 277 } 278 279 // todo: test raft qourum stability 280 } 281 282 func (s *DockerSwarmSuite) TestApiSwarmServicesCreate(c *check.C) { 283 d := s.AddDaemon(c, true, true) 284 285 instances := 2 286 id := d.createService(c, simpleTestService, setInstances(instances)) 287 waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, instances) 288 289 service := d.getService(c, id) 290 instances = 5 291 d.updateService(c, service, setInstances(instances)) 292 waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, instances) 293 294 d.removeService(c, service.ID) 295 waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, 0) 296 } 297 298 func (s *DockerSwarmSuite) TestApiSwarmServicesMultipleAgents(c *check.C) { 299 d1 := s.AddDaemon(c, true, true) 300 d2 := s.AddDaemon(c, true, false) 301 d3 := s.AddDaemon(c, true, false) 302 303 time.Sleep(1 * time.Second) // make sure all daemons are ready to accept tasks 304 305 instances := 9 306 id := d1.createService(c, simpleTestService, setInstances(instances)) 307 308 waitAndAssert(c, defaultReconciliationTimeout, d1.checkActiveContainerCount, checker.GreaterThan, 0) 309 waitAndAssert(c, defaultReconciliationTimeout, d2.checkActiveContainerCount, checker.GreaterThan, 0) 310 waitAndAssert(c, defaultReconciliationTimeout, d3.checkActiveContainerCount, checker.GreaterThan, 0) 311 312 waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.checkActiveContainerCount, d2.checkActiveContainerCount, d3.checkActiveContainerCount), checker.Equals, instances) 313 314 // reconciliation on d2 node down 315 c.Assert(d2.Stop(), checker.IsNil) 316 317 waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.checkActiveContainerCount, d3.checkActiveContainerCount), checker.Equals, instances) 318 319 // test downscaling 320 instances = 5 321 d1.updateService(c, d1.getService(c, id), setInstances(instances)) 322 waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.checkActiveContainerCount, d3.checkActiveContainerCount), checker.Equals, instances) 323 324 } 325 326 func (s *DockerSwarmSuite) TestApiSwarmServicesCreateGlobal(c *check.C) { 327 d1 := s.AddDaemon(c, true, true) 328 d2 := s.AddDaemon(c, true, false) 329 d3 := s.AddDaemon(c, true, false) 330 331 d1.createService(c, simpleTestService, setGlobalMode) 332 333 waitAndAssert(c, defaultReconciliationTimeout, d1.checkActiveContainerCount, checker.Equals, 1) 334 waitAndAssert(c, defaultReconciliationTimeout, d2.checkActiveContainerCount, checker.Equals, 1) 335 waitAndAssert(c, defaultReconciliationTimeout, d3.checkActiveContainerCount, checker.Equals, 1) 336 337 d4 := s.AddDaemon(c, true, false) 338 d5 := s.AddDaemon(c, true, false) 339 340 waitAndAssert(c, defaultReconciliationTimeout, d4.checkActiveContainerCount, checker.Equals, 1) 341 waitAndAssert(c, defaultReconciliationTimeout, d5.checkActiveContainerCount, checker.Equals, 1) 342 } 343 344 func (s *DockerSwarmSuite) TestApiSwarmServicesStateReporting(c *check.C) { 345 testRequires(c, SameHostDaemon) 346 testRequires(c, DaemonIsLinux) 347 348 d1 := s.AddDaemon(c, true, true) 349 d2 := s.AddDaemon(c, true, true) 350 d3 := s.AddDaemon(c, true, false) 351 352 time.Sleep(1 * time.Second) // make sure all daemons are ready to accept 353 354 instances := 9 355 d1.createService(c, simpleTestService, setInstances(instances)) 356 357 waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.checkActiveContainerCount, d2.checkActiveContainerCount, d3.checkActiveContainerCount), checker.Equals, instances) 358 359 getContainers := func() map[string]*SwarmDaemon { 360 m := make(map[string]*SwarmDaemon) 361 for _, d := range []*SwarmDaemon{d1, d2, d3} { 362 for _, id := range d.activeContainers() { 363 m[id] = d 364 } 365 } 366 return m 367 } 368 369 containers := getContainers() 370 c.Assert(containers, checker.HasLen, instances) 371 var toRemove string 372 for i := range containers { 373 toRemove = i 374 } 375 376 _, err := containers[toRemove].Cmd("stop", toRemove) 377 c.Assert(err, checker.IsNil) 378 379 waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.checkActiveContainerCount, d2.checkActiveContainerCount, d3.checkActiveContainerCount), checker.Equals, instances) 380 381 containers2 := getContainers() 382 c.Assert(containers2, checker.HasLen, instances) 383 for i := range containers { 384 if i == toRemove { 385 c.Assert(containers2[i], checker.IsNil) 386 } else { 387 c.Assert(containers2[i], checker.NotNil) 388 } 389 } 390 391 containers = containers2 392 for i := range containers { 393 toRemove = i 394 } 395 396 // try with killing process outside of docker 397 pidStr, err := containers[toRemove].Cmd("inspect", "-f", "{{.State.Pid}}", toRemove) 398 c.Assert(err, checker.IsNil) 399 pid, err := strconv.Atoi(strings.TrimSpace(pidStr)) 400 c.Assert(err, checker.IsNil) 401 c.Assert(syscall.Kill(pid, syscall.SIGKILL), checker.IsNil) 402 403 time.Sleep(time.Second) // give some time to handle the signal 404 405 waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.checkActiveContainerCount, d2.checkActiveContainerCount, d3.checkActiveContainerCount), checker.Equals, instances) 406 407 containers2 = getContainers() 408 c.Assert(containers2, checker.HasLen, instances) 409 for i := range containers { 410 if i == toRemove { 411 c.Assert(containers2[i], checker.IsNil) 412 } else { 413 c.Assert(containers2[i], checker.NotNil) 414 } 415 } 416 } 417 418 func (s *DockerSwarmSuite) TestApiSwarmRaftQuorum(c *check.C) { 419 d1 := s.AddDaemon(c, true, true) 420 d2 := s.AddDaemon(c, true, true) 421 d3 := s.AddDaemon(c, true, true) 422 423 d1.createService(c, simpleTestService) 424 425 c.Assert(d2.Stop(), checker.IsNil) 426 427 d1.createService(c, simpleTestService, func(s *swarm.Service) { 428 s.Spec.Name = "top1" 429 }) 430 431 c.Assert(d3.Stop(), checker.IsNil) 432 433 var service swarm.Service 434 simpleTestService(&service) 435 service.Spec.Name = "top2" 436 status, out, err := d1.SockRequest("POST", "/services/create", service.Spec) 437 c.Assert(err, checker.IsNil) 438 c.Assert(status, checker.Equals, http.StatusInternalServerError, check.Commentf("deadline exceeded", string(out))) 439 440 c.Assert(d2.Start(), checker.IsNil) 441 442 d1.createService(c, simpleTestService, func(s *swarm.Service) { 443 s.Spec.Name = "top3" 444 }) 445 } 446 447 func (s *DockerSwarmSuite) TestApiSwarmListNodes(c *check.C) { 448 d1 := s.AddDaemon(c, true, true) 449 d2 := s.AddDaemon(c, true, false) 450 d3 := s.AddDaemon(c, true, false) 451 452 nodes := d1.listNodes(c) 453 c.Assert(len(nodes), checker.Equals, 3, check.Commentf("nodes: %#v", nodes)) 454 455 loop0: 456 for _, n := range nodes { 457 for _, d := range []*SwarmDaemon{d1, d2, d3} { 458 if n.ID == d.NodeID { 459 continue loop0 460 } 461 } 462 c.Errorf("unknown nodeID %v", n.ID) 463 } 464 } 465 466 func (s *DockerSwarmSuite) TestApiSwarmNodeUpdate(c *check.C) { 467 d := s.AddDaemon(c, true, true) 468 469 nodes := d.listNodes(c) 470 471 d.updateNode(c, nodes[0].ID, func(n *swarm.Node) { 472 n.Spec.Availability = swarm.NodeAvailabilityPause 473 }) 474 475 n := d.getNode(c, nodes[0].ID) 476 c.Assert(n.Spec.Availability, checker.Equals, swarm.NodeAvailabilityPause) 477 } 478 479 func (s *DockerSwarmSuite) TestApiSwarmNodeDrainPause(c *check.C) { 480 d1 := s.AddDaemon(c, true, true) 481 d2 := s.AddDaemon(c, true, false) 482 483 time.Sleep(1 * time.Second) // make sure all daemons are ready to accept tasks 484 485 // start a service, expect balanced distribution 486 instances := 8 487 id := d1.createService(c, simpleTestService, setInstances(instances)) 488 489 waitAndAssert(c, defaultReconciliationTimeout, d1.checkActiveContainerCount, checker.GreaterThan, 0) 490 waitAndAssert(c, defaultReconciliationTimeout, d2.checkActiveContainerCount, checker.GreaterThan, 0) 491 waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.checkActiveContainerCount, d2.checkActiveContainerCount), checker.Equals, instances) 492 493 // drain d2, all containers should move to d1 494 d1.updateNode(c, d2.NodeID, func(n *swarm.Node) { 495 n.Spec.Availability = swarm.NodeAvailabilityDrain 496 }) 497 waitAndAssert(c, defaultReconciliationTimeout, d1.checkActiveContainerCount, checker.Equals, instances) 498 waitAndAssert(c, defaultReconciliationTimeout, d2.checkActiveContainerCount, checker.Equals, 0) 499 500 // set d2 back to active 501 d1.updateNode(c, d2.NodeID, func(n *swarm.Node) { 502 n.Spec.Availability = swarm.NodeAvailabilityActive 503 }) 504 505 instances = 1 506 d1.updateService(c, d1.getService(c, id), setInstances(instances)) 507 508 waitAndAssert(c, defaultReconciliationTimeout*2, reducedCheck(sumAsIntegers, d1.checkActiveContainerCount, d2.checkActiveContainerCount), checker.Equals, instances) 509 510 instances = 8 511 d1.updateService(c, d1.getService(c, id), setInstances(instances)) 512 513 // drained node first so we don't get any old containers 514 waitAndAssert(c, defaultReconciliationTimeout, d2.checkActiveContainerCount, checker.GreaterThan, 0) 515 waitAndAssert(c, defaultReconciliationTimeout, d1.checkActiveContainerCount, checker.GreaterThan, 0) 516 waitAndAssert(c, defaultReconciliationTimeout*2, reducedCheck(sumAsIntegers, d1.checkActiveContainerCount, d2.checkActiveContainerCount), checker.Equals, instances) 517 518 d2ContainerCount := len(d2.activeContainers()) 519 520 // set d2 to paused, scale service up, only d1 gets new tasks 521 d1.updateNode(c, d2.NodeID, func(n *swarm.Node) { 522 n.Spec.Availability = swarm.NodeAvailabilityPause 523 }) 524 525 instances = 14 526 d1.updateService(c, d1.getService(c, id), setInstances(instances)) 527 528 waitAndAssert(c, defaultReconciliationTimeout, d1.checkActiveContainerCount, checker.Equals, instances-d2ContainerCount) 529 waitAndAssert(c, defaultReconciliationTimeout, d2.checkActiveContainerCount, checker.Equals, d2ContainerCount) 530 531 } 532 533 func (s *DockerSwarmSuite) TestApiSwarmLeaveRemovesContainer(c *check.C) { 534 d := s.AddDaemon(c, true, true) 535 536 instances := 2 537 d.createService(c, simpleTestService, setInstances(instances)) 538 539 id, err := d.Cmd("run", "-d", "busybox", "top") 540 c.Assert(err, checker.IsNil) 541 id = strings.TrimSpace(id) 542 543 waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, instances+1) 544 545 c.Assert(d.Leave(false), checker.NotNil) 546 c.Assert(d.Leave(true), checker.IsNil) 547 548 waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, 1) 549 550 id2, err := d.Cmd("ps", "-q") 551 c.Assert(err, checker.IsNil) 552 c.Assert(id, checker.HasPrefix, strings.TrimSpace(id2)) 553 } 554 555 // #23629 556 func (s *DockerSwarmSuite) TestApiSwarmLeaveOnPendingJoin(c *check.C) { 557 s.AddDaemon(c, true, true) 558 d2 := s.AddDaemon(c, false, false) 559 560 id, err := d2.Cmd("run", "-d", "busybox", "top") 561 c.Assert(err, checker.IsNil) 562 id = strings.TrimSpace(id) 563 564 go d2.Join("nosuchhost:1234", "", "", false) // will block on pending state 565 566 for i := 0; ; i++ { 567 info, err := d2.info() 568 c.Assert(err, checker.IsNil) 569 if info.LocalNodeState == swarm.LocalNodeStatePending { 570 break 571 } 572 if i > 100 { 573 c.Fatalf("node did not go to pending state: %v", info.LocalNodeState) 574 } 575 time.Sleep(100 * time.Millisecond) 576 } 577 578 c.Assert(d2.Leave(true), checker.IsNil) 579 580 waitAndAssert(c, defaultReconciliationTimeout, d2.checkActiveContainerCount, checker.Equals, 1) 581 582 id2, err := d2.Cmd("ps", "-q") 583 c.Assert(err, checker.IsNil) 584 c.Assert(id, checker.HasPrefix, strings.TrimSpace(id2)) 585 } 586 587 // #23705 588 func (s *DockerSwarmSuite) TestApiSwarmRestoreOnPendingJoin(c *check.C) { 589 d := s.AddDaemon(c, false, false) 590 go d.Join("nosuchhost:1234", "", "", false) // will block on pending state 591 592 for i := 0; ; i++ { 593 info, err := d.info() 594 c.Assert(err, checker.IsNil) 595 if info.LocalNodeState == swarm.LocalNodeStatePending { 596 break 597 } 598 if i > 100 { 599 c.Fatalf("node did not go to pending state: %v", info.LocalNodeState) 600 } 601 time.Sleep(100 * time.Millisecond) 602 } 603 604 c.Assert(d.Stop(), checker.IsNil) 605 c.Assert(d.Start(), checker.IsNil) 606 607 info, err := d.info() 608 c.Assert(err, checker.IsNil) 609 c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive) 610 } 611 612 func (s *DockerSwarmSuite) TestApiSwarmManagerRestore(c *check.C) { 613 d1 := s.AddDaemon(c, true, true) 614 615 instances := 2 616 id := d1.createService(c, simpleTestService, setInstances(instances)) 617 618 d1.getService(c, id) 619 d1.Stop() 620 d1.Start() 621 d1.getService(c, id) 622 623 d2 := s.AddDaemon(c, true, true) 624 d2.getService(c, id) 625 d2.Stop() 626 d2.Start() 627 d2.getService(c, id) 628 629 d3 := s.AddDaemon(c, true, true) 630 d3.getService(c, id) 631 d3.Stop() 632 d3.Start() 633 d3.getService(c, id) 634 635 d3.Kill() 636 time.Sleep(1 * time.Second) // time to handle signal 637 d3.Start() 638 d3.getService(c, id) 639 } 640 641 func (s *DockerSwarmSuite) TestApiSwarmScaleNoRollingUpdate(c *check.C) { 642 d := s.AddDaemon(c, true, true) 643 644 instances := 2 645 id := d.createService(c, simpleTestService, setInstances(instances)) 646 647 waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, instances) 648 containers := d.activeContainers() 649 instances = 4 650 d.updateService(c, d.getService(c, id), setInstances(instances)) 651 waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, instances) 652 containers2 := d.activeContainers() 653 654 loop0: 655 for _, c1 := range containers { 656 for _, c2 := range containers2 { 657 if c1 == c2 { 658 continue loop0 659 } 660 } 661 c.Errorf("container %v not found in new set %#v", c1, containers2) 662 } 663 } 664 665 func (s *DockerSwarmSuite) TestApiSwarmInvalidAddress(c *check.C) { 666 d := s.AddDaemon(c, false, false) 667 req := swarm.InitRequest{ 668 ListenAddr: "", 669 } 670 status, _, err := d.SockRequest("POST", "/swarm/init", req) 671 c.Assert(err, checker.IsNil) 672 c.Assert(status, checker.Equals, http.StatusInternalServerError) 673 674 req2 := swarm.JoinRequest{ 675 ListenAddr: "0.0.0.0:2377", 676 RemoteAddrs: []string{""}, 677 } 678 status, _, err = d.SockRequest("POST", "/swarm/join", req2) 679 c.Assert(err, checker.IsNil) 680 c.Assert(status, checker.Equals, http.StatusInternalServerError) 681 } 682 683 func simpleTestService(s *swarm.Service) { 684 var ureplicas uint64 685 ureplicas = 1 686 s.Spec = swarm.ServiceSpec{ 687 TaskTemplate: swarm.TaskSpec{ 688 ContainerSpec: swarm.ContainerSpec{ 689 Image: "busybox:latest", 690 Command: []string{"/bin/top"}, 691 }, 692 }, 693 Mode: swarm.ServiceMode{ 694 Replicated: &swarm.ReplicatedService{ 695 Replicas: &ureplicas, 696 }, 697 }, 698 } 699 s.Spec.Name = "top" 700 } 701 702 func setInstances(replicas int) serviceConstructor { 703 ureplicas := uint64(replicas) 704 return func(s *swarm.Service) { 705 s.Spec.Mode = swarm.ServiceMode{ 706 Replicated: &swarm.ReplicatedService{ 707 Replicas: &ureplicas, 708 }, 709 } 710 } 711 } 712 713 func setGlobalMode(s *swarm.Service) { 714 s.Spec.Mode = swarm.ServiceMode{ 715 Global: &swarm.GlobalService{}, 716 } 717 }