diff --git a/embed/config.go b/embed/config.go index db35e84cbb7..a569b0f0806 100644 --- a/embed/config.go +++ b/embed/config.go @@ -57,20 +57,12 @@ var ( DefaultInitialAdvertisePeerURLs = "http://localhost:2380" DefaultAdvertiseClientURLs = "http://localhost:2379" - defaultHostname string = "localhost" + defaultHostname string defaultHostStatus error ) func init() { - ip, err := 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 + defaultHostname, defaultHostStatus = netutil.GetDefaultHost() } // Config holds the arguments for configuring an etcd server. @@ -358,34 +350,50 @@ func (cfg Config) InitialClusterFromName(name string) (ret string) { func (cfg Config) IsNewCluster() bool { return cfg.ClusterState == ClusterStateFlagNew } func (cfg Config) ElectionTicks() int { return int(cfg.ElectionMs / cfg.TickMs) } -// IsDefaultHost returns the default hostname, if used, and the error, if any, -// from getting the machine's default host. -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 +func (cfg Config) defaultPeerHost() bool { + return len(cfg.APUrls) == 1 && cfg.APUrls[0].String() == DefaultInitialAdvertisePeerURLs } -// 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 -func (cfg *Config) UpdateDefaultClusterFromName(defaultInitialCluster string) { - defaultHost, defaultHostErr := cfg.IsDefaultHost() - defaultHostOverride := defaultHost == "" || defaultHostErr == nil - if (defaultHostOverride || 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)} +func (cfg *Config) UpdateDefaultClusterFromName(defaultInitialCluster string) (string, error) { + if defaultHostname == "" || defaultHostStatus != nil { + if cfg.Name != DefaultName && cfg.InitialCluster == defaultInitialCluster { + 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 + 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 + } + cfg.InitialCluster = cfg.InitialClusterFromName(cfg.Name) + if !used { + defaultHostname = "" + } + return defaultHostname, defaultHostStatus } // checkBindURLs returns an error if any URL uses a domain name.