docker_api_swarm_test.go 32 KB

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