docker_api_swarm_test.go 33 KB

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