diff --git a/consul/client.go b/consul/client.go index 5935dd8668..adbab9e258 100644 --- a/consul/client.go +++ b/consul/client.go @@ -90,8 +90,10 @@ func NewClient(config *Config) (*Client, error) { // setupSerf is used to setup and initialize a Serf func (c *Client) setupSerf(conf *serf.Config, ch chan serf.Event, path string) (*serf.Serf, error) { + conf.Init() conf.NodeName = c.config.NodeName - conf.Role = fmt.Sprintf("node:%s", c.config.Datacenter) + conf.Tags["role"] = "node" + conf.Tags["dc"] = c.config.Datacenter conf.MemberlistConfig.LogOutput = c.config.LogOutput conf.LogOutput = c.config.LogOutput conf.EventCh = ch diff --git a/consul/leader.go b/consul/leader.go index d6f79e4fdd..6174e40c71 100644 --- a/consul/leader.go +++ b/consul/leader.go @@ -270,11 +270,11 @@ func (s *Server) joinConsulServer(m serf.Member, parts *serverParts) error { } // Check for possibility of multiple bootstrap nodes - if parts.HasFlag(bootstrapFlag) { + if parts.Bootstrap { members := s.serfLAN.Members() for _, member := range members { valid, p := isConsulServer(member) - if valid && member.Name != m.Name && p.HasFlag(bootstrapFlag) { + if valid && member.Name != m.Name && p.Bootstrap { s.logger.Printf("[ERR] consul: '%v' and '%v' are both in bootstrap mode. Only one node should be in bootstrap mode, not adding Raft peer.", m.Name, member.Name) return nil } diff --git a/consul/server.go b/consul/server.go index 131a372791..cc18b02ae6 100644 --- a/consul/server.go +++ b/consul/server.go @@ -162,12 +162,14 @@ func NewServer(config *Config) (*Server, error) { // setupSerf is used to setup and initialize a Serf func (s *Server) setupSerf(conf *serf.Config, ch chan serf.Event, path string) (*serf.Serf, error) { addr := s.rpcListener.Addr().(*net.TCPAddr) - flags := "" - if s.config.Bootstrap { - flags = bootstrapFlag - } + conf.Init() conf.NodeName = s.config.NodeName - conf.Role = fmt.Sprintf("consul:%s:%d:%s", s.config.Datacenter, addr.Port, flags) + conf.Tags["role"] = "consul" + conf.Tags["dc"] = s.config.Datacenter + conf.Tags["port"] = fmt.Sprintf("%d", addr.Port) + if s.config.Bootstrap { + conf.Tags["bootstrap"] = "1" + } conf.MemberlistConfig.LogOutput = s.config.LogOutput conf.LogOutput = s.config.LogOutput conf.EventCh = ch diff --git a/consul/server_test.go b/consul/server_test.go index 03d03304b6..f73ec6f2ee 100644 --- a/consul/server_test.go +++ b/consul/server_test.go @@ -173,7 +173,8 @@ func TestServer_Leave(t *testing.T) { defer os.RemoveAll(dir1) defer s1.Shutdown() - dir2, s2 := testServer(t) + // Second server not in bootstrap mode + dir2, s2 := testServerDCBootstrap(t, "dc1", false) defer os.RemoveAll(dir2) defer s2.Shutdown() diff --git a/consul/util.go b/consul/util.go index 6bd119ad7a..ffca9961cb 100644 --- a/consul/util.go +++ b/consul/util.go @@ -8,7 +8,6 @@ import ( "os" "path/filepath" "strconv" - "strings" ) /* @@ -23,12 +22,7 @@ var privateBlocks []*net.IPNet type serverParts struct { Datacenter string Port int - Flags string -} - -// HasFlag is used to check if a flag is present -func (s *serverParts) HasFlag(flag string) bool { - return strings.Contains(s.Flags, flag) + Bootstrap bool } func init() { @@ -74,34 +68,28 @@ func ensurePath(path string, dir bool) error { // Returns if a member is a consul server. Returns a bool, // the data center, and the rpc port func isConsulServer(m serf.Member) (bool, *serverParts) { - role := m.Role - if !strings.HasPrefix(role, "consul:") { + if m.Tags["role"] != "consul" { return false, nil } - parts := strings.SplitN(role, ":", 4) - datacenter := parts[1] - port_str := parts[2] - flags := parts[3] + datacenter := m.Tags["dc"] + port_str := m.Tags["port"] + _, bootstrap := m.Tags["bootstrap"] port, err := strconv.Atoi(port_str) if err != nil { return false, nil } - return true, &serverParts{datacenter, port, flags} + return true, &serverParts{datacenter, port, bootstrap} } // Returns if a member is a consul node. Returns a boo, // and the data center. func isConsulNode(m serf.Member) (bool, string) { - role := m.Role - if !strings.HasPrefix(role, "node:") { + if m.Tags["role"] != "node" { return false, "" } - - parts := strings.SplitN(role, ":", 2) - datacenter := parts[1] - return true, datacenter + return true, m.Tags["dc"] } // Returns if the given IP is in a private block diff --git a/consul/util_test.go b/consul/util_test.go index 9117684b17..edd73fdf69 100644 --- a/consul/util_test.go +++ b/consul/util_test.go @@ -35,17 +35,32 @@ func TestIsPrivateIP(t *testing.T) { func TestIsConsulServer(t *testing.T) { m := serf.Member{ - Role: "consul:east-aws:10000", + Tags: map[string]string{ + "role": "consul", + "dc": "east-aws", + "port": "10000", + }, } valid, parts := isConsulServer(m) if !valid || parts.Datacenter != "east-aws" || parts.Port != 10000 { t.Fatalf("bad: %v %v", valid, parts) } + if parts.Bootstrap { + t.Fatalf("unexpected bootstrap") + } + m.Tags["bootstrap"] = "1" + valid, parts = isConsulServer(m) + if !valid || !parts.Bootstrap { + t.Fatalf("expected bootstrap") + } } func TestIsConsulNode(t *testing.T) { m := serf.Member{ - Role: "node:east-aws", + Tags: map[string]string{ + "role": "node", + "dc": "east-aws", + }, } valid, dc := isConsulNode(m) if !valid || dc != "east-aws" {