docker_api_swarm_test.go 33 KB

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