swarm.go 4.4 KB

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