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  }