From ad0b7b7dbbfe9fda7579918618bfd58137413419 Mon Sep 17 00:00:00 2001 From: Barak Michener Date: Tue, 21 Oct 2014 14:32:09 -0400 Subject: [PATCH] Add cluster name to etcd flags --- etcdserver/cluster.go | 9 +++++---- etcdserver/cluster_store.go | 5 +++-- etcdserver/cluster_store_test.go | 2 +- etcdserver/cluster_test.go | 22 +++++++++++----------- etcdserver/etcdhttp/http_test.go | 2 +- etcdserver/member.go | 10 +++++++--- etcdserver/member_test.go | 15 +++++++++------ integration/cluster_test.go | 12 +++++++++--- main.go | 12 ++++++++---- 9 files changed, 54 insertions(+), 35 deletions(-) diff --git a/etcdserver/cluster.go b/etcdserver/cluster.go index 57b26d6dc..0400e7af2 100644 --- a/etcdserver/cluster.go +++ b/etcdserver/cluster.go @@ -32,11 +32,12 @@ import ( // Cluster is a list of Members that belong to the same raft cluster type Cluster struct { id uint64 + name string members map[uint64]*Member } -func NewCluster() *Cluster { - return &Cluster{members: make(map[uint64]*Member)} +func NewCluster(clusterName string) *Cluster { + return &Cluster{name: clusterName, members: make(map[uint64]*Member)} } func (c Cluster) FindID(id uint64) *Member { @@ -79,7 +80,7 @@ func (c Cluster) Pick(id uint64) string { // Set parses command line sets of names to IPs formatted like: // mach0=http://1.1.1.1,mach0=http://2.2.2.2,mach0=http://1.1.1.1,mach1=http://2.2.2.2,mach1=http://3.3.3.3 func (c *Cluster) Set(s string) error { - *c = *NewCluster() + *c = *NewCluster(c.name) v, err := url.ParseQuery(strings.Replace(s, ",", "&", -1)) if err != nil { return err @@ -90,7 +91,7 @@ func (c *Cluster) Set(s string) error { return fmt.Errorf("Empty URL given for %q", name) } - m := newMember(name, types.URLs(*flags.NewURLsValue(strings.Join(urls, ","))), nil) + m := newMember(name, types.URLs(*flags.NewURLsValue(strings.Join(urls, ","))), &c.name, nil) err := c.Add(*m) if err != nil { return err diff --git a/etcdserver/cluster_store.go b/etcdserver/cluster_store.go index c36655070..82a337477 100644 --- a/etcdserver/cluster_store.go +++ b/etcdserver/cluster_store.go @@ -49,7 +49,8 @@ type clusterStore struct { Store store.Store // TODO: write the id into the actual store? // TODO: save the id as string? - id uint64 + id uint64 + clusterName string } // Add puts a new Member into the store. @@ -75,7 +76,7 @@ func (s *clusterStore) Add(m Member) { // TODO(philips): keep the latest copy without going to the store to avoid the // lock here. func (s *clusterStore) Get() Cluster { - c := NewCluster() + c := NewCluster(s.clusterName) c.id = s.id e, err := s.Store.Get(storeMembersPrefix, true, true) if err != nil { diff --git a/etcdserver/cluster_store_test.go b/etcdserver/cluster_store_test.go index 202a4f13b..babbdead1 100644 --- a/etcdserver/cluster_store_test.go +++ b/etcdserver/cluster_store_test.go @@ -93,7 +93,7 @@ func TestClusterStoreGet(t *testing.T) { }, } for i, tt := range tests { - c := NewCluster() + c := NewCluster("") if err := c.AddSlice(tt.mems); err != nil { t.Fatal(err) } diff --git a/etcdserver/cluster_test.go b/etcdserver/cluster_test.go index 148c9a478..f7291fd54 100644 --- a/etcdserver/cluster_test.go +++ b/etcdserver/cluster_test.go @@ -28,7 +28,7 @@ func TestClusterAddSlice(t *testing.T) { }{ { []Member{}, - NewCluster(), + NewCluster(""), }, { []Member{ @@ -44,7 +44,7 @@ func TestClusterAddSlice(t *testing.T) { }, } for i, tt := range tests { - c := NewCluster() + c := NewCluster("") if err := c.AddSlice(tt.mems); err != nil { t.Errorf("#%d: err=%#v, want nil", i, err) continue @@ -134,7 +134,7 @@ func TestClusterFind(t *testing.T) { }, } for i, tt := range tests { - c := NewCluster() + c := NewCluster("") c.AddSlice(tt.mems) m := c.FindID(tt.id) @@ -150,7 +150,7 @@ func TestClusterFind(t *testing.T) { } for i, tt := range tests { - c := NewCluster() + c := NewCluster("") c.AddSlice(tt.mems) m := c.FindID(tt.id) @@ -181,7 +181,7 @@ func TestClusterSet(t *testing.T) { }, } for i, tt := range tests { - c := NewCluster() + c := NewCluster("") if err := c.AddSlice(tt.mems); err != nil { t.Error(err) } @@ -196,7 +196,7 @@ func TestClusterSet(t *testing.T) { } func TestClusterGenID(t *testing.T) { - cs := NewCluster() + cs := NewCluster("") cs.AddSlice([]Member{ newTestMember(1, nil, "", nil), newTestMember(2, nil, "", nil), @@ -232,7 +232,7 @@ func TestClusterSetBad(t *testing.T) { // "06b2f82fd81b2c20=http://128.193.4.20:2379,02c60cb75083ceef=http://128.193.4.20:2379", } for i, tt := range tests { - g := NewCluster() + g := NewCluster("") if err := g.Set(tt); err == nil { t.Errorf("#%d: set = %v, want err", i, tt) } @@ -240,7 +240,7 @@ func TestClusterSetBad(t *testing.T) { } func TestClusterMemberIDs(t *testing.T) { - cs := NewCluster() + cs := NewCluster("") cs.AddSlice([]Member{ newTestMember(1, nil, "", nil), newTestMember(4, nil, "", nil), @@ -259,7 +259,7 @@ func TestClusterAddBad(t *testing.T) { newTestMember(1, nil, "mem1", nil), newTestMember(1, nil, "mem2", nil), } - c := NewCluster() + c := NewCluster("") c.Add(newTestMember(1, nil, "mem1", nil)) for i, m := range mems { if err := c.Add(m); err == nil { @@ -315,7 +315,7 @@ func TestClusterPeerURLs(t *testing.T) { } for i, tt := range tests { - c := NewCluster() + c := NewCluster("") if err := c.AddSlice(tt.mems); err != nil { t.Errorf("AddSlice error: %v", err) continue @@ -374,7 +374,7 @@ func TestClusterClientURLs(t *testing.T) { } for i, tt := range tests { - c := NewCluster() + c := NewCluster("") if err := c.AddSlice(tt.mems); err != nil { t.Errorf("AddSlice error: %v", err) continue diff --git a/etcdserver/etcdhttp/http_test.go b/etcdserver/etcdhttp/http_test.go index 659aa71ff..b2736c329 100644 --- a/etcdserver/etcdhttp/http_test.go +++ b/etcdserver/etcdhttp/http_test.go @@ -1648,7 +1648,7 @@ type fakeCluster struct { func (c *fakeCluster) Add(m etcdserver.Member) { return } func (c *fakeCluster) Get() etcdserver.Cluster { - cl := etcdserver.NewCluster() + cl := etcdserver.NewCluster("") cl.AddSlice(c.members) return *cl } diff --git a/etcdserver/member.go b/etcdserver/member.go index a6c0fccef..cb1236708 100644 --- a/etcdserver/member.go +++ b/etcdserver/member.go @@ -49,7 +49,7 @@ type Member struct { // newMember creates a Member without an ID and generates one based on the // name, peer URLs. This is used for bootstrapping. -func newMember(name string, peerURLs types.URLs, now *time.Time) *Member { +func newMember(name string, peerURLs types.URLs, clusterName *string, now *time.Time) *Member { m := &Member{ RaftAttributes: RaftAttributes{PeerURLs: peerURLs.StringSlice()}, Attributes: Attributes{Name: name}, @@ -61,6 +61,10 @@ func newMember(name string, peerURLs types.URLs, now *time.Time) *Member { b = append(b, []byte(p)...) } + if clusterName != nil { + b = append(b, []byte(*clusterName)...) + } + if now != nil { b = append(b, []byte(fmt.Sprintf("%d", now.Unix()))...) } @@ -70,8 +74,8 @@ func newMember(name string, peerURLs types.URLs, now *time.Time) *Member { return m } -func NewMemberFromURLs(name string, urls types.URLs) *Member { - return newMember(name, urls, nil) +func NewMemberFromURLs(name string, urls types.URLs, clusterName *string) *Member { + return newMember(name, urls, clusterName, nil) } func (m Member) storeKey() string { diff --git a/etcdserver/member_test.go b/etcdserver/member_test.go index 57ae871ef..1250ba372 100644 --- a/etcdserver/member_test.go +++ b/etcdserver/member_test.go @@ -31,19 +31,22 @@ func timeParse(value string) *time.Time { } func TestMemberTime(t *testing.T) { + var clusterName = "etcd" tests := []struct { mem *Member id uint64 }{ - {newMember("mem1", []url.URL{{Scheme: "http", Host: "10.0.0.8:2379"}}, nil), 14544069596553697298}, + {newMember("mem1", []url.URL{{Scheme: "http", Host: "10.0.0.8:2379"}}, nil, nil), 14544069596553697298}, // Same ID, different name (names shouldn't matter) - {newMember("memfoo", []url.URL{{Scheme: "http", Host: "10.0.0.8:2379"}}, nil), 14544069596553697298}, + {newMember("memfoo", []url.URL{{Scheme: "http", Host: "10.0.0.8:2379"}}, nil, nil), 14544069596553697298}, // Same ID, different Time - {newMember("mem1", []url.URL{{Scheme: "http", Host: "10.0.0.8:2379"}}, timeParse("1984-12-23T15:04:05Z")), 2448790162483548276}, - {newMember("mem1", []url.URL{{Scheme: "http", Host: "10.0.0.1:2379"}}, timeParse("1984-12-23T15:04:05Z")), 1466075294948436910}, + {newMember("mem1", []url.URL{{Scheme: "http", Host: "10.0.0.8:2379"}}, nil, timeParse("1984-12-23T15:04:05Z")), 2448790162483548276}, + // Different cluster name + {newMember("mcm1", []url.URL{{Scheme: "http", Host: "10.0.0.8:2379"}}, &clusterName, timeParse("1984-12-23T15:04:05Z")), 6973882743191604649}, + {newMember("mem1", []url.URL{{Scheme: "http", Host: "10.0.0.1:2379"}}, nil, timeParse("1984-12-23T15:04:05Z")), 1466075294948436910}, // Order shouldn't matter - {newMember("mem1", []url.URL{{Scheme: "http", Host: "10.0.0.1:2379"}, {Scheme: "http", Host: "10.0.0.2:2379"}}, nil), 16552244735972308939}, - {newMember("mem1", []url.URL{{Scheme: "http", Host: "10.0.0.2:2379"}, {Scheme: "http", Host: "10.0.0.1:2379"}}, nil), 16552244735972308939}, + {newMember("mem1", []url.URL{{Scheme: "http", Host: "10.0.0.1:2379"}, {Scheme: "http", Host: "10.0.0.2:2379"}}, nil, nil), 16552244735972308939}, + {newMember("mem1", []url.URL{{Scheme: "http", Host: "10.0.0.2:2379"}, {Scheme: "http", Host: "10.0.0.1:2379"}}, nil, nil), 16552244735972308939}, } for i, tt := range tests { if tt.mem.ID != tt.id { diff --git a/integration/cluster_test.go b/integration/cluster_test.go index abc55206e..5ff17c6cd 100644 --- a/integration/cluster_test.go +++ b/integration/cluster_test.go @@ -19,7 +19,13 @@ import ( "github.com/coreos/etcd/pkg/types" ) -const tickDuration = 5 * time.Millisecond +const ( + tickDuration = 5 * time.Millisecond +) + +var ( + clusterName = "etcd" +) func init() { // open microsecond-level time log for integration test debugging @@ -89,7 +95,7 @@ func (c *cluster) Launch(t *testing.T) { lns[i] = l bootstrapCfgs[i] = fmt.Sprintf("%s=%s", c.name(i), "http://"+l.Addr().String()) } - clusterCfg := etcdserver.NewCluster() + clusterCfg := etcdserver.NewCluster(clusterName) if err := clusterCfg.Set(strings.Join(bootstrapCfgs, ",")); err != nil { t.Fatal(err) } @@ -103,7 +109,7 @@ func (c *cluster) Launch(t *testing.T) { if err != nil { t.Fatal(err) } - localMember := *etcdserver.NewMemberFromURLs(c.name(i), listenUrls) + localMember := *etcdserver.NewMemberFromURLs(c.name(i), listenUrls, &clusterName) m.NodeID = localMember.ID m.Name = localMember.Name m.ClientURLs, err = types.NewURLs([]string{"http://" + cln.Addr().String()}) diff --git a/main.go b/main.go index 40684ce99..bb9fb6f94 100644 --- a/main.go +++ b/main.go @@ -56,6 +56,8 @@ var ( clientTLSInfo = transport.TLSInfo{} peerTLSInfo = transport.TLSInfo{} + initialClusterName *string + ignored = []string{ "cluster-active-size", "cluster-remove-delay", @@ -74,7 +76,9 @@ var ( ) func init() { + fs.StringVar(initialClusterName, "initial-cluster-name", "etcd", "Initial name for the etcd cluster during bootstrap.") fs.Var(cluster, "initial-cluster", "Initial cluster configuration for bootstrapping") + cluster = etcdserver.NewCluster(*initialClusterName) if err := cluster.Set("default=http://localhost:2380,default=http://localhost:7001"); err != nil { // Should never happen log.Panic(err) @@ -283,8 +287,8 @@ func setupCluster() (*etcdserver.Member, error) { return nil, err } if set["discovery"] { - m = etcdserver.NewMemberFromURLs(*name, apurls) - cluster = etcdserver.NewCluster() + m = etcdserver.NewMemberFromURLs(*name, apurls, durl) + cluster = etcdserver.NewCluster(*durl) cluster.Add(*m) return m, nil } else if set["initial-cluster"] { @@ -298,7 +302,7 @@ func setupCluster() (*etcdserver.Member, error) { log.Println("etcd: cannot find the passed name", *name, "in initial-cluster. Trying advertise-peer-urls") // Try to configure by looking for a matching machine based on the peer urls. - m = etcdserver.NewMemberFromURLs(*name, apurls) + m = etcdserver.NewMemberFromURLs(*name, apurls, initialClusterName) for _, c := range cluster.Members() { if c.ID == m.ID { return c, nil @@ -307,6 +311,6 @@ func setupCluster() (*etcdserver.Member, error) { log.Println("etcd: Could not find a matching peer for the local instance in initial-cluster.") return nil, fmt.Errorf("etcd: Bootstrapping a static cluster, but local name or local peer urls are not defined") } - m = etcdserver.NewMemberFromURLs(*name, apurls) + m = etcdserver.NewMemberFromURLs(*name, apurls, initialClusterName) return m, nil }