diff --git a/etcdserver/cluster.go b/etcdserver/cluster.go index 881808fa4cc..0acbf1da1a9 100644 --- a/etcdserver/cluster.go +++ b/etcdserver/cluster.go @@ -346,6 +346,20 @@ func (c *Cluster) UpdateRaftAttributes(id types.ID, raftAttr RaftAttributes) { c.members[id].RaftAttributes = raftAttr } +// Validate ensures that there is no identical urls in the cluster peer list +func (c *Cluster) Validate() error { + urlMap := make(map[string]bool) + for _, m := range c.Members() { + for _, url := range m.PeerURLs { + if urlMap[url] { + return fmt.Errorf("duplicate url %v in cluster config", url) + } + urlMap[url] = true + } + } + return nil +} + func membersFromStore(st store.Store) (map[types.ID]*Member, map[types.ID]bool) { members := make(map[types.ID]*Member) removed := make(map[types.ID]bool) diff --git a/etcdserver/config.go b/etcdserver/config.go index a1a1d5cfbc4..87747938187 100644 --- a/etcdserver/config.go +++ b/etcdserver/config.go @@ -62,15 +62,8 @@ func (c *ServerConfig) VerifyBootstrapConfig() error { return fmt.Errorf("initial cluster state unset and no wal or discovery URL found") } - // No identical IPs in the cluster peer list - urlMap := make(map[string]bool) - for _, m := range c.Cluster.Members() { - for _, url := range m.PeerURLs { - if urlMap[url] { - return fmt.Errorf("duplicate url %v in cluster config", url) - } - urlMap[url] = true - } + if err := c.Cluster.Validate(); err != nil { + return err } // Advertised peer URLs must match those in the cluster peer list diff --git a/etcdserver/server.go b/etcdserver/server.go index 0249506f7b8..436f897d029 100644 --- a/etcdserver/server.go +++ b/etcdserver/server.go @@ -185,6 +185,9 @@ func NewServer(cfg *ServerConfig) (*EtcdServer, error) { if cfg.Cluster, err = NewClusterFromString(cfg.Cluster.token, s); err != nil { return nil, err } + if cfg.Cluster.Validate() != nil { + return nil, fmt.Errorf("bad discovery cluster: %v", err) + } } cfg.Cluster.SetStore(st) cfg.PrintWithInitial()