mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
*: detect duplicate name for discovery bootstrap
This commit is contained in:
parent
b8279b3591
commit
dc3f7f5d90
@ -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 }
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user