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")
|
ErrSizeNotFound = errors.New("discovery: size key not found")
|
||||||
ErrTokenNotFound = errors.New("discovery: token not found")
|
ErrTokenNotFound = errors.New("discovery: token not found")
|
||||||
ErrDuplicateID = errors.New("discovery: found duplicate id")
|
ErrDuplicateID = errors.New("discovery: found duplicate id")
|
||||||
|
ErrDuplicateName = errors.New("discovery: found duplicate name")
|
||||||
ErrFullCluster = errors.New("discovery: cluster is full")
|
ErrFullCluster = errors.New("discovery: cluster is full")
|
||||||
ErrTooManyRetries = errors.New("discovery: too many retries")
|
ErrTooManyRetries = errors.New("discovery: too many retries")
|
||||||
)
|
)
|
||||||
@ -170,14 +171,14 @@ func (d *discovery) joinCluster(config string) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodesToCluster(all), nil
|
return nodesToCluster(all, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *discovery) getCluster() (string, error) {
|
func (d *discovery) getCluster() (string, error) {
|
||||||
nodes, size, index, err := d.checkCluster()
|
nodes, size, index, err := d.checkCluster()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == ErrFullCluster {
|
if err == ErrFullCluster {
|
||||||
return nodesToCluster(nodes), nil
|
return nodesToCluster(nodes, size)
|
||||||
}
|
}
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -186,7 +187,7 @@ func (d *discovery) getCluster() (string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return nodesToCluster(all), nil
|
return nodesToCluster(all, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *discovery) createSelf(contents string) error {
|
func (d *discovery) createSelf(contents string) error {
|
||||||
@ -322,12 +323,20 @@ func (d *discovery) selfKey() string {
|
|||||||
return path.Join("/", d.cluster, d.id.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))
|
s := make([]string, len(ns))
|
||||||
for i, n := range ns {
|
for i, n := range ns {
|
||||||
s[i] = n.Value
|
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 }
|
type sortableNodes struct{ Nodes []*client.Node }
|
||||||
|
@ -344,16 +344,52 @@ func TestCreateSelf(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNodesToCluster(t *testing.T) {
|
func TestNodesToCluster(t *testing.T) {
|
||||||
nodes := []*client.Node{
|
tests := []struct {
|
||||||
0: {Key: "/1000/1", Value: "1=1.1.1.1", CreatedIndex: 1},
|
nodes []*client.Node
|
||||||
1: {Key: "/1000/2", Value: "2=2.2.2.2", CreatedIndex: 2},
|
size int
|
||||||
2: {Key: "/1000/3", Value: "3=3.3.3.3", CreatedIndex: 3},
|
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)
|
for i, tt := range tests {
|
||||||
if !reflect.DeepEqual(cluster, w) {
|
cluster, err := nodesToCluster(tt.nodes, tt.size)
|
||||||
t.Errorf("cluster = %v, want %v", cluster, w)
|
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 {
|
switch err {
|
||||||
case discovery.ErrDuplicateID:
|
case discovery.ErrDuplicateID:
|
||||||
plog.Errorf("member %q has previously registered with discovery service token (%s).", cfg.name, cfg.durl)
|
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("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.")
|
plog.Infof("or use a new discovery token if the previous bootstrap failed.")
|
||||||
os.Exit(1)
|
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:
|
default:
|
||||||
plog.Fatalf("%v", err)
|
plog.Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user