diff --git a/server/config.go b/server/config.go index d09893820e1..2e37b9fe47b 100644 --- a/server/config.go +++ b/server/config.go @@ -445,7 +445,7 @@ func (c *Config) PeerTLSConfig() (TLSConfig, error) { return c.PeerTLSInfo().Config() } -// sanitizeURL will cleanup a host string in the format hostname:port and +// sanitizeURL will cleanup a host string in the format hostname[:port] and // attach a schema. func sanitizeURL(host string, defaultScheme string) (string, error) { // Blank URLs are fine input, just return it @@ -476,14 +476,22 @@ func sanitizeBindAddr(bindAddr string, addr string) (string, error) { return "", err } - ahost, aport, err := net.SplitHostPort(aurl.Host) - if err != nil { - return "", err + // If it is a valid host:port simply return with no further checks. + bhost, bport, err := net.SplitHostPort(bindAddr) + if err == nil && bhost != "" { + return bindAddr, nil + } + + // SplitHostPort makes the host optional, but we don't want that. + if bhost == "" && bport != "" { + return "", fmt.Errorf("IP required can't use a port only") } - // If the listen host isn't set use the advertised host - if bindAddr == "" { - bindAddr = ahost + // bindAddr doesn't have a port if we reach here so take the port from the + // advertised URL. + _, aport, err := net.SplitHostPort(aurl.Host) + if err != nil { + return "", err } return net.JoinHostPort(bindAddr, aport), nil diff --git a/server/config_test.go b/server/config_test.go index 5571773cc5a..00299698350 100644 --- a/server/config_test.go +++ b/server/config_test.go @@ -223,6 +223,29 @@ func TestConfigBindAddrFlag(t *testing.T) { assert.Equal(t, c.BindAddr, "127.0.0.1:4003", "") } +// Ensures that a the Listen Host port overrides the advertised port +func TestConfigBindAddrOverride(t *testing.T) { + c := NewConfig() + assert.Nil(t, c.LoadFlags([]string{"-addr", "127.0.0.1:4009", "-bind-addr", "127.0.0.1:4010"}), "") + assert.Nil(t, c.Sanitize()) + assert.Equal(t, c.BindAddr, "127.0.0.1:4010", "") +} + +// Ensures that a the Listen Host inherits its port from the advertised addr +func TestConfigBindAddrInheritPort(t *testing.T) { + c := NewConfig() + assert.Nil(t, c.LoadFlags([]string{"-addr", "127.0.0.1:4009", "-bind-addr", "127.0.0.1"}), "") + assert.Nil(t, c.Sanitize()) + assert.Equal(t, c.BindAddr, "127.0.0.1:4009", "") +} + +// Ensures that a port only argument errors out +func TestConfigBindAddrErrorOnNoHost(t *testing.T) { + c := NewConfig() + assert.Nil(t, c.LoadFlags([]string{"-addr", "127.0.0.1:4009", "-bind-addr", ":4010"}), "") + assert.Error(t, c.Sanitize()) +} + // Ensures that the peers can be parsed from the environment. func TestConfigPeersEnv(t *testing.T) { withEnv("ETCD_PEERS", "coreos.com:4001,coreos.com:4002", func(c *Config) { diff --git a/server/usage.go b/server/usage.go index 3809fb04b90..e8969c3448e 100644 --- a/server/usage.go +++ b/server/usage.go @@ -31,18 +31,18 @@ Cluster Configuration Options: should match the peer's '-peer-addr' flag. Client Communication Options: - -addr= The public host:port used for client communication. - -bind-addr= The listening hostname used for client communication. - -ca-file= Path to the client CA file. - -cert-file= Path to the client cert file. - -key-file= Path to the client key file. + -addr= The public host:port used for client communication. + -bind-addr= The listening host:port used for client communication. + -ca-file= Path to the client CA file. + -cert-file= Path to the client cert file. + -key-file= Path to the client key file. Peer Communication Options: - -peer-addr= The public host:port used for peer communication. - -peer-bind-addr= The listening hostname used for peer communication. - -peer-ca-file= Path to the peer CA file. - -peer-cert-file= Path to the peer cert file. - -peer-key-file= Path to the peer key file. + -peer-addr= The public host:port used for peer communication. + -peer-bind-addr= The listening host:port used for peer communication. + -peer-ca-file= Path to the peer CA file. + -peer-cert-file= Path to the peer cert file. + -peer-key-file= Path to the peer key file. Other Options: -max-result-buffer Max size of the result buffer.