embed: use machine default host only for default value, 0.0.0.0
Signed-off-by: Gyu-Ho Lee <gyuhox@gmail.com>release-3.2
parent
2831b9dcfd
commit
b7ee8f4967
|
@ -57,20 +57,12 @@ var (
|
||||||
DefaultInitialAdvertisePeerURLs = "http://localhost:2380"
|
DefaultInitialAdvertisePeerURLs = "http://localhost:2380"
|
||||||
DefaultAdvertiseClientURLs = "http://localhost:2379"
|
DefaultAdvertiseClientURLs = "http://localhost:2379"
|
||||||
|
|
||||||
defaultHostname string = "localhost"
|
defaultHostname string
|
||||||
defaultHostStatus error
|
defaultHostStatus error
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
ip, err := netutil.GetDefaultHost()
|
defaultHostname, defaultHostStatus = netutil.GetDefaultHost()
|
||||||
if err != nil {
|
|
||||||
defaultHostStatus = err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// found default host, advertise on it
|
|
||||||
DefaultInitialAdvertisePeerURLs = "http://" + net.JoinHostPort(ip, "2380")
|
|
||||||
DefaultAdvertiseClientURLs = "http://" + net.JoinHostPort(ip, "2379")
|
|
||||||
defaultHostname = ip
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config holds the arguments for configuring an etcd server.
|
// Config holds the arguments for configuring an etcd server.
|
||||||
|
@ -358,34 +350,52 @@ func (cfg Config) InitialClusterFromName(name string) (ret string) {
|
||||||
func (cfg Config) IsNewCluster() bool { return cfg.ClusterState == ClusterStateFlagNew }
|
func (cfg Config) IsNewCluster() bool { return cfg.ClusterState == ClusterStateFlagNew }
|
||||||
func (cfg Config) ElectionTicks() int { return int(cfg.ElectionMs / cfg.TickMs) }
|
func (cfg Config) ElectionTicks() int { return int(cfg.ElectionMs / cfg.TickMs) }
|
||||||
|
|
||||||
// IsDefaultHost returns the default hostname, if used, and the error, if any,
|
func (cfg Config) defaultPeerHost() bool {
|
||||||
// from getting the machine's default host.
|
return len(cfg.APUrls) == 1 && cfg.APUrls[0].String() == DefaultInitialAdvertisePeerURLs
|
||||||
func (cfg Config) IsDefaultHost() (string, error) {
|
|
||||||
if len(cfg.APUrls) == 1 && cfg.APUrls[0].String() == DefaultInitialAdvertisePeerURLs {
|
|
||||||
return defaultHostname, defaultHostStatus
|
|
||||||
}
|
|
||||||
if len(cfg.ACUrls) == 1 && cfg.ACUrls[0].String() == DefaultAdvertiseClientURLs {
|
|
||||||
return defaultHostname, defaultHostStatus
|
|
||||||
}
|
|
||||||
return "", defaultHostStatus
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateDefaultClusterFromName updates cluster advertise URLs with default host.
|
func (cfg Config) defaultClientHost() bool {
|
||||||
|
return len(cfg.ACUrls) == 1 && cfg.ACUrls[0].String() == DefaultAdvertiseClientURLs
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateDefaultClusterFromName updates cluster advertise URLs with, if available, default host,
|
||||||
|
// if advertise URLs are default values(localhost:2379,2380) AND if listen URL is 0.0.0.0.
|
||||||
|
// e.g. advertise peer URL localhost:2380 or listen peer URL 0.0.0.0:2380
|
||||||
|
// then the advertise peer host would be updated with machine's default host,
|
||||||
|
// while keeping the listen URL's port.
|
||||||
|
// User can work around this by explicitly setting URL with 127.0.0.1.
|
||||||
|
// It returns the default hostname, if used, and the error, if any, from getting the machine's default host.
|
||||||
// TODO: check whether fields are set instead of whether fields have default value
|
// TODO: check whether fields are set instead of whether fields have default value
|
||||||
func (cfg *Config) UpdateDefaultClusterFromName(defaultInitialCluster string) {
|
func (cfg *Config) UpdateDefaultClusterFromName(defaultInitialCluster string) (string, error) {
|
||||||
defaultHost, defaultHostErr := cfg.IsDefaultHost()
|
if defaultHostname == "" || defaultHostStatus != nil {
|
||||||
defaultHostOverride := defaultHost == "" || defaultHostErr == nil
|
// update 'initial-cluster' when only the name is specified (e.g. 'etcd --name=abc')
|
||||||
if (defaultHostOverride || cfg.Name != DefaultName) && cfg.InitialCluster == defaultInitialCluster {
|
if cfg.Name != DefaultName && cfg.InitialCluster == defaultInitialCluster {
|
||||||
cfg.InitialCluster = cfg.InitialClusterFromName(cfg.Name)
|
|
||||||
ip, _, _ := net.SplitHostPort(cfg.LCUrls[0].Host)
|
|
||||||
// if client-listen-url is 0.0.0.0, just use detected default host
|
|
||||||
// otherwise, rewrite advertise-client-url with localhost
|
|
||||||
if ip != "0.0.0.0" {
|
|
||||||
_, acPort, _ := net.SplitHostPort(cfg.ACUrls[0].Host)
|
|
||||||
cfg.ACUrls[0] = url.URL{Scheme: cfg.ACUrls[0].Scheme, Host: fmt.Sprintf("localhost:%s", acPort)}
|
|
||||||
cfg.InitialCluster = cfg.InitialClusterFromName(cfg.Name)
|
cfg.InitialCluster = cfg.InitialClusterFromName(cfg.Name)
|
||||||
}
|
}
|
||||||
|
return "", defaultHostStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
|
used := false
|
||||||
|
pip, pport, _ := net.SplitHostPort(cfg.LPUrls[0].Host)
|
||||||
|
if cfg.defaultPeerHost() && pip == "0.0.0.0" {
|
||||||
|
cfg.APUrls[0] = url.URL{Scheme: cfg.APUrls[0].Scheme, Host: fmt.Sprintf("%s:%s", defaultHostname, pport)}
|
||||||
|
used = true
|
||||||
|
}
|
||||||
|
// update 'initial-cluster' when only the name is specified (e.g. 'etcd --name=abc')
|
||||||
|
if cfg.Name != DefaultName && cfg.InitialCluster == defaultInitialCluster {
|
||||||
|
cfg.InitialCluster = cfg.InitialClusterFromName(cfg.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
cip, cport, _ := net.SplitHostPort(cfg.LCUrls[0].Host)
|
||||||
|
if cfg.defaultClientHost() && cip == "0.0.0.0" {
|
||||||
|
cfg.ACUrls[0] = url.URL{Scheme: cfg.ACUrls[0].Scheme, Host: fmt.Sprintf("%s:%s", defaultHostname, cport)}
|
||||||
|
used = true
|
||||||
|
}
|
||||||
|
dhost := defaultHostname
|
||||||
|
if !used {
|
||||||
|
dhost = ""
|
||||||
|
}
|
||||||
|
return dhost, defaultHostStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkBindURLs returns an error if any URL uses a domain name.
|
// checkBindURLs returns an error if any URL uses a domain name.
|
||||||
|
|
|
@ -15,11 +15,15 @@
|
||||||
package embed
|
package embed
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/coreos/etcd/pkg/transport"
|
"github.com/coreos/etcd/pkg/transport"
|
||||||
|
|
||||||
"github.com/ghodss/yaml"
|
"github.com/ghodss/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -61,6 +65,70 @@ func TestConfigFileOtherFields(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestUpdateDefaultClusterFromName ensures that etcd can start with 'etcd --name=abc'.
|
||||||
|
func TestUpdateDefaultClusterFromName(t *testing.T) {
|
||||||
|
cfg := NewConfig()
|
||||||
|
defaultInitialCluster := cfg.InitialCluster
|
||||||
|
oldscheme := cfg.APUrls[0].Scheme
|
||||||
|
origpeer := cfg.APUrls[0].String()
|
||||||
|
origadvc := cfg.ACUrls[0].String()
|
||||||
|
|
||||||
|
cfg.Name = "abc"
|
||||||
|
_, lpport, _ := net.SplitHostPort(cfg.LPUrls[0].Host)
|
||||||
|
|
||||||
|
// in case of 'etcd --name=abc'
|
||||||
|
exp := fmt.Sprintf("%s=%s://localhost:%s", cfg.Name, oldscheme, lpport)
|
||||||
|
cfg.UpdateDefaultClusterFromName(defaultInitialCluster)
|
||||||
|
if exp != cfg.InitialCluster {
|
||||||
|
t.Fatalf("initial-cluster expected %q, got %q", exp, cfg.InitialCluster)
|
||||||
|
}
|
||||||
|
// advertise peer URL should not be affected
|
||||||
|
if origpeer != cfg.APUrls[0].String() {
|
||||||
|
t.Fatalf("advertise peer url expected %q, got %q", origadvc, cfg.APUrls[0].String())
|
||||||
|
}
|
||||||
|
// advertise client URL should not be affected
|
||||||
|
if origadvc != cfg.ACUrls[0].String() {
|
||||||
|
t.Fatalf("advertise client url expected %q, got %q", origadvc, cfg.ACUrls[0].String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestUpdateDefaultClusterFromNameOverwrite ensures that machine's default host is only used
|
||||||
|
// if advertise URLs are default values(localhost:2379,2380) AND if listen URL is 0.0.0.0.
|
||||||
|
func TestUpdateDefaultClusterFromNameOverwrite(t *testing.T) {
|
||||||
|
if defaultHostname == "" {
|
||||||
|
t.Skip("machine's default host not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg := NewConfig()
|
||||||
|
defaultInitialCluster := cfg.InitialCluster
|
||||||
|
oldscheme := cfg.APUrls[0].Scheme
|
||||||
|
origadvc := cfg.ACUrls[0].String()
|
||||||
|
|
||||||
|
cfg.Name = "abc"
|
||||||
|
_, lpport, _ := net.SplitHostPort(cfg.LPUrls[0].Host)
|
||||||
|
cfg.LPUrls[0] = url.URL{Scheme: cfg.LPUrls[0].Scheme, Host: fmt.Sprintf("0.0.0.0:%s", lpport)}
|
||||||
|
dhost, _ := cfg.UpdateDefaultClusterFromName(defaultInitialCluster)
|
||||||
|
if dhost != defaultHostname {
|
||||||
|
t.Fatalf("expected default host %q, got %q", defaultHostname, dhost)
|
||||||
|
}
|
||||||
|
aphost, apport, _ := net.SplitHostPort(cfg.APUrls[0].Host)
|
||||||
|
if apport != lpport {
|
||||||
|
t.Fatalf("advertise peer url got different port %s, expected %s", apport, lpport)
|
||||||
|
}
|
||||||
|
if aphost != defaultHostname {
|
||||||
|
t.Fatalf("advertise peer url expected machine default host %q, got %q", defaultHostname, aphost)
|
||||||
|
}
|
||||||
|
expected := fmt.Sprintf("%s=%s://%s:%s", cfg.Name, oldscheme, defaultHostname, lpport)
|
||||||
|
if expected != cfg.InitialCluster {
|
||||||
|
t.Fatalf("initial-cluster expected %q, got %q", expected, cfg.InitialCluster)
|
||||||
|
}
|
||||||
|
|
||||||
|
// advertise client URL should not be affected
|
||||||
|
if origadvc != cfg.ACUrls[0].String() {
|
||||||
|
t.Fatalf("advertise-client-url expected %q, got %q", origadvc, cfg.ACUrls[0].String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *securityConfig) equals(t *transport.TLSInfo) bool {
|
func (s *securityConfig) equals(t *transport.TLSInfo) bool {
|
||||||
return s.CAFile == t.CAFile &&
|
return s.CAFile == t.CAFile &&
|
||||||
s.CertFile == t.CertFile &&
|
s.CertFile == t.CertFile &&
|
||||||
|
|
Loading…
Reference in New Issue