1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00
moby--moby/internal/test/daemon/swarm.go
Kir Kolyshkin 2ed512c7fa integration-cli/Test*Swarm*: use same args on restart
When starting docker daemons for swarm testing, we disable iptables
and use lo for communication (in order to avoid network conflicts).

The problem is, these options are lost on restart, that can lead
to any sorts of network conflicts and thus connectivity issues
between swarm nodes.

Fix this. This does not fix issues with swarm test failures, but
it seems they appear are less often after this one.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2018-11-01 13:25:12 -07:00

210 lines
5.3 KiB
Go

package daemon
import (
"context"
"fmt"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/internal/test"
"github.com/pkg/errors"
"gotest.tools/assert"
)
const (
// DefaultSwarmPort is the default port use for swarm in the tests
DefaultSwarmPort = 2477
defaultSwarmListenAddr = "0.0.0.0"
)
var (
startArgs = []string{"--iptables=false", "--swarm-default-advertise-addr=lo"}
)
// StartNode starts daemon to be used as a swarm node
func (d *Daemon) StartNode(t testingT) {
if ht, ok := t.(test.HelperT); ok {
ht.Helper()
}
// avoid networking conflicts
d.StartWithBusybox(t, startArgs...)
}
// RestartNode restarts a daemon to be used as a swarm node
func (d *Daemon) RestartNode(t testingT) {
if ht, ok := t.(test.HelperT); ok {
ht.Helper()
}
// avoid networking conflicts
d.Stop(t)
d.StartWithBusybox(t, startArgs...)
}
// StartAndSwarmInit starts the daemon (with busybox) and init the swarm
func (d *Daemon) StartAndSwarmInit(t testingT) {
d.StartNode(t)
d.SwarmInit(t, swarm.InitRequest{})
}
// StartAndSwarmJoin starts the daemon (with busybox) and join the specified swarm as worker or manager
func (d *Daemon) StartAndSwarmJoin(t testingT, leader *Daemon, manager bool) {
d.StartNode(t)
tokens := leader.JoinTokens(t)
token := tokens.Worker
if manager {
token = tokens.Manager
}
d.SwarmJoin(t, swarm.JoinRequest{
RemoteAddrs: []string{leader.SwarmListenAddr()},
JoinToken: token,
})
}
// SpecConstructor defines a swarm spec constructor
type SpecConstructor func(*swarm.Spec)
// SwarmListenAddr returns the listen-addr used for the daemon
func (d *Daemon) SwarmListenAddr() string {
return fmt.Sprintf("%s:%d", d.swarmListenAddr, d.SwarmPort)
}
// NodeID returns the swarm mode node ID
func (d *Daemon) NodeID() string {
return d.CachedInfo.Swarm.NodeID
}
// SwarmInit initializes a new swarm cluster.
func (d *Daemon) SwarmInit(t assert.TestingT, req swarm.InitRequest) {
if ht, ok := t.(test.HelperT); ok {
ht.Helper()
}
if req.ListenAddr == "" {
req.ListenAddr = fmt.Sprintf("%s:%d", d.swarmListenAddr, d.SwarmPort)
}
if req.DefaultAddrPool == nil {
req.DefaultAddrPool = d.DefaultAddrPool
req.SubnetSize = d.SubnetSize
}
cli := d.NewClientT(t)
defer cli.Close()
_, err := cli.SwarmInit(context.Background(), req)
assert.NilError(t, err, "initializing swarm")
d.CachedInfo = d.Info(t)
}
// SwarmJoin joins a daemon to an existing cluster.
func (d *Daemon) SwarmJoin(t assert.TestingT, req swarm.JoinRequest) {
if ht, ok := t.(test.HelperT); ok {
ht.Helper()
}
if req.ListenAddr == "" {
req.ListenAddr = fmt.Sprintf("%s:%d", d.swarmListenAddr, d.SwarmPort)
}
cli := d.NewClientT(t)
defer cli.Close()
err := cli.SwarmJoin(context.Background(), req)
assert.NilError(t, err, "initializing swarm")
d.CachedInfo = d.Info(t)
}
// SwarmLeave forces daemon to leave current cluster.
func (d *Daemon) SwarmLeave(force bool) error {
cli, err := d.NewClient()
if err != nil {
return fmt.Errorf("leaving swarm: failed to create client %v", err)
}
defer cli.Close()
err = cli.SwarmLeave(context.Background(), force)
if err != nil {
err = fmt.Errorf("leaving swarm: %v", err)
}
return err
}
// SwarmInfo returns the swarm information of the daemon
func (d *Daemon) SwarmInfo(t assert.TestingT) swarm.Info {
if ht, ok := t.(test.HelperT); ok {
ht.Helper()
}
cli := d.NewClientT(t)
info, err := cli.Info(context.Background())
assert.NilError(t, err, "get swarm info")
return info.Swarm
}
// SwarmUnlock tries to unlock a locked swarm
func (d *Daemon) SwarmUnlock(req swarm.UnlockRequest) error {
cli, err := d.NewClient()
if err != nil {
return fmt.Errorf("unlocking swarm: failed to create client %v", err)
}
defer cli.Close()
err = cli.SwarmUnlock(context.Background(), req)
if err != nil {
err = errors.Wrap(err, "unlocking swarm")
}
return err
}
// GetSwarm returns the current swarm object
func (d *Daemon) GetSwarm(t assert.TestingT) swarm.Swarm {
if ht, ok := t.(test.HelperT); ok {
ht.Helper()
}
cli := d.NewClientT(t)
defer cli.Close()
sw, err := cli.SwarmInspect(context.Background())
assert.NilError(t, err)
return sw
}
// UpdateSwarm updates the current swarm object with the specified spec constructors
func (d *Daemon) UpdateSwarm(t assert.TestingT, f ...SpecConstructor) {
if ht, ok := t.(test.HelperT); ok {
ht.Helper()
}
cli := d.NewClientT(t)
defer cli.Close()
sw := d.GetSwarm(t)
for _, fn := range f {
fn(&sw.Spec)
}
err := cli.SwarmUpdate(context.Background(), sw.Version, sw.Spec, swarm.UpdateFlags{})
assert.NilError(t, err)
}
// RotateTokens update the swarm to rotate tokens
func (d *Daemon) RotateTokens(t assert.TestingT) {
if ht, ok := t.(test.HelperT); ok {
ht.Helper()
}
cli := d.NewClientT(t)
defer cli.Close()
sw, err := cli.SwarmInspect(context.Background())
assert.NilError(t, err)
flags := swarm.UpdateFlags{
RotateManagerToken: true,
RotateWorkerToken: true,
}
err = cli.SwarmUpdate(context.Background(), sw.Version, sw.Spec, flags)
assert.NilError(t, err)
}
// JoinTokens returns the current swarm join tokens
func (d *Daemon) JoinTokens(t assert.TestingT) swarm.JoinTokens {
if ht, ok := t.(test.HelperT); ok {
ht.Helper()
}
cli := d.NewClientT(t)
defer cli.Close()
sw, err := cli.SwarmInspect(context.Background())
assert.NilError(t, err)
return sw.JoinTokens
}