docker_api_swarm_test.go 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851
  1. // +build !windows
  2. package main
  3. import (
  4. "encoding/json"
  5. "fmt"
  6. "net"
  7. "net/http"
  8. "os"
  9. "path/filepath"
  10. "strings"
  11. "sync"
  12. "time"
  13. "github.com/docker/docker/api/types"
  14. "github.com/docker/docker/api/types/container"
  15. "github.com/docker/docker/api/types/swarm"
  16. "github.com/docker/docker/integration-cli/checker"
  17. "github.com/docker/docker/integration-cli/daemon"
  18. "github.com/go-check/check"
  19. )
  20. var defaultReconciliationTimeout = 30 * time.Second
  21. func (s *DockerSwarmSuite) TestAPISwarmInit(c *check.C) {
  22. // todo: should find a better way to verify that components are running than /info
  23. d1 := s.AddDaemon(c, true, true)
  24. info, err := d1.SwarmInfo()
  25. c.Assert(err, checker.IsNil)
  26. c.Assert(info.ControlAvailable, checker.True)
  27. c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
  28. d2 := s.AddDaemon(c, true, false)
  29. info, err = d2.SwarmInfo()
  30. c.Assert(err, checker.IsNil)
  31. c.Assert(info.ControlAvailable, checker.False)
  32. c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
  33. // Leaving cluster
  34. c.Assert(d2.Leave(false), checker.IsNil)
  35. info, err = d2.SwarmInfo()
  36. c.Assert(err, checker.IsNil)
  37. c.Assert(info.ControlAvailable, checker.False)
  38. c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
  39. c.Assert(d2.Join(swarm.JoinRequest{JoinToken: d1.JoinTokens(c).Worker, RemoteAddrs: []string{d1.ListenAddr}}), checker.IsNil)
  40. info, err = d2.SwarmInfo()
  41. c.Assert(err, checker.IsNil)
  42. c.Assert(info.ControlAvailable, checker.False)
  43. c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
  44. // Current state restoring after restarts
  45. d1.Stop(c)
  46. d2.Stop(c)
  47. d1.Start(c)
  48. d2.Start(c)
  49. info, err = d1.SwarmInfo()
  50. c.Assert(err, checker.IsNil)
  51. c.Assert(info.ControlAvailable, checker.True)
  52. c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
  53. info, err = d2.SwarmInfo()
  54. c.Assert(err, checker.IsNil)
  55. c.Assert(info.ControlAvailable, checker.False)
  56. c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
  57. }
  58. func (s *DockerSwarmSuite) TestAPISwarmJoinToken(c *check.C) {
  59. d1 := s.AddDaemon(c, false, false)
  60. c.Assert(d1.Init(swarm.InitRequest{}), checker.IsNil)
  61. // todo: error message differs depending if some components of token are valid
  62. d2 := s.AddDaemon(c, false, false)
  63. err := d2.Join(swarm.JoinRequest{RemoteAddrs: []string{d1.ListenAddr}})
  64. c.Assert(err, checker.NotNil)
  65. c.Assert(err.Error(), checker.Contains, "join token is necessary")
  66. info, err := d2.SwarmInfo()
  67. c.Assert(err, checker.IsNil)
  68. c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
  69. err = d2.Join(swarm.JoinRequest{JoinToken: "foobaz", RemoteAddrs: []string{d1.ListenAddr}})
  70. c.Assert(err, checker.NotNil)
  71. c.Assert(err.Error(), checker.Contains, "invalid join token")
  72. info, err = d2.SwarmInfo()
  73. c.Assert(err, checker.IsNil)
  74. c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
  75. workerToken := d1.JoinTokens(c).Worker
  76. c.Assert(d2.Join(swarm.JoinRequest{JoinToken: workerToken, RemoteAddrs: []string{d1.ListenAddr}}), checker.IsNil)
  77. info, err = d2.SwarmInfo()
  78. c.Assert(err, checker.IsNil)
  79. c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
  80. c.Assert(d2.Leave(false), checker.IsNil)
  81. info, err = d2.SwarmInfo()
  82. c.Assert(err, checker.IsNil)
  83. c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
  84. // change tokens
  85. d1.RotateTokens(c)
  86. err = d2.Join(swarm.JoinRequest{JoinToken: workerToken, RemoteAddrs: []string{d1.ListenAddr}})
  87. c.Assert(err, checker.NotNil)
  88. c.Assert(err.Error(), checker.Contains, "join token is necessary")
  89. info, err = d2.SwarmInfo()
  90. c.Assert(err, checker.IsNil)
  91. c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
  92. workerToken = d1.JoinTokens(c).Worker
  93. c.Assert(d2.Join(swarm.JoinRequest{JoinToken: workerToken, RemoteAddrs: []string{d1.ListenAddr}}), checker.IsNil)
  94. info, err = d2.SwarmInfo()
  95. c.Assert(err, checker.IsNil)
  96. c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
  97. c.Assert(d2.Leave(false), checker.IsNil)
  98. info, err = d2.SwarmInfo()
  99. c.Assert(err, checker.IsNil)
  100. c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
  101. // change spec, don't change tokens
  102. d1.UpdateSwarm(c, func(s *swarm.Spec) {})
  103. err = d2.Join(swarm.JoinRequest{RemoteAddrs: []string{d1.ListenAddr}})
  104. c.Assert(err, checker.NotNil)
  105. c.Assert(err.Error(), checker.Contains, "join token is necessary")
  106. info, err = d2.SwarmInfo()
  107. c.Assert(err, checker.IsNil)
  108. c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
  109. c.Assert(d2.Join(swarm.JoinRequest{JoinToken: workerToken, RemoteAddrs: []string{d1.ListenAddr}}), checker.IsNil)
  110. info, err = d2.SwarmInfo()
  111. c.Assert(err, checker.IsNil)
  112. c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
  113. c.Assert(d2.Leave(false), checker.IsNil)
  114. info, err = d2.SwarmInfo()
  115. c.Assert(err, checker.IsNil)
  116. c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
  117. }
  118. func (s *DockerSwarmSuite) TestAPISwarmCAHash(c *check.C) {
  119. d1 := s.AddDaemon(c, true, true)
  120. d2 := s.AddDaemon(c, false, false)
  121. splitToken := strings.Split(d1.JoinTokens(c).Worker, "-")
  122. splitToken[2] = "1kxftv4ofnc6mt30lmgipg6ngf9luhwqopfk1tz6bdmnkubg0e"
  123. replacementToken := strings.Join(splitToken, "-")
  124. err := d2.Join(swarm.JoinRequest{JoinToken: replacementToken, RemoteAddrs: []string{d1.ListenAddr}})
  125. c.Assert(err, checker.NotNil)
  126. c.Assert(err.Error(), checker.Contains, "remote CA does not match fingerprint")
  127. }
  128. func (s *DockerSwarmSuite) TestAPISwarmPromoteDemote(c *check.C) {
  129. d1 := s.AddDaemon(c, false, false)
  130. c.Assert(d1.Init(swarm.InitRequest{}), checker.IsNil)
  131. d2 := s.AddDaemon(c, true, false)
  132. info, err := d2.SwarmInfo()
  133. c.Assert(err, checker.IsNil)
  134. c.Assert(info.ControlAvailable, checker.False)
  135. c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
  136. d1.UpdateNode(c, d2.NodeID, func(n *swarm.Node) {
  137. n.Spec.Role = swarm.NodeRoleManager
  138. })
  139. waitAndAssert(c, defaultReconciliationTimeout, d2.CheckControlAvailable, checker.True)
  140. d1.UpdateNode(c, d2.NodeID, func(n *swarm.Node) {
  141. n.Spec.Role = swarm.NodeRoleWorker
  142. })
  143. waitAndAssert(c, defaultReconciliationTimeout, d2.CheckControlAvailable, checker.False)
  144. // Demoting last node should fail
  145. node := d1.GetNode(c, d1.NodeID)
  146. node.Spec.Role = swarm.NodeRoleWorker
  147. url := fmt.Sprintf("/nodes/%s/update?version=%d", node.ID, node.Version.Index)
  148. status, out, err := d1.SockRequest("POST", url, node.Spec)
  149. c.Assert(err, checker.IsNil)
  150. c.Assert(status, checker.Equals, http.StatusInternalServerError, check.Commentf("output: %q", string(out)))
  151. c.Assert(string(out), checker.Contains, "last manager of the swarm")
  152. info, err = d1.SwarmInfo()
  153. c.Assert(err, checker.IsNil)
  154. c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
  155. c.Assert(info.ControlAvailable, checker.True)
  156. // Promote already demoted node
  157. d1.UpdateNode(c, d2.NodeID, func(n *swarm.Node) {
  158. n.Spec.Role = swarm.NodeRoleManager
  159. })
  160. waitAndAssert(c, defaultReconciliationTimeout, d2.CheckControlAvailable, checker.True)
  161. }
  162. func (s *DockerSwarmSuite) TestAPISwarmLeaderProxy(c *check.C) {
  163. // add three managers, one of these is leader
  164. d1 := s.AddDaemon(c, true, true)
  165. d2 := s.AddDaemon(c, true, true)
  166. d3 := s.AddDaemon(c, true, true)
  167. // start a service by hitting each of the 3 managers
  168. d1.CreateService(c, simpleTestService, func(s *swarm.Service) {
  169. s.Spec.Name = "test1"
  170. })
  171. d2.CreateService(c, simpleTestService, func(s *swarm.Service) {
  172. s.Spec.Name = "test2"
  173. })
  174. d3.CreateService(c, simpleTestService, func(s *swarm.Service) {
  175. s.Spec.Name = "test3"
  176. })
  177. // 3 services should be started now, because the requests were proxied to leader
  178. // query each node and make sure it returns 3 services
  179. for _, d := range []*daemon.Swarm{d1, d2, d3} {
  180. services := d.ListServices(c)
  181. c.Assert(services, checker.HasLen, 3)
  182. }
  183. }
  184. func (s *DockerSwarmSuite) TestAPISwarmLeaderElection(c *check.C) {
  185. // Create 3 nodes
  186. d1 := s.AddDaemon(c, true, true)
  187. d2 := s.AddDaemon(c, true, true)
  188. d3 := s.AddDaemon(c, true, true)
  189. // assert that the first node we made is the leader, and the other two are followers
  190. c.Assert(d1.GetNode(c, d1.NodeID).ManagerStatus.Leader, checker.True)
  191. c.Assert(d1.GetNode(c, d2.NodeID).ManagerStatus.Leader, checker.False)
  192. c.Assert(d1.GetNode(c, d3.NodeID).ManagerStatus.Leader, checker.False)
  193. d1.Stop(c)
  194. var (
  195. leader *daemon.Swarm // keep track of leader
  196. followers []*daemon.Swarm // keep track of followers
  197. )
  198. checkLeader := func(nodes ...*daemon.Swarm) checkF {
  199. return func(c *check.C) (interface{}, check.CommentInterface) {
  200. // clear these out before each run
  201. leader = nil
  202. followers = nil
  203. for _, d := range nodes {
  204. if d.GetNode(c, d.NodeID).ManagerStatus.Leader {
  205. leader = d
  206. } else {
  207. followers = append(followers, d)
  208. }
  209. }
  210. if leader == nil {
  211. return false, check.Commentf("no leader elected")
  212. }
  213. return true, check.Commentf("elected %v", leader.ID())
  214. }
  215. }
  216. // wait for an election to occur
  217. waitAndAssert(c, defaultReconciliationTimeout, checkLeader(d2, d3), checker.True)
  218. // assert that we have a new leader
  219. c.Assert(leader, checker.NotNil)
  220. // Keep track of the current leader, since we want that to be chosen.
  221. stableleader := leader
  222. // add the d1, the initial leader, back
  223. d1.Start(c)
  224. // TODO(stevvooe): may need to wait for rejoin here
  225. // wait for possible election
  226. waitAndAssert(c, defaultReconciliationTimeout, checkLeader(d1, d2, d3), checker.True)
  227. // pick out the leader and the followers again
  228. // verify that we still only have 1 leader and 2 followers
  229. c.Assert(leader, checker.NotNil)
  230. c.Assert(followers, checker.HasLen, 2)
  231. // and that after we added d1 back, the leader hasn't changed
  232. c.Assert(leader.NodeID, checker.Equals, stableleader.NodeID)
  233. }
  234. func (s *DockerSwarmSuite) TestAPISwarmRaftQuorum(c *check.C) {
  235. d1 := s.AddDaemon(c, true, true)
  236. d2 := s.AddDaemon(c, true, true)
  237. d3 := s.AddDaemon(c, true, true)
  238. d1.CreateService(c, simpleTestService)
  239. d2.Stop(c)
  240. // make sure there is a leader
  241. waitAndAssert(c, defaultReconciliationTimeout, d1.CheckLeader, checker.IsNil)
  242. d1.CreateService(c, simpleTestService, func(s *swarm.Service) {
  243. s.Spec.Name = "top1"
  244. })
  245. d3.Stop(c)
  246. // make sure there is a leader
  247. waitAndAssert(c, defaultReconciliationTimeout, d1.CheckLeader, checker.IsNil)
  248. var service swarm.Service
  249. simpleTestService(&service)
  250. service.Spec.Name = "top2"
  251. status, out, err := d1.SockRequest("POST", "/services/create", service.Spec)
  252. c.Assert(err, checker.IsNil)
  253. c.Assert(status, checker.Equals, http.StatusInternalServerError, check.Commentf("deadline exceeded", string(out)))
  254. d2.Start(c)
  255. // make sure there is a leader
  256. waitAndAssert(c, defaultReconciliationTimeout, d1.CheckLeader, checker.IsNil)
  257. d1.CreateService(c, simpleTestService, func(s *swarm.Service) {
  258. s.Spec.Name = "top3"
  259. })
  260. }
  261. func (s *DockerSwarmSuite) TestAPISwarmLeaveRemovesContainer(c *check.C) {
  262. d := s.AddDaemon(c, true, true)
  263. instances := 2
  264. d.CreateService(c, simpleTestService, setInstances(instances))
  265. id, err := d.Cmd("run", "-d", "busybox", "top")
  266. c.Assert(err, checker.IsNil)
  267. id = strings.TrimSpace(id)
  268. waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances+1)
  269. c.Assert(d.Leave(false), checker.NotNil)
  270. c.Assert(d.Leave(true), checker.IsNil)
  271. waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
  272. id2, err := d.Cmd("ps", "-q")
  273. c.Assert(err, checker.IsNil)
  274. c.Assert(id, checker.HasPrefix, strings.TrimSpace(id2))
  275. }
  276. // #23629
  277. func (s *DockerSwarmSuite) TestAPISwarmLeaveOnPendingJoin(c *check.C) {
  278. testRequires(c, Network)
  279. s.AddDaemon(c, true, true)
  280. d2 := s.AddDaemon(c, false, false)
  281. id, err := d2.Cmd("run", "-d", "busybox", "top")
  282. c.Assert(err, checker.IsNil)
  283. id = strings.TrimSpace(id)
  284. err = d2.Join(swarm.JoinRequest{
  285. RemoteAddrs: []string{"123.123.123.123:1234"},
  286. })
  287. c.Assert(err, check.NotNil)
  288. c.Assert(err.Error(), checker.Contains, "Timeout was reached")
  289. info, err := d2.SwarmInfo()
  290. c.Assert(err, checker.IsNil)
  291. c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStatePending)
  292. c.Assert(d2.Leave(true), checker.IsNil)
  293. waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.Equals, 1)
  294. id2, err := d2.Cmd("ps", "-q")
  295. c.Assert(err, checker.IsNil)
  296. c.Assert(id, checker.HasPrefix, strings.TrimSpace(id2))
  297. }
  298. // #23705
  299. func (s *DockerSwarmSuite) TestAPISwarmRestoreOnPendingJoin(c *check.C) {
  300. testRequires(c, Network)
  301. d := s.AddDaemon(c, false, false)
  302. err := d.Join(swarm.JoinRequest{
  303. RemoteAddrs: []string{"123.123.123.123:1234"},
  304. })
  305. c.Assert(err, check.NotNil)
  306. c.Assert(err.Error(), checker.Contains, "Timeout was reached")
  307. waitAndAssert(c, defaultReconciliationTimeout, d.CheckLocalNodeState, checker.Equals, swarm.LocalNodeStatePending)
  308. d.Stop(c)
  309. d.Start(c)
  310. info, err := d.SwarmInfo()
  311. c.Assert(err, checker.IsNil)
  312. c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
  313. }
  314. func (s *DockerSwarmSuite) TestAPISwarmManagerRestore(c *check.C) {
  315. d1 := s.AddDaemon(c, true, true)
  316. instances := 2
  317. id := d1.CreateService(c, simpleTestService, setInstances(instances))
  318. d1.GetService(c, id)
  319. d1.Stop(c)
  320. d1.Start(c)
  321. d1.GetService(c, id)
  322. d2 := s.AddDaemon(c, true, true)
  323. d2.GetService(c, id)
  324. d2.Stop(c)
  325. d2.Start(c)
  326. d2.GetService(c, id)
  327. d3 := s.AddDaemon(c, true, true)
  328. d3.GetService(c, id)
  329. d3.Stop(c)
  330. d3.Start(c)
  331. d3.GetService(c, id)
  332. d3.Kill()
  333. time.Sleep(1 * time.Second) // time to handle signal
  334. d3.Start(c)
  335. d3.GetService(c, id)
  336. }
  337. func (s *DockerSwarmSuite) TestAPISwarmScaleNoRollingUpdate(c *check.C) {
  338. d := s.AddDaemon(c, true, true)
  339. instances := 2
  340. id := d.CreateService(c, simpleTestService, setInstances(instances))
  341. waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances)
  342. containers := d.ActiveContainers()
  343. instances = 4
  344. d.UpdateService(c, d.GetService(c, id), setInstances(instances))
  345. waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances)
  346. containers2 := d.ActiveContainers()
  347. loop0:
  348. for _, c1 := range containers {
  349. for _, c2 := range containers2 {
  350. if c1 == c2 {
  351. continue loop0
  352. }
  353. }
  354. c.Errorf("container %v not found in new set %#v", c1, containers2)
  355. }
  356. }
  357. func (s *DockerSwarmSuite) TestAPISwarmInvalidAddress(c *check.C) {
  358. d := s.AddDaemon(c, false, false)
  359. req := swarm.InitRequest{
  360. ListenAddr: "",
  361. }
  362. status, _, err := d.SockRequest("POST", "/swarm/init", req)
  363. c.Assert(err, checker.IsNil)
  364. c.Assert(status, checker.Equals, http.StatusBadRequest)
  365. req2 := swarm.JoinRequest{
  366. ListenAddr: "0.0.0.0:2377",
  367. RemoteAddrs: []string{""},
  368. }
  369. status, _, err = d.SockRequest("POST", "/swarm/join", req2)
  370. c.Assert(err, checker.IsNil)
  371. c.Assert(status, checker.Equals, http.StatusBadRequest)
  372. }
  373. func (s *DockerSwarmSuite) TestAPISwarmForceNewCluster(c *check.C) {
  374. d1 := s.AddDaemon(c, true, true)
  375. d2 := s.AddDaemon(c, true, true)
  376. instances := 2
  377. id := d1.CreateService(c, simpleTestService, setInstances(instances))
  378. waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals, instances)
  379. // drain d2, all containers should move to d1
  380. d1.UpdateNode(c, d2.NodeID, func(n *swarm.Node) {
  381. n.Spec.Availability = swarm.NodeAvailabilityDrain
  382. })
  383. waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.Equals, instances)
  384. waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.Equals, 0)
  385. d2.Stop(c)
  386. c.Assert(d1.Init(swarm.InitRequest{
  387. ForceNewCluster: true,
  388. Spec: swarm.Spec{},
  389. }), checker.IsNil)
  390. waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.Equals, instances)
  391. d3 := s.AddDaemon(c, true, true)
  392. info, err := d3.SwarmInfo()
  393. c.Assert(err, checker.IsNil)
  394. c.Assert(info.ControlAvailable, checker.True)
  395. c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
  396. instances = 4
  397. d3.UpdateService(c, d3.GetService(c, id), setInstances(instances))
  398. waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals, instances)
  399. }
  400. func simpleTestService(s *swarm.Service) {
  401. ureplicas := uint64(1)
  402. restartDelay := time.Duration(100 * time.Millisecond)
  403. s.Spec = swarm.ServiceSpec{
  404. TaskTemplate: swarm.TaskSpec{
  405. ContainerSpec: swarm.ContainerSpec{
  406. Image: "busybox:latest",
  407. Command: []string{"/bin/top"},
  408. },
  409. RestartPolicy: &swarm.RestartPolicy{
  410. Delay: &restartDelay,
  411. },
  412. },
  413. Mode: swarm.ServiceMode{
  414. Replicated: &swarm.ReplicatedService{
  415. Replicas: &ureplicas,
  416. },
  417. },
  418. }
  419. s.Spec.Name = "top"
  420. }
  421. func serviceForUpdate(s *swarm.Service) {
  422. ureplicas := uint64(1)
  423. restartDelay := time.Duration(100 * time.Millisecond)
  424. s.Spec = swarm.ServiceSpec{
  425. TaskTemplate: swarm.TaskSpec{
  426. ContainerSpec: swarm.ContainerSpec{
  427. Image: "busybox:latest",
  428. Command: []string{"/bin/top"},
  429. },
  430. RestartPolicy: &swarm.RestartPolicy{
  431. Delay: &restartDelay,
  432. },
  433. },
  434. Mode: swarm.ServiceMode{
  435. Replicated: &swarm.ReplicatedService{
  436. Replicas: &ureplicas,
  437. },
  438. },
  439. UpdateConfig: &swarm.UpdateConfig{
  440. Parallelism: 2,
  441. Delay: 4 * time.Second,
  442. FailureAction: swarm.UpdateFailureActionContinue,
  443. },
  444. }
  445. s.Spec.Name = "updatetest"
  446. }
  447. func setInstances(replicas int) daemon.ServiceConstructor {
  448. ureplicas := uint64(replicas)
  449. return func(s *swarm.Service) {
  450. s.Spec.Mode = swarm.ServiceMode{
  451. Replicated: &swarm.ReplicatedService{
  452. Replicas: &ureplicas,
  453. },
  454. }
  455. }
  456. }
  457. func setImage(image string) daemon.ServiceConstructor {
  458. return func(s *swarm.Service) {
  459. s.Spec.TaskTemplate.ContainerSpec.Image = image
  460. }
  461. }
  462. func setFailureAction(failureAction string) daemon.ServiceConstructor {
  463. return func(s *swarm.Service) {
  464. s.Spec.UpdateConfig.FailureAction = failureAction
  465. }
  466. }
  467. func setMaxFailureRatio(maxFailureRatio float32) daemon.ServiceConstructor {
  468. return func(s *swarm.Service) {
  469. s.Spec.UpdateConfig.MaxFailureRatio = maxFailureRatio
  470. }
  471. }
  472. func setParallelism(parallelism uint64) daemon.ServiceConstructor {
  473. return func(s *swarm.Service) {
  474. s.Spec.UpdateConfig.Parallelism = parallelism
  475. }
  476. }
  477. func setConstraints(constraints []string) daemon.ServiceConstructor {
  478. return func(s *swarm.Service) {
  479. if s.Spec.TaskTemplate.Placement == nil {
  480. s.Spec.TaskTemplate.Placement = &swarm.Placement{}
  481. }
  482. s.Spec.TaskTemplate.Placement.Constraints = constraints
  483. }
  484. }
  485. func setGlobalMode(s *swarm.Service) {
  486. s.Spec.Mode = swarm.ServiceMode{
  487. Global: &swarm.GlobalService{},
  488. }
  489. }
  490. func checkClusterHealth(c *check.C, cl []*daemon.Swarm, managerCount, workerCount int) {
  491. var totalMCount, totalWCount int
  492. for _, d := range cl {
  493. var (
  494. info swarm.Info
  495. err error
  496. )
  497. // check info in a waitAndAssert, because if the cluster doesn't have a leader, `info` will return an error
  498. checkInfo := func(c *check.C) (interface{}, check.CommentInterface) {
  499. info, err = d.SwarmInfo()
  500. return err, check.Commentf("cluster not ready in time")
  501. }
  502. waitAndAssert(c, defaultReconciliationTimeout, checkInfo, checker.IsNil)
  503. if !info.ControlAvailable {
  504. totalWCount++
  505. continue
  506. }
  507. var leaderFound bool
  508. totalMCount++
  509. var mCount, wCount int
  510. for _, n := range d.ListNodes(c) {
  511. waitReady := func(c *check.C) (interface{}, check.CommentInterface) {
  512. if n.Status.State == swarm.NodeStateReady {
  513. return true, nil
  514. }
  515. nn := d.GetNode(c, n.ID)
  516. n = *nn
  517. return n.Status.State == swarm.NodeStateReady, check.Commentf("state of node %s, reported by %s", n.ID, d.Info.NodeID)
  518. }
  519. waitAndAssert(c, defaultReconciliationTimeout, waitReady, checker.True)
  520. waitActive := func(c *check.C) (interface{}, check.CommentInterface) {
  521. if n.Spec.Availability == swarm.NodeAvailabilityActive {
  522. return true, nil
  523. }
  524. nn := d.GetNode(c, n.ID)
  525. n = *nn
  526. return n.Spec.Availability == swarm.NodeAvailabilityActive, check.Commentf("availability of node %s, reported by %s", n.ID, d.Info.NodeID)
  527. }
  528. waitAndAssert(c, defaultReconciliationTimeout, waitActive, checker.True)
  529. if n.Spec.Role == swarm.NodeRoleManager {
  530. c.Assert(n.ManagerStatus, checker.NotNil, check.Commentf("manager status of node %s (manager), reported by %s", n.ID, d.Info.NodeID))
  531. if n.ManagerStatus.Leader {
  532. leaderFound = true
  533. }
  534. mCount++
  535. } else {
  536. c.Assert(n.ManagerStatus, checker.IsNil, check.Commentf("manager status of node %s (worker), reported by %s", n.ID, d.Info.NodeID))
  537. wCount++
  538. }
  539. }
  540. c.Assert(leaderFound, checker.True, check.Commentf("lack of leader reported by node %s", info.NodeID))
  541. c.Assert(mCount, checker.Equals, managerCount, check.Commentf("managers count reported by node %s", info.NodeID))
  542. c.Assert(wCount, checker.Equals, workerCount, check.Commentf("workers count reported by node %s", info.NodeID))
  543. }
  544. c.Assert(totalMCount, checker.Equals, managerCount)
  545. c.Assert(totalWCount, checker.Equals, workerCount)
  546. }
  547. func (s *DockerSwarmSuite) TestAPISwarmRestartCluster(c *check.C) {
  548. mCount, wCount := 5, 1
  549. var nodes []*daemon.Swarm
  550. for i := 0; i < mCount; i++ {
  551. manager := s.AddDaemon(c, true, true)
  552. info, err := manager.SwarmInfo()
  553. c.Assert(err, checker.IsNil)
  554. c.Assert(info.ControlAvailable, checker.True)
  555. c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
  556. nodes = append(nodes, manager)
  557. }
  558. for i := 0; i < wCount; i++ {
  559. worker := s.AddDaemon(c, true, false)
  560. info, err := worker.SwarmInfo()
  561. c.Assert(err, checker.IsNil)
  562. c.Assert(info.ControlAvailable, checker.False)
  563. c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
  564. nodes = append(nodes, worker)
  565. }
  566. // stop whole cluster
  567. {
  568. var wg sync.WaitGroup
  569. wg.Add(len(nodes))
  570. errs := make(chan error, len(nodes))
  571. for _, d := range nodes {
  572. go func(daemon *daemon.Swarm) {
  573. defer wg.Done()
  574. if err := daemon.StopWithError(); err != nil {
  575. errs <- err
  576. }
  577. // FIXME(vdemeester) This is duplicated…
  578. if root := os.Getenv("DOCKER_REMAP_ROOT"); root != "" {
  579. daemon.Root = filepath.Dir(daemon.Root)
  580. }
  581. }(d)
  582. }
  583. wg.Wait()
  584. close(errs)
  585. for err := range errs {
  586. c.Assert(err, check.IsNil)
  587. }
  588. }
  589. // start whole cluster
  590. {
  591. var wg sync.WaitGroup
  592. wg.Add(len(nodes))
  593. errs := make(chan error, len(nodes))
  594. for _, d := range nodes {
  595. go func(daemon *daemon.Swarm) {
  596. defer wg.Done()
  597. if err := daemon.StartWithError("--iptables=false"); err != nil {
  598. errs <- err
  599. }
  600. }(d)
  601. }
  602. wg.Wait()
  603. close(errs)
  604. for err := range errs {
  605. c.Assert(err, check.IsNil)
  606. }
  607. }
  608. checkClusterHealth(c, nodes, mCount, wCount)
  609. }
  610. func (s *DockerSwarmSuite) TestAPISwarmServicesUpdateWithName(c *check.C) {
  611. d := s.AddDaemon(c, true, true)
  612. instances := 2
  613. id := d.CreateService(c, simpleTestService, setInstances(instances))
  614. waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances)
  615. service := d.GetService(c, id)
  616. instances = 5
  617. setInstances(instances)(service)
  618. url := fmt.Sprintf("/services/%s/update?version=%d", service.Spec.Name, service.Version.Index)
  619. status, out, err := d.SockRequest("POST", url, service.Spec)
  620. c.Assert(err, checker.IsNil)
  621. c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out)))
  622. waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances)
  623. }
  624. // Unlocking an unlocked swarm results in an error
  625. func (s *DockerSwarmSuite) TestAPISwarmUnlockNotLocked(c *check.C) {
  626. d := s.AddDaemon(c, true, true)
  627. err := d.Unlock(swarm.UnlockRequest{UnlockKey: "wrong-key"})
  628. c.Assert(err, checker.NotNil)
  629. c.Assert(err.Error(), checker.Contains, "swarm is not locked")
  630. }
  631. // #29885
  632. func (s *DockerSwarmSuite) TestAPISwarmErrorHandling(c *check.C) {
  633. ln, err := net.Listen("tcp", fmt.Sprintf(":%d", defaultSwarmPort))
  634. c.Assert(err, checker.IsNil)
  635. defer ln.Close()
  636. d := s.AddDaemon(c, false, false)
  637. err = d.Init(swarm.InitRequest{})
  638. c.Assert(err, checker.NotNil)
  639. c.Assert(err.Error(), checker.Contains, "address already in use")
  640. }
  641. // Test case for 30242, where duplicate networks, with different drivers `bridge` and `overlay`,
  642. // caused both scopes to be `swarm` for `docker network inspect` and `docker network ls`.
  643. // This test makes sure the fixes correctly output scopes instead.
  644. func (s *DockerSwarmSuite) TestAPIDuplicateNetworks(c *check.C) {
  645. d := s.AddDaemon(c, true, true)
  646. name := "foo"
  647. networkCreateRequest := types.NetworkCreateRequest{
  648. Name: name,
  649. NetworkCreate: types.NetworkCreate{
  650. CheckDuplicate: false,
  651. },
  652. }
  653. var n1 types.NetworkCreateResponse
  654. networkCreateRequest.NetworkCreate.Driver = "bridge"
  655. status, out, err := d.SockRequest("POST", "/networks/create", networkCreateRequest)
  656. c.Assert(err, checker.IsNil, check.Commentf(string(out)))
  657. c.Assert(status, checker.Equals, http.StatusCreated, check.Commentf(string(out)))
  658. c.Assert(json.Unmarshal(out, &n1), checker.IsNil)
  659. var n2 types.NetworkCreateResponse
  660. networkCreateRequest.NetworkCreate.Driver = "overlay"
  661. status, out, err = d.SockRequest("POST", "/networks/create", networkCreateRequest)
  662. c.Assert(err, checker.IsNil, check.Commentf(string(out)))
  663. c.Assert(status, checker.Equals, http.StatusCreated, check.Commentf(string(out)))
  664. c.Assert(json.Unmarshal(out, &n2), checker.IsNil)
  665. var r1 types.NetworkResource
  666. status, out, err = d.SockRequest("GET", "/networks/"+n1.ID, nil)
  667. c.Assert(err, checker.IsNil, check.Commentf(string(out)))
  668. c.Assert(status, checker.Equals, http.StatusOK, check.Commentf(string(out)))
  669. c.Assert(json.Unmarshal(out, &r1), checker.IsNil)
  670. c.Assert(r1.Scope, checker.Equals, "local")
  671. var r2 types.NetworkResource
  672. status, out, err = d.SockRequest("GET", "/networks/"+n2.ID, nil)
  673. c.Assert(err, checker.IsNil, check.Commentf(string(out)))
  674. c.Assert(status, checker.Equals, http.StatusOK, check.Commentf(string(out)))
  675. c.Assert(json.Unmarshal(out, &r2), checker.IsNil)
  676. c.Assert(r2.Scope, checker.Equals, "swarm")
  677. }
  678. // Test case for 30178
  679. func (s *DockerSwarmSuite) TestAPISwarmHealthcheckNone(c *check.C) {
  680. d := s.AddDaemon(c, true, true)
  681. out, err := d.Cmd("network", "create", "-d", "overlay", "lb")
  682. c.Assert(err, checker.IsNil, check.Commentf(out))
  683. instances := 1
  684. d.CreateService(c, simpleTestService, setInstances(instances), func(s *swarm.Service) {
  685. s.Spec.TaskTemplate.ContainerSpec.Healthcheck = &container.HealthConfig{}
  686. s.Spec.TaskTemplate.Networks = []swarm.NetworkAttachmentConfig{
  687. {Target: "lb"},
  688. }
  689. })
  690. waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances)
  691. containers := d.ActiveContainers()
  692. out, err = d.Cmd("exec", containers[0], "ping", "-c1", "-W3", "top")
  693. c.Assert(err, checker.IsNil, check.Commentf(out))
  694. }