swarm.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  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. d.StartNode(t)
  43. tokens := leader.JoinTokens(t)
  44. token := tokens.Worker
  45. if manager {
  46. token = tokens.Manager
  47. }
  48. d.SwarmJoin(t, swarm.JoinRequest{
  49. RemoteAddrs: []string{leader.SwarmListenAddr()},
  50. JoinToken: token,
  51. })
  52. }
  53. // SpecConstructor defines a swarm spec constructor
  54. type SpecConstructor func(*swarm.Spec)
  55. // SwarmListenAddr returns the listen-addr used for the daemon
  56. func (d *Daemon) SwarmListenAddr() string {
  57. return fmt.Sprintf("%s:%d", d.swarmListenAddr, d.SwarmPort)
  58. }
  59. // NodeID returns the swarm mode node ID
  60. func (d *Daemon) NodeID() string {
  61. return d.CachedInfo.Swarm.NodeID
  62. }
  63. // SwarmInit initializes a new swarm cluster.
  64. func (d *Daemon) SwarmInit(t assert.TestingT, req swarm.InitRequest) {
  65. if ht, ok := t.(test.HelperT); ok {
  66. ht.Helper()
  67. }
  68. if req.ListenAddr == "" {
  69. req.ListenAddr = fmt.Sprintf("%s:%d", d.swarmListenAddr, d.SwarmPort)
  70. }
  71. if req.DefaultAddrPool == nil {
  72. req.DefaultAddrPool = d.DefaultAddrPool
  73. req.SubnetSize = d.SubnetSize
  74. }
  75. cli := d.NewClientT(t)
  76. defer cli.Close()
  77. _, err := cli.SwarmInit(context.Background(), req)
  78. assert.NilError(t, err, "initializing swarm")
  79. d.CachedInfo = d.Info(t)
  80. }
  81. // SwarmJoin joins a daemon to an existing cluster.
  82. func (d *Daemon) SwarmJoin(t assert.TestingT, req swarm.JoinRequest) {
  83. if ht, ok := t.(test.HelperT); ok {
  84. ht.Helper()
  85. }
  86. if req.ListenAddr == "" {
  87. req.ListenAddr = fmt.Sprintf("%s:%d", d.swarmListenAddr, d.SwarmPort)
  88. }
  89. cli := d.NewClientT(t)
  90. defer cli.Close()
  91. err := cli.SwarmJoin(context.Background(), req)
  92. assert.NilError(t, err, "initializing swarm")
  93. d.CachedInfo = d.Info(t)
  94. }
  95. // SwarmLeave forces daemon to leave current cluster.
  96. func (d *Daemon) SwarmLeave(force bool) error {
  97. cli, err := d.NewClient()
  98. if err != nil {
  99. return fmt.Errorf("leaving swarm: failed to create client %v", err)
  100. }
  101. defer cli.Close()
  102. err = cli.SwarmLeave(context.Background(), force)
  103. if err != nil {
  104. err = fmt.Errorf("leaving swarm: %v", err)
  105. }
  106. return err
  107. }
  108. // SwarmInfo returns the swarm information of the daemon
  109. func (d *Daemon) SwarmInfo(t assert.TestingT) swarm.Info {
  110. if ht, ok := t.(test.HelperT); ok {
  111. ht.Helper()
  112. }
  113. cli := d.NewClientT(t)
  114. info, err := cli.Info(context.Background())
  115. assert.NilError(t, err, "get swarm info")
  116. return info.Swarm
  117. }
  118. // SwarmUnlock tries to unlock a locked swarm
  119. func (d *Daemon) SwarmUnlock(req swarm.UnlockRequest) error {
  120. cli, err := d.NewClient()
  121. if err != nil {
  122. return fmt.Errorf("unlocking swarm: failed to create client %v", err)
  123. }
  124. defer cli.Close()
  125. err = cli.SwarmUnlock(context.Background(), req)
  126. if err != nil {
  127. err = errors.Wrap(err, "unlocking swarm")
  128. }
  129. return err
  130. }
  131. // GetSwarm returns the current swarm object
  132. func (d *Daemon) GetSwarm(t assert.TestingT) swarm.Swarm {
  133. if ht, ok := t.(test.HelperT); ok {
  134. ht.Helper()
  135. }
  136. cli := d.NewClientT(t)
  137. defer cli.Close()
  138. sw, err := cli.SwarmInspect(context.Background())
  139. assert.NilError(t, err)
  140. return sw
  141. }
  142. // UpdateSwarm updates the current swarm object with the specified spec constructors
  143. func (d *Daemon) UpdateSwarm(t assert.TestingT, f ...SpecConstructor) {
  144. if ht, ok := t.(test.HelperT); ok {
  145. ht.Helper()
  146. }
  147. cli := d.NewClientT(t)
  148. defer cli.Close()
  149. sw := d.GetSwarm(t)
  150. for _, fn := range f {
  151. fn(&sw.Spec)
  152. }
  153. err := cli.SwarmUpdate(context.Background(), sw.Version, sw.Spec, swarm.UpdateFlags{})
  154. assert.NilError(t, err)
  155. }
  156. // RotateTokens update the swarm to rotate tokens
  157. func (d *Daemon) RotateTokens(t assert.TestingT) {
  158. if ht, ok := t.(test.HelperT); ok {
  159. ht.Helper()
  160. }
  161. cli := d.NewClientT(t)
  162. defer cli.Close()
  163. sw, err := cli.SwarmInspect(context.Background())
  164. assert.NilError(t, err)
  165. flags := swarm.UpdateFlags{
  166. RotateManagerToken: true,
  167. RotateWorkerToken: true,
  168. }
  169. err = cli.SwarmUpdate(context.Background(), sw.Version, sw.Spec, flags)
  170. assert.NilError(t, err)
  171. }
  172. // JoinTokens returns the current swarm join tokens
  173. func (d *Daemon) JoinTokens(t assert.TestingT) swarm.JoinTokens {
  174. if ht, ok := t.(test.HelperT); ok {
  175. ht.Helper()
  176. }
  177. cli := d.NewClientT(t)
  178. defer cli.Close()
  179. sw, err := cli.SwarmInspect(context.Background())
  180. assert.NilError(t, err)
  181. return sw.JoinTokens
  182. }