Browse code

Support a listen addr without a port, and add tests.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
(cherry picked from commit 595e79b805fd6e96d2e6c8876f7c9734164f5db7)

Daniel Nephin authored on 2016/06/18 04:42:16
Showing 4 changed files
... ...
@@ -22,7 +22,7 @@ type initOptions struct {
22 22
 func newInitCommand(dockerCli *client.DockerCli) *cobra.Command {
23 23
 	var flags *pflag.FlagSet
24 24
 	opts := initOptions{
25
-		listenAddr: NewNodeAddrOption(),
25
+		listenAddr: NewListenAddrOption(),
26 26
 		autoAccept: NewAutoAcceptOption(),
27 27
 	}
28 28
 
... ...
@@ -35,10 +35,10 @@ func newInitCommand(dockerCli *client.DockerCli) *cobra.Command {
35 35
 		},
36 36
 	}
37 37
 
38
-	flags = cmd.Flags()
39
-	flags.Var(&opts.listenAddr, "listen-addr", "Listen address")
40
-	flags.Var(&opts.autoAccept, "auto-accept", "Auto acceptance policy (worker, manager, or none)")
41
-	flags.StringVar(&opts.secret, "secret", "", "Set secret value needed to accept nodes into cluster")
38
+	flags := cmd.Flags()
39
+	flags.Var(&opts.listenAddr, flagListenAddr, "Listen address")
40
+	flags.Var(&opts.autoAccept, flagAutoAccept, "Auto acceptance policy (worker, manager, or none)")
41
+	flags.StringVar(&opts.secret, flagSecret, "", "Set secret value needed to accept nodes into cluster")
42 42
 	flags.BoolVar(&opts.forceNewCluster, "force-new-cluster", false, "Force create a new cluster from current state.")
43 43
 	return cmd
44 44
 }
... ...
@@ -20,7 +20,7 @@ type joinOptions struct {
20 20
 
21 21
 func newJoinCommand(dockerCli *client.DockerCli) *cobra.Command {
22 22
 	opts := joinOptions{
23
-		listenAddr: NodeAddrOption{addr: defaultListenAddr},
23
+		listenAddr: NewListenAddrOption(),
24 24
 	}
25 25
 
26 26
 	cmd := &cobra.Command{
... ...
@@ -34,7 +34,7 @@ func newJoinCommand(dockerCli *client.DockerCli) *cobra.Command {
34 34
 	}
35 35
 
36 36
 	flags := cmd.Flags()
37
-	flags.Var(&opts.listenAddr, "listen-addr", "Listen address")
37
+	flags.Var(&opts.listenAddr, flagListenAddr, "Listen address")
38 38
 	flags.BoolVar(&opts.manager, "manager", false, "Try joining as a manager.")
39 39
 	flags.StringVar(&opts.secret, "secret", "", "Secret for node acceptance")
40 40
 	flags.StringVar(&opts.CACertHash, "ca-hash", "", "Hash of the Root Certificate Authority certificate used for trusted join")
... ...
@@ -2,17 +2,27 @@ package swarm
2 2
 
3 3
 import (
4 4
 	"fmt"
5
+	"net"
6
+	"strconv"
5 7
 	"strings"
6 8
 
7 9
 	"github.com/docker/engine-api/types/swarm"
8 10
 )
9 11
 
10 12
 const (
11
-	defaultListenAddr = "0.0.0.0:2377"
13
+	defaultListenAddr        = "0.0.0.0"
14
+	defaultListenPort uint16 = 2377
12 15
 	// WORKER constant for worker name
13 16
 	WORKER = "WORKER"
14 17
 	// MANAGER constant for manager name
15 18
 	MANAGER = "MANAGER"
19
+
20
+	flagAutoAccept          = "auto-accept"
21
+	flagCertExpiry          = "cert-expiry"
22
+	flagDispatcherHeartbeat = "dispatcher-heartbeat"
23
+	flagListenAddr          = "listen-addr"
24
+	flagSecret              = "secret"
25
+	flagTaskHistoryLimit    = "task-history-limit"
16 26
 )
17 27
 
18 28
 var (
... ...
@@ -25,25 +35,35 @@ var (
25 25
 // NodeAddrOption is a pflag.Value for listen and remote addresses
26 26
 type NodeAddrOption struct {
27 27
 	addr string
28
+	port uint16
28 29
 }
29 30
 
30 31
 // String prints the representation of this flag
31 32
 func (a *NodeAddrOption) String() string {
32
-	return a.addr
33
+	return a.Value()
33 34
 }
34 35
 
35 36
 // Set the value for this flag
36 37
 func (a *NodeAddrOption) Set(value string) error {
37 38
 	if !strings.Contains(value, ":") {
38
-		return fmt.Errorf("Invalid url, a host and port are required")
39
+		a.addr = value
40
+		return nil
41
+	}
42
+
43
+	host, port, err := net.SplitHostPort(value)
44
+	if err != nil {
45
+		return fmt.Errorf("Invalid url, %v", err)
39 46
 	}
40 47
 
41
-	parts := strings.Split(value, ":")
42
-	if len(parts) != 2 {
43
-		return fmt.Errorf("Invalid url, too many colons")
48
+	portInt, err := strconv.ParseUint(port, 10, 16)
49
+	if err != nil {
50
+		return fmt.Errorf("invalid url, %v", err)
44 51
 	}
52
+	a.port = uint16(portInt)
45 53
 
46
-	a.addr = value
54
+	if host != "" {
55
+		a.addr = host
56
+	}
47 57
 	return nil
48 58
 }
49 59
 
... ...
@@ -52,9 +72,19 @@ func (a *NodeAddrOption) Type() string {
52 52
 	return "node-addr"
53 53
 }
54 54
 
55
+// Value returns the value of this option as addr:port
56
+func (a *NodeAddrOption) Value() string {
57
+	return net.JoinHostPort(a.addr, strconv.Itoa(int(a.port)))
58
+}
59
+
55 60
 // NewNodeAddrOption returns a new node address option
56
-func NewNodeAddrOption() NodeAddrOption {
57
-	return NodeAddrOption{addr: defaultListenAddr}
61
+func NewNodeAddrOption(host string, port uint16) NodeAddrOption {
62
+	return NodeAddrOption{addr: host, port: port}
63
+}
64
+
65
+// NewListenAddrOption returns a NodeAddrOption with default values
66
+func NewListenAddrOption() NodeAddrOption {
67
+	return NewNodeAddrOption(defaultListenAddr, defaultListenPort)
58 68
 }
59 69
 
60 70
 // AutoAcceptOption is a value type for auto-accept policy
61 71
new file mode 100644
... ...
@@ -0,0 +1,35 @@
0
+package swarm
1
+
2
+import (
3
+	"testing"
4
+
5
+	"github.com/docker/docker/pkg/testutil/assert"
6
+)
7
+
8
+func TestNodeAddrOptionSetHostAndPort(t *testing.T) {
9
+	opt := NewNodeAddrOption("old", 123)
10
+	addr := "newhost:5555"
11
+	assert.NilError(t, opt.Set(addr))
12
+	assert.Equal(t, opt.addr, "newhost")
13
+	assert.Equal(t, opt.port, uint16(5555))
14
+	assert.Equal(t, opt.Value(), addr)
15
+}
16
+
17
+func TestNodeAddrOptionSetHostOnly(t *testing.T) {
18
+	opt := NewListenAddrOption()
19
+	assert.NilError(t, opt.Set("newhost"))
20
+	assert.Equal(t, opt.addr, "newhost")
21
+	assert.Equal(t, opt.port, defaultListenPort)
22
+}
23
+
24
+func TestNodeAddrOptionSetPortOnly(t *testing.T) {
25
+	opt := NewListenAddrOption()
26
+	assert.NilError(t, opt.Set(":4545"))
27
+	assert.Equal(t, opt.addr, defaultListenAddr)
28
+	assert.Equal(t, opt.port, uint16(4545))
29
+}
30
+
31
+func TestNodeAddrOptionSetInvalidFormat(t *testing.T) {
32
+	opt := NewListenAddrOption()
33
+	assert.Error(t, opt.Set("http://localhost:4545"), "Invalid url")
34
+}