Skip to content

Commit

Permalink
Global Default Address Pool feature support
Browse files Browse the repository at this point in the history
This feature brings new attribute/option for swarm init command.
default-addr-pool will take string input which can be in below format.
"CIDR,CIDR,CIDR...:SUBNET-SIZE".
Signed-off-by: selansen <elango.siva@docker.com>
  • Loading branch information
selansen committed Aug 21, 2018
1 parent 466e1b0 commit 53af407
Show file tree
Hide file tree
Showing 23 changed files with 289 additions and 92 deletions.
2 changes: 1 addition & 1 deletion cli/command/image/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
excludes = build.TrimBuildFilesFromExcludes(excludes, relDockerfile, options.dockerfileFromStdin())
buildCtx, err = archive.TarWithOptions(contextDir, &archive.TarOptions{
ExcludePatterns: excludes,
ChownOpts: &idtools.IDPair{UID: 0, GID: 0},
ChownOpts: &idtools.Identity{UID: 0, GID: 0},
})
if err != nil {
return err
Expand Down
66 changes: 66 additions & 0 deletions cli/command/swarm/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package swarm
import (
"context"
"fmt"
"net"
"strconv"
"strings"

"github.com/docker/cli/cli"
Expand All @@ -21,6 +23,7 @@ type initOptions struct {
dataPathAddr string
forceNewCluster bool
availability string
defaultAddrPool string
}

func newInitCommand(dockerCli command.Cli) *cobra.Command {
Expand All @@ -45,21 +48,84 @@ func newInitCommand(dockerCli command.Cli) *cobra.Command {
flags.BoolVar(&opts.forceNewCluster, "force-new-cluster", false, "Force create a new cluster from current state")
flags.BoolVar(&opts.autolock, flagAutolock, false, "Enable manager autolocking (requiring an unlock key to start a stopped manager)")
flags.StringVar(&opts.availability, flagAvailability, "active", `Availability of the node ("active"|"pause"|"drain")`)
flags.StringVar(&opts.defaultAddrPool, flagDefaultAddrPool, "", "List of default subnet addresses followed by subnet size (format: <subnet,subnet,..:subnet-size)")
flags.SetAnnotation(flagDefaultAddrPool, "version", []string{"1.39"})
addSwarmFlags(flags, &opts.swarmOptions)
return cmd
}

// getDefaultAddrPool extracts info from address pool string and fills PoolsOpt struct
func getDefaultAddrPool(defaultAddrPool string) ([]string, int, error) {
var (
size int
err error
)
if defaultAddrPool == "" {
// defaultAddrPool is not defined
return nil, 0, nil
}

result := strings.Split(defaultAddrPool, ":")
if len(result) > 2 {
return nil, 0, fmt.Errorf("Invalid default address pool format. Expected format CIDR[,CIDR]*:SUBNET-SIZE")
}
// if size is not specified default size is 24
size = 24
if len(result) == 2 {
// trim leading and trailing white spaces
result[1] = strings.TrimSpace(result[1])

// get the size from the slice
size, err = strconv.Atoi(result[1])

if err != nil || size <= 0 {
return nil, 0, fmt.Errorf("error in DefaultAddressPool subnet size %s", defaultAddrPool)
}
}

// get subnet list
subnetlist := strings.Split(result[0], ",")

for i := range subnetlist {
// trim leading and trailing white spaces
subnetlist[i] = strings.TrimSpace(subnetlist[i])
_, b, err := net.ParseCIDR(subnetlist[i])
if err != nil {
return nil, 0, fmt.Errorf("invalid base pool %q: %v", subnetlist[i], err)
}
ones, _ := b.Mask.Size()
if size < ones {
return nil, 0, fmt.Errorf("subnet size is too small for pool: %d", size)
}
}
return subnetlist, size, nil
}

func runInit(dockerCli command.Cli, flags *pflag.FlagSet, opts initOptions) error {
var (
size int
defaultAddrPool []string
err error
)
client := dockerCli.Client()
ctx := context.Background()

if opts.defaultAddrPool != "" {
defaultAddrPool, size, err = getDefaultAddrPool(opts.defaultAddrPool)
if err != nil {
return err
}
}

req := swarm.InitRequest{
ListenAddr: opts.listenAddr.String(),
AdvertiseAddr: opts.advertiseAddr,
DataPathAddr: opts.dataPathAddr,
DefaultAddrPool: defaultAddrPool,
ForceNewCluster: opts.forceNewCluster,
Spec: opts.swarmOptions.ToSpec(flags),
AutoLockManagers: opts.swarmOptions.autolock,
SubnetSize: uint32(size),
}
if flags.Changed(flagAvailability) {
availability := swarm.NodeAvailability(strings.ToLower(opts.availability))
Expand Down
26 changes: 26 additions & 0 deletions cli/command/swarm/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/docker/docker/api/types/swarm"
"github.com/pkg/errors"
"gotest.tools/assert"
is "gotest.tools/assert/cmp"
"gotest.tools/golden"
)

Expand Down Expand Up @@ -123,3 +124,28 @@ func TestSwarmInit(t *testing.T) {
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("init-%s.golden", tc.name))
}
}

func TestGetDefaultAddrPool(t *testing.T) {
// Test only CIDR input and make sure default subnet size is returned
addrList, size, err := getDefaultAddrPool("20.20.0.0/16,30.30.0.0/16")
assert.NilError(t, err)
assert.Check(t, is.Equal(size, 24))
assert.Check(t, is.Equal(len(addrList), 2))

//Pass wrong syntax params
_, _, err = getDefaultAddrPool("20.20.0.0/16;30.30.0.0/16;24")
assert.Check(t, err != nil)

// Pass subnet size smaller than subnet
_, _, err = getDefaultAddrPool("20.20.0.0/24,30.30.0.0/24:20")
assert.Check(t, err != nil)

// Pass CIDR and subnet with white space and make sure everything works
addrList, _, err = getDefaultAddrPool(" 20.20.0.0/20 , 30.30.0.0/20 , 40.40.0.0/16 : 24")
assert.NilError(t, err)
assert.Check(t, is.Equal(len(addrList), 3))

// Pass CIDR just with IP address and it should fail
_, _, err = getDefaultAddrPool(" 20.20.0.0, 30.30.0.0/20 : 24")
assert.Check(t, err != nil)
}
1 change: 1 addition & 0 deletions cli/command/swarm/opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const (
flagListenAddr = "listen-addr"
flagAdvertiseAddr = "advertise-addr"
flagDataPathAddr = "data-path-addr"
flagDefaultAddrPool = "default-addr-pool"
flagQuiet = "quiet"
flagRotate = "rotate"
flagToken = "token"
Expand Down
13 changes: 13 additions & 0 deletions cli/command/system/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ func prettyPrintInfo(dockerCli command.Cli, info types.Info) error {
return nil
}

// nolint: gocyclo
func printSwarmInfo(dockerCli command.Cli, info types.Info) {
if info.Swarm.LocalNodeState == swarm.LocalNodeStateInactive || info.Swarm.LocalNodeState == swarm.LocalNodeStateLocked {
return
Expand All @@ -261,7 +262,19 @@ func printSwarmInfo(dockerCli command.Cli, info types.Info) {
fmt.Fprintln(dockerCli.Out(), " ClusterID:", info.Swarm.Cluster.ID)
fmt.Fprintln(dockerCli.Out(), " Managers:", info.Swarm.Managers)
fmt.Fprintln(dockerCli.Out(), " Nodes:", info.Swarm.Nodes)
var strAddrPool strings.Builder
if info.Swarm.Cluster.DefaultAddrPool != nil {
for _, p := range info.Swarm.Cluster.DefaultAddrPool {
strAddrPool.WriteString(p + " ")
}
fmt.Fprintln(dockerCli.Out(), " Default Address Pool:", strAddrPool.String())
fmt.Fprintln(dockerCli.Out(), " SubnetSize:", info.Swarm.Cluster.SubnetSize)
} else {
fmt.Fprintln(dockerCli.Out(), " Default Address Pool:", "10.0.0.0/8")
fmt.Fprintln(dockerCli.Out(), " SubnetSize: 24")
}
fmt.Fprintln(dockerCli.Out(), " Orchestration:")

taskHistoryRetentionLimit := int64(0)
if info.Swarm.Cluster.Spec.Orchestration.TaskHistoryRetentionLimit != nil {
taskHistoryRetentionLimit = *info.Swarm.Cluster.Spec.Orchestration.TaskHistoryRetentionLimit
Expand Down
2 changes: 2 additions & 0 deletions cli/command/system/info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ PQQDAgNIADBFAiEAo9fTQNM5DP9bHVcTJYfl2Cay1bFu1E+lnpmN+EYJfeACIGKH
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPLs15vJQnJSNYkMFR2dmhXoYHEQYo7hNk80PCfEPElxR0tVoHtYZrj8MutZR+xWCHUkaKTZVOIu5MwDW0uU08w=="),
},
RootRotationInProgress: false,
DefaultAddrPool: []string{"10.0.0.0/8"},
SubnetSize: 24,
},
}

Expand Down
2 changes: 2 additions & 0 deletions cli/command/system/testdata/docker-info-with-swarm.golden
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Swarm: active
ClusterID: 9vs5ygs0gguyyec4iqf2314c0
Managers: 1
Nodes: 1
Default Address Pool: 10.0.0.0/8
SubnetSize: 24
Orchestration:
Task History Retention Limit: 5
Raft:
Expand Down
4 changes: 2 additions & 2 deletions contrib/completion/bash/docker
Original file line number Diff line number Diff line change
Expand Up @@ -3697,7 +3697,7 @@ _docker_swarm_init() {
COMPREPLY=( $( compgen -W "active drain pause" -- "$cur" ) )
return
;;
--cert-expiry|--dispatcher-heartbeat|--external-ca|--max-snapshots|--snapshot-interval|--task-history-limit)
--cert-expiry|--default-addr-pool|--dispatcher-heartbeat|--external-ca|--max-snapshots|--snapshot-interval|--task-history-limit )
return
;;
--data-path-addr)
Expand All @@ -3717,7 +3717,7 @@ _docker_swarm_init() {

case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--advertise-addr --autolock --availability --cert-expiry --data-path-addr --dispatcher-heartbeat --external-ca --force-new-cluster --help --listen-addr --max-snapshots --snapshot-interval --task-history-limit" -- "$cur" ) )
COMPREPLY=( $( compgen -W "--advertise-addr --autolock --availability --cert-expiry --data-path-addr --default-addr-pool --dispatcher-heartbeat --external-ca --force-new-cluster --help --listen-addr --max-snapshots --snapshot-interval --task-history-limit" -- "$cur" ) )
;;
esac
}
Expand Down
1 change: 1 addition & 0 deletions contrib/completion/zsh/_docker
Original file line number Diff line number Diff line change
Expand Up @@ -2285,6 +2285,7 @@ __docker_swarm_subcommand() {
$opts_help \
"($help)--advertise-addr=[Advertised address]:ip\:port: " \
"($help)--data-path-addr=[Data path IP or interface]:ip " \
"($help)--default-addr-pool=[default subnet addresses]:subnet-size " \
"($help)--autolock[Enable manager autolocking]" \
"($help)--availability=[Availability of the node]:availability:(active drain pause)" \
"($help)--cert-expiry=[Validity period for node certificates]:duration: " \
Expand Down
7 changes: 7 additions & 0 deletions docs/reference/commandline/swarm_init.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Options:
--availability string Availability of the node ("active"|"pause"|"drain") (default "active")
--cert-expiry duration Validity period for node certificates (ns|us|ms|s|m|h) (default 2160h0m0s)
--data-path-addr string Address or interface to use for data path traffic (format: <ip|interface>)
--default-addr-pool string List of default subnet addresses followed by subnet size (format: <cidr[,cidr]*:subnet-size>)
--dispatcher-heartbeat duration Dispatcher heartbeat period (ns|us|ms|s|m|h) (default 5s)
--external-ca external-ca Specifications of one or more certificate signing endpoints
--force-new-cluster Force create a new cluster from current state
Expand Down Expand Up @@ -128,6 +129,12 @@ management traffic of the cluster.
If unspecified, Docker will use the same IP address or interface that is used for the
advertise address.

### `--default-addr-pool`
This flag specifies default subnet pools for global scope networks. If subnet size is not
specified then default value 24 will be used.
If unspecified, Docker will use the predefined subnets as it works on older releases.
Format example is `default-addr-pool 30.30.0.0/16,40.40.0.0/16:24`

### `--task-history-limit`

This flag sets up task history retention limit.
Expand Down
2 changes: 1 addition & 1 deletion vendor.conf
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ github.com/cpuguy83/go-md2man v1.0.8
github.com/davecgh/go-spew 346938d642f2ec3594ed81d874461961cd0faa76 # v1.1.0
github.com/dgrijalva/jwt-go a2c85815a77d0f951e33ba4db5ae93629a1530af
github.com/docker/distribution 83389a148052d74ac602f5f1d62f86ff2f3c4aa5
github.com/docker/docker a7ff19d69a90dfe152abd146221c8b9b46a0903d
github.com/docker/docker 1800883bd16664846db1572b8c8fbe8c85892cee
github.com/docker/docker-credential-helpers 5241b46610f2491efdf9d1c85f1ddf5b02f6d962
# the docker/go package contains a customized version of canonical/json
# and is used by Notary. The package is periodically rebased on current Go versions.
Expand Down
8 changes: 7 additions & 1 deletion vendor/github.com/docker/docker/api/types/swarm/swarm.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions vendor/github.com/docker/docker/api/types/types.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion vendor/github.com/docker/docker/client/ping.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 53af407

Please sign in to comment.