swarm.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. package daemon
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/docker/docker/api/types/swarm"
  6. "github.com/docker/docker/internal/test"
  7. "github.com/pkg/errors"
  8. "gotest.tools/assert"
  9. )
  10. const (
  11. // DefaultSwarmPort is the default port use for swarm in the tests
  12. DefaultSwarmPort = 2477
  13. defaultSwarmListenAddr = "0.0.0.0"
  14. )
  15. var (
  16. startArgs = []string{"--iptables=false", "--swarm-default-advertise-addr=lo"}
  17. )
  18. // StartNode starts daemon to be used as a swarm node
  19. func (d *Daemon) StartNode(t testingT) {
  20. if ht, ok := t.(test.HelperT); ok {
  21. ht.Helper()
  22. }
  23. // avoid networking conflicts
  24. d.StartWithBusybox(t, startArgs...)
  25. }
  26. // RestartNode restarts a daemon to be used as a swarm node
  27. func (d *Daemon) RestartNode(t testingT) {
  28. if ht, ok := t.(test.HelperT); ok {
  29. ht.Helper()
  30. }
  31. // avoid networking conflicts
  32. d.Stop(t)
  33. d.StartWithBusybox(t, startArgs...)
  34. }
  35. // StartAndSwarmInit starts the daemon (with busybox) and init the swarm
  36. func (d *Daemon) StartAndSwarmInit(t testingT) {
  37. d.StartNode(t)
  38. d.SwarmInit(t, swarm.InitRequest{})
  39. }
  40. // StartAndSwarmJoin starts the daemon (with busybox) and join the specified swarm as worker or manager
  41. func (d *Daemon) StartAndSwarmJoin(t testingT, leader *Daemon, manager bool) {
  42. if th, ok := t.(test.HelperT); ok {
  43. th.Helper()
  44. }
  45. d.StartNode(t)
  46. tokens := leader.JoinTokens(t)
  47. token := tokens.Worker
  48. if manager {
  49. token = tokens.Manager
  50. }
  51. t.Logf("[%s] joining swarm manager [%s]@%s, swarm listen addr %s", d.id, leader.id, leader.SwarmListenAddr(), d.SwarmListenAddr())
  52. d.SwarmJoin(t, swarm.JoinRequest{
  53. RemoteAddrs: []string{leader.SwarmListenAddr()},
  54. JoinToken: token,
  55. })
  56. }
  57. // SpecConstructor defines a swarm spec constructor
  58. type SpecConstructor func(*swarm.Spec)
  59. // SwarmListenAddr returns the listen-addr used for the daemon
  60. func (d *Daemon) SwarmListenAddr() string {
  61. return fmt.Sprintf("%s:%d", d.swarmListenAddr, d.SwarmPort)
  62. }
  63. // NodeID returns the swarm mode node ID
  64. func (d *Daemon) NodeID() string {
  65. return d.CachedInfo.Swarm.NodeID
  66. }
  67. // SwarmInit initializes a new swarm cluster.
  68. func (d *Daemon) SwarmInit(t assert.TestingT, req swarm.InitRequest) {
  69. if ht, ok := t.(test.HelperT); ok {
  70. ht.Helper()
  71. }
  72. if req.ListenAddr == "" {
  73. req.ListenAddr = fmt.Sprintf("%s:%d", d.swarmListenAddr, d.SwarmPort)
  74. }
  75. if req.DefaultAddrPool == nil {
  76. req.DefaultAddrPool = d.DefaultAddrPool
  77. req.SubnetSize = d.SubnetSize
  78. }
  79. if d.DataPathPort > 0 {
  80. req.DataPathPort = d.DataPathPort
  81. }
  82. cli := d.NewClientT(t)
  83. defer cli.Close()
  84. _, err := cli.SwarmInit(context.Background(), req)
  85. assert.NilError(t, err, "initializing swarm")
  86. d.CachedInfo = d.Info(t)
  87. }
  88. // SwarmJoin joins a daemon to an existing cluster.
  89. func (d *Daemon) SwarmJoin(t assert.TestingT, req swarm.JoinRequest) {
  90. if ht, ok := t.(test.HelperT); ok {
  91. ht.Helper()
  92. }
  93. if req.ListenAddr == "" {
  94. req.ListenAddr = fmt.Sprintf("%s:%d", d.swarmListenAddr, d.SwarmPort)
  95. }
  96. cli := d.NewClientT(t)
  97. defer cli.Close()
  98. err := cli.SwarmJoin(context.Background(), req)
  99. assert.NilError(t, err, "[%s] joining swarm", d.id)
  100. d.CachedInfo = d.Info(t)
  101. }
  102. // SwarmLeave forces daemon to leave current cluster.
  103. //
  104. // The passed in TestingT is only used to validate that the client was successfully created
  105. // Some tests rely on error checking the result of the actual unlock, so allow
  106. // the error to be returned.
  107. func (d *Daemon) SwarmLeave(t assert.TestingT, force bool) error {
  108. cli := d.NewClientT(t)
  109. defer cli.Close()
  110. return cli.SwarmLeave(context.Background(), force)
  111. }
  112. // SwarmInfo returns the swarm information of the daemon
  113. func (d *Daemon) SwarmInfo(t assert.TestingT) swarm.Info {
  114. if ht, ok := t.(test.HelperT); ok {
  115. ht.Helper()
  116. }
  117. cli := d.NewClientT(t)
  118. info, err := cli.Info(context.Background())
  119. assert.NilError(t, err, "get swarm info")
  120. return info.Swarm
  121. }
  122. // SwarmUnlock tries to unlock a locked swarm
  123. //
  124. // The passed in TestingT is only used to validate that the client was successfully created
  125. // Some tests rely on error checking the result of the actual unlock, so allow
  126. // the error to be returned.
  127. func (d *Daemon) SwarmUnlock(t assert.TestingT, req swarm.UnlockRequest) error {
  128. cli := d.NewClientT(t)
  129. defer cli.Close()
  130. err := cli.SwarmUnlock(context.Background(), req)
  131. if err != nil {
  132. err = errors.Wrap(err, "unlocking swarm")
  133. }
  134. return err
  135. }
  136. // GetSwarm returns the current swarm object
  137. func (d *Daemon) GetSwarm(t assert.TestingT) swarm.Swarm {
  138. if ht, ok := t.(test.HelperT); ok {
  139. ht.Helper()
  140. }
  141. cli := d.NewClientT(t)
  142. defer cli.Close()
  143. sw, err := cli.SwarmInspect(context.Background())
  144. assert.NilError(t, err)
  145. return sw
  146. }
  147. // UpdateSwarm updates the current swarm object with the specified spec constructors
  148. func (d *Daemon) UpdateSwarm(t assert.TestingT, f ...SpecConstructor) {
  149. if ht, ok := t.(test.HelperT); ok {
  150. ht.Helper()
  151. }
  152. cli := d.NewClientT(t)
  153. defer cli.Close()
  154. sw := d.GetSwarm(t)
  155. for _, fn := range f {
  156. fn(&sw.Spec)
  157. }
  158. err := cli.SwarmUpdate(context.Background(), sw.Version, sw.Spec, swarm.UpdateFlags{})
  159. assert.NilError(t, err)
  160. }
  161. // RotateTokens update the swarm to rotate tokens
  162. func (d *Daemon) RotateTokens(t assert.TestingT) {
  163. if ht, ok := t.(test.HelperT); ok {
  164. ht.Helper()
  165. }
  166. cli := d.NewClientT(t)
  167. defer cli.Close()
  168. sw, err := cli.SwarmInspect(context.Background())
  169. assert.NilError(t, err)
  170. flags := swarm.UpdateFlags{
  171. RotateManagerToken: true,
  172. RotateWorkerToken: true,
  173. }
  174. err = cli.SwarmUpdate(context.Background(), sw.Version, sw.Spec, flags)
  175. assert.NilError(t, err)
  176. }
  177. // JoinTokens returns the current swarm join tokens
  178. func (d *Daemon) JoinTokens(t assert.TestingT) swarm.JoinTokens {
  179. if ht, ok := t.(test.HelperT); ok {
  180. ht.Helper()
  181. }
  182. cli := d.NewClientT(t)
  183. defer cli.Close()
  184. sw, err := cli.SwarmInspect(context.Background())
  185. assert.NilError(t, err)
  186. return sw.JoinTokens
  187. }