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