Prechádzať zdrojové kódy

*: detect duplicate name for discovery bootstrap

Xiang Li 10 rokov pred
rodič
commit
dc3f7f5d90
3 zmenil súbory, kde vykonal 63 pridanie a 14 odobranie
  1. 14 5
      discovery/discovery.go
  2. 44 8
      discovery/discovery_test.go
  3. 5 1
      etcdmain/etcd.go

+ 14 - 5
discovery/discovery.go

@@ -42,6 +42,7 @@ var (
 	ErrSizeNotFound   = errors.New("discovery: size key not found")
 	ErrTokenNotFound  = errors.New("discovery: token not found")
 	ErrDuplicateID    = errors.New("discovery: found duplicate id")
+	ErrDuplicateName  = errors.New("discovery: found duplicate name")
 	ErrFullCluster    = errors.New("discovery: cluster is full")
 	ErrTooManyRetries = errors.New("discovery: too many retries")
 )
@@ -170,14 +171,14 @@ func (d *discovery) joinCluster(config string) (string, error) {
 		return "", err
 	}
 
-	return nodesToCluster(all), nil
+	return nodesToCluster(all, size)
 }
 
 func (d *discovery) getCluster() (string, error) {
 	nodes, size, index, err := d.checkCluster()
 	if err != nil {
 		if err == ErrFullCluster {
-			return nodesToCluster(nodes), nil
+			return nodesToCluster(nodes, size)
 		}
 		return "", err
 	}
@@ -186,7 +187,7 @@ func (d *discovery) getCluster() (string, error) {
 	if err != nil {
 		return "", err
 	}
-	return nodesToCluster(all), nil
+	return nodesToCluster(all, size)
 }
 
 func (d *discovery) createSelf(contents string) error {
@@ -322,12 +323,20 @@ func (d *discovery) selfKey() string {
 	return path.Join("/", d.cluster, d.id.String())
 }
 
-func nodesToCluster(ns []*client.Node) string {
+func nodesToCluster(ns []*client.Node, size int) (string, error) {
 	s := make([]string, len(ns))
 	for i, n := range ns {
 		s[i] = n.Value
 	}
-	return strings.Join(s, ",")
+	us := strings.Join(s, ",")
+	m, err := types.NewURLsMap(us)
+	if err != nil {
+		return us, ErrInvalidURL
+	}
+	if m.Len() != size {
+		return us, ErrDuplicateName
+	}
+	return us, nil
 }
 
 type sortableNodes struct{ Nodes []*client.Node }

+ 44 - 8
discovery/discovery_test.go

@@ -344,16 +344,52 @@ func TestCreateSelf(t *testing.T) {
 }
 
 func TestNodesToCluster(t *testing.T) {
-	nodes := []*client.Node{
-		0: {Key: "/1000/1", Value: "1=1.1.1.1", CreatedIndex: 1},
-		1: {Key: "/1000/2", Value: "2=2.2.2.2", CreatedIndex: 2},
-		2: {Key: "/1000/3", Value: "3=3.3.3.3", CreatedIndex: 3},
+	tests := []struct {
+		nodes    []*client.Node
+		size     int
+		wcluster string
+		werr     error
+	}{
+		{
+			[]*client.Node{
+				0: {Key: "/1000/1", Value: "1=http://1.1.1.1:2380", CreatedIndex: 1},
+				1: {Key: "/1000/2", Value: "2=http://2.2.2.2:2380", CreatedIndex: 2},
+				2: {Key: "/1000/3", Value: "3=http://3.3.3.3:2380", CreatedIndex: 3},
+			},
+			3,
+			"1=http://1.1.1.1:2380,2=http://2.2.2.2:2380,3=http://3.3.3.3:2380",
+			nil,
+		},
+		{
+			[]*client.Node{
+				0: {Key: "/1000/1", Value: "1=http://1.1.1.1:2380", CreatedIndex: 1},
+				1: {Key: "/1000/2", Value: "2=http://2.2.2.2:2380", CreatedIndex: 2},
+				2: {Key: "/1000/3", Value: "2=http://3.3.3.3:2380", CreatedIndex: 3},
+			},
+			3,
+			"1=http://1.1.1.1:2380,2=http://2.2.2.2:2380,2=http://3.3.3.3:2380",
+			ErrDuplicateName,
+		},
+		{
+			[]*client.Node{
+				0: {Key: "/1000/1", Value: "1=1.1.1.1:2380", CreatedIndex: 1},
+				1: {Key: "/1000/2", Value: "2=http://2.2.2.2:2380", CreatedIndex: 2},
+				2: {Key: "/1000/3", Value: "2=http://3.3.3.3:2380", CreatedIndex: 3},
+			},
+			3,
+			"1=1.1.1.1:2380,2=http://2.2.2.2:2380,2=http://3.3.3.3:2380",
+			ErrInvalidURL,
+		},
 	}
-	w := "1=1.1.1.1,2=2.2.2.2,3=3.3.3.3"
 
-	cluster := nodesToCluster(nodes)
-	if !reflect.DeepEqual(cluster, w) {
-		t.Errorf("cluster = %v, want %v", cluster, w)
+	for i, tt := range tests {
+		cluster, err := nodesToCluster(tt.nodes, tt.size)
+		if err != tt.werr {
+			t.Errorf("#%d: err = %v, want %v", i, err, tt.werr)
+		}
+		if !reflect.DeepEqual(cluster, tt.wcluster) {
+			t.Errorf("#%d: cluster = %v, want %v", i, cluster, tt.wcluster)
+		}
 	}
 }
 

+ 5 - 1
etcdmain/etcd.go

@@ -110,10 +110,14 @@ func Main() {
 		switch err {
 		case discovery.ErrDuplicateID:
 			plog.Errorf("member %q has previously registered with discovery service token (%s).", cfg.name, cfg.durl)
-			plog.Errorf("But etcd could not find vaild cluster configuration in the given data dir (%s).", cfg.dir)
+			plog.Errorf("But etcd could not find valid cluster configuration in the given data dir (%s).", cfg.dir)
 			plog.Infof("Please check the given data dir path if the previous bootstrap succeeded")
 			plog.Infof("or use a new discovery token if the previous bootstrap failed.")
 			os.Exit(1)
+		case discovery.ErrDuplicateName:
+			plog.Errorf("member with duplicated name has registered with discovery service token(%s).", cfg.durl)
+			plog.Errorf("please check (cURL) the discovery token for more information.")
+			plog.Errorf("please do not reuse the discovery token and generate a new one to bootstrap the cluster.")
 		default:
 			plog.Fatalf("%v", err)
 		}