swarm.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. package daemon
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/docker/docker/api/types/swarm"
  6. "github.com/gotestyourself/gotestyourself/assert"
  7. "github.com/pkg/errors"
  8. )
  9. const (
  10. // DefaultSwarmPort is the default port use for swarm in the tests
  11. DefaultSwarmPort = 2477
  12. defaultSwarmListenAddr = "0.0.0.0"
  13. )
  14. // StartAndSwarmInit starts the daemon (with busybox) and init the swarm
  15. func (d *Daemon) StartAndSwarmInit(t testingT) {
  16. // avoid networking conflicts
  17. args := []string{"--iptables=false", "--swarm-default-advertise-addr=lo"}
  18. d.StartWithBusybox(t, args...)
  19. d.SwarmInit(t, swarm.InitRequest{})
  20. }
  21. // StartAndSwarmJoin starts the daemon (with busybox) and join the specified swarm as worker or manager
  22. func (d *Daemon) StartAndSwarmJoin(t testingT, leader *Daemon, manager bool) {
  23. // avoid networking conflicts
  24. args := []string{"--iptables=false", "--swarm-default-advertise-addr=lo"}
  25. d.StartWithBusybox(t, args...)
  26. tokens := leader.JoinTokens(t)
  27. token := tokens.Worker
  28. if manager {
  29. token = tokens.Manager
  30. }
  31. d.SwarmJoin(t, swarm.JoinRequest{
  32. RemoteAddrs: []string{leader.SwarmListenAddr()},
  33. JoinToken: token,
  34. })
  35. }
  36. // SpecConstructor defines a swarm spec constructor
  37. type SpecConstructor func(*swarm.Spec)
  38. // SwarmListenAddr returns the listen-addr used for the daemon
  39. func (d *Daemon) SwarmListenAddr() string {
  40. return fmt.Sprintf("%s:%d", d.swarmListenAddr, d.SwarmPort)
  41. }
  42. // NodeID returns the swarm mode node ID
  43. func (d *Daemon) NodeID() string {
  44. return d.CachedInfo.Swarm.NodeID
  45. }
  46. // SwarmInit initializes a new swarm cluster.
  47. func (d *Daemon) SwarmInit(t assert.TestingT, req swarm.InitRequest) {
  48. if req.ListenAddr == "" {
  49. req.ListenAddr = fmt.Sprintf("%s:%d", d.swarmListenAddr, d.SwarmPort)
  50. }
  51. cli := d.NewClientT(t)
  52. defer cli.Close()
  53. _, err := cli.SwarmInit(context.Background(), req)
  54. assert.NilError(t, err, "initializing swarm")
  55. d.CachedInfo = d.Info(t)
  56. }
  57. // SwarmJoin joins a daemon to an existing cluster.
  58. func (d *Daemon) SwarmJoin(t assert.TestingT, req swarm.JoinRequest) {
  59. if req.ListenAddr == "" {
  60. req.ListenAddr = fmt.Sprintf("%s:%d", d.swarmListenAddr, d.SwarmPort)
  61. }
  62. cli := d.NewClientT(t)
  63. defer cli.Close()
  64. err := cli.SwarmJoin(context.Background(), req)
  65. assert.NilError(t, err, "initializing swarm")
  66. d.CachedInfo = d.Info(t)
  67. }
  68. // SwarmLeave forces daemon to leave current cluster.
  69. func (d *Daemon) SwarmLeave(force bool) error {
  70. cli, err := d.NewClient()
  71. if err != nil {
  72. return fmt.Errorf("leaving swarm: failed to create client %v", err)
  73. }
  74. defer cli.Close()
  75. err = cli.SwarmLeave(context.Background(), force)
  76. if err != nil {
  77. err = fmt.Errorf("leaving swarm: %v", err)
  78. }
  79. return err
  80. }
  81. // SwarmInfo returns the swarm information of the daemon
  82. func (d *Daemon) SwarmInfo(t assert.TestingT) swarm.Info {
  83. cli := d.NewClientT(t)
  84. info, err := cli.Info(context.Background())
  85. assert.NilError(t, err, "get swarm info")
  86. return info.Swarm
  87. }
  88. // SwarmUnlock tries to unlock a locked swarm
  89. func (d *Daemon) SwarmUnlock(req swarm.UnlockRequest) error {
  90. cli, err := d.NewClient()
  91. if err != nil {
  92. return fmt.Errorf("unlocking swarm: failed to create client %v", err)
  93. }
  94. defer cli.Close()
  95. err = cli.SwarmUnlock(context.Background(), req)
  96. if err != nil {
  97. err = errors.Wrap(err, "unlocking swarm")
  98. }
  99. return err
  100. }
  101. // GetSwarm returns the current swarm object
  102. func (d *Daemon) GetSwarm(t assert.TestingT) swarm.Swarm {
  103. cli := d.NewClientT(t)
  104. defer cli.Close()
  105. sw, err := cli.SwarmInspect(context.Background())
  106. assert.NilError(t, err)
  107. return sw
  108. }
  109. // UpdateSwarm updates the current swarm object with the specified spec constructors
  110. func (d *Daemon) UpdateSwarm(t assert.TestingT, f ...SpecConstructor) {
  111. cli := d.NewClientT(t)
  112. defer cli.Close()
  113. sw := d.GetSwarm(t)
  114. for _, fn := range f {
  115. fn(&sw.Spec)
  116. }
  117. err := cli.SwarmUpdate(context.Background(), sw.Version, sw.Spec, swarm.UpdateFlags{})
  118. assert.NilError(t, err)
  119. }
  120. // RotateTokens update the swarm to rotate tokens
  121. func (d *Daemon) RotateTokens(t assert.TestingT) {
  122. cli := d.NewClientT(t)
  123. defer cli.Close()
  124. sw, err := cli.SwarmInspect(context.Background())
  125. assert.NilError(t, err)
  126. flags := swarm.UpdateFlags{
  127. RotateManagerToken: true,
  128. RotateWorkerToken: true,
  129. }
  130. err = cli.SwarmUpdate(context.Background(), sw.Version, sw.Spec, flags)
  131. assert.NilError(t, err)
  132. }
  133. // JoinTokens returns the current swarm join tokens
  134. func (d *Daemon) JoinTokens(t assert.TestingT) swarm.JoinTokens {
  135. cli := d.NewClientT(t)
  136. defer cli.Close()
  137. sw, err := cli.SwarmInspect(context.Background())
  138. assert.NilError(t, err)
  139. return sw.JoinTokens
  140. }