mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
etcdserver: add join-existing check
This commit is contained in:
parent
b7bbeefbff
commit
abcd828114
@ -46,9 +46,39 @@ type ServerConfig struct {
|
|||||||
ElectionTicks int
|
ElectionTicks int
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifyBootstrapConfig sanity-checks the initial config and returns an error
|
// VerifyBootstrapConfig sanity-checks the initial config for bootstrap case
|
||||||
// for things that should never happen.
|
// and returns an error for things that should never happen.
|
||||||
func (c *ServerConfig) VerifyBootstrapConfig() error {
|
func (c *ServerConfig) VerifyBootstrap() error {
|
||||||
|
if err := c.verifyLocalMember(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := c.Cluster.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if c.Cluster.String() == "" && c.DiscoveryURL == "" {
|
||||||
|
return fmt.Errorf("initial cluster unset and no discovery URL found")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifyJoinExisting sanity-checks the initial config for join existing cluster
|
||||||
|
// case and returns an error for things that should never happen.
|
||||||
|
func (c *ServerConfig) VerifyJoinExisting() error {
|
||||||
|
if err := c.verifyLocalMember(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := c.Cluster.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if c.DiscoveryURL != "" {
|
||||||
|
return fmt.Errorf("discovery URL should not be set when joining existing initial cluster")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// verifyLocalMember verifies that the local member is valid and is listed
|
||||||
|
// in the cluster correctly.
|
||||||
|
func (c *ServerConfig) verifyLocalMember() error {
|
||||||
m := c.Cluster.MemberByName(c.Name)
|
m := c.Cluster.MemberByName(c.Name)
|
||||||
// Make sure the cluster at least contains the local server.
|
// Make sure the cluster at least contains the local server.
|
||||||
if m == nil {
|
if m == nil {
|
||||||
@ -58,14 +88,6 @@ func (c *ServerConfig) VerifyBootstrapConfig() error {
|
|||||||
return fmt.Errorf("cannot use %x as member id", raft.None)
|
return fmt.Errorf("cannot use %x as member id", raft.None)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.DiscoveryURL == "" && !c.NewCluster {
|
|
||||||
return fmt.Errorf("initial cluster state unset and no wal or discovery URL found")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.Cluster.Validate(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Advertised peer URLs must match those in the cluster peer list
|
// Advertised peer URLs must match those in the cluster peer list
|
||||||
// TODO: Remove URLStringsEqual after improvement of using hostnames #2150 #2123
|
// TODO: Remove URLStringsEqual after improvement of using hostnames #2150 #2123
|
||||||
apurls := c.PeerURLs.StringSlice()
|
apurls := c.PeerURLs.StringSlice()
|
||||||
|
@ -29,74 +29,76 @@ func mustNewURLs(t *testing.T, urls []string) []url.URL {
|
|||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBootstrapConfigVerify(t *testing.T) {
|
func TestConfigVerifyBootstrapWithoutClusterAndDiscoveryURLFail(t *testing.T) {
|
||||||
|
cluster, err := NewClusterFromString("", "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("NewClusterFromString error: %v", err)
|
||||||
|
}
|
||||||
|
c := &ServerConfig{
|
||||||
|
Name: "node1",
|
||||||
|
DiscoveryURL: "",
|
||||||
|
Cluster: cluster,
|
||||||
|
}
|
||||||
|
if err := c.VerifyBootstrap(); err == nil {
|
||||||
|
t.Errorf("err = nil, want not nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigVerifyExistingWithDiscoveryURLFail(t *testing.T) {
|
||||||
|
cluster, err := NewClusterFromString("", "node1=http://127.0.0.1:2380")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("NewClusterFromString error: %v", err)
|
||||||
|
}
|
||||||
|
c := &ServerConfig{
|
||||||
|
Name: "node1",
|
||||||
|
DiscoveryURL: "http://127.0.0.1:4001/abcdefg",
|
||||||
|
PeerURLs: mustNewURLs(t, []string{"http://127.0.0.1:2380"}),
|
||||||
|
Cluster: cluster,
|
||||||
|
NewCluster: false,
|
||||||
|
}
|
||||||
|
if err := c.VerifyJoinExisting(); err == nil {
|
||||||
|
t.Errorf("err = nil, want not nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigVerifyLocalMember(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
clusterSetting string
|
clusterSetting string
|
||||||
newclst bool
|
|
||||||
apurls []string
|
apurls []string
|
||||||
disc string
|
|
||||||
shouldError bool
|
shouldError bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
// Node must exist in cluster
|
// Node must exist in cluster
|
||||||
"",
|
"",
|
||||||
true,
|
|
||||||
nil,
|
nil,
|
||||||
"",
|
|
||||||
|
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Cannot have duplicate URLs in cluster config
|
// Initial cluster set
|
||||||
"node1=http://localhost:7001,node2=http://localhost:7001,node2=http://localhost:7002",
|
|
||||||
true,
|
|
||||||
nil,
|
|
||||||
"",
|
|
||||||
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Node defined, ClusterState OK
|
|
||||||
"node1=http://localhost:7001,node2=http://localhost:7002",
|
"node1=http://localhost:7001,node2=http://localhost:7002",
|
||||||
true,
|
|
||||||
[]string{"http://localhost:7001"},
|
[]string{"http://localhost:7001"},
|
||||||
"",
|
|
||||||
|
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Node defined, discovery OK
|
// Default initial cluster
|
||||||
"node1=http://localhost:7001",
|
"node1=http://localhost:2380,node1=http://localhost:7001",
|
||||||
false,
|
[]string{"http://localhost:2380", "http://localhost:7001"},
|
||||||
[]string{"http://localhost:7001"},
|
|
||||||
"http://discovery",
|
|
||||||
|
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
// Cannot have ClusterState!=new && !discovery
|
|
||||||
"node1=http://localhost:7001",
|
|
||||||
false,
|
|
||||||
nil,
|
|
||||||
"",
|
|
||||||
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
// Advertised peer URLs must match those in cluster-state
|
// Advertised peer URLs must match those in cluster-state
|
||||||
"node1=http://localhost:7001",
|
"node1=http://localhost:7001",
|
||||||
true,
|
|
||||||
[]string{"http://localhost:12345"},
|
[]string{"http://localhost:12345"},
|
||||||
"",
|
|
||||||
|
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Advertised peer URLs must match those in cluster-state
|
// Advertised peer URLs must match those in cluster-state
|
||||||
"node1=http://localhost:7001,node1=http://localhost:12345",
|
"node1=http://localhost:7001,node1=http://localhost:12345",
|
||||||
true,
|
|
||||||
[]string{"http://localhost:12345"},
|
[]string{"http://localhost:12345"},
|
||||||
"",
|
|
||||||
|
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
@ -109,14 +111,12 @@ func TestBootstrapConfigVerify(t *testing.T) {
|
|||||||
}
|
}
|
||||||
cfg := ServerConfig{
|
cfg := ServerConfig{
|
||||||
Name: "node1",
|
Name: "node1",
|
||||||
DiscoveryURL: tt.disc,
|
|
||||||
Cluster: cluster,
|
Cluster: cluster,
|
||||||
NewCluster: tt.newclst,
|
|
||||||
}
|
}
|
||||||
if tt.apurls != nil {
|
if tt.apurls != nil {
|
||||||
cfg.PeerURLs = mustNewURLs(t, tt.apurls)
|
cfg.PeerURLs = mustNewURLs(t, tt.apurls)
|
||||||
}
|
}
|
||||||
err = cfg.VerifyBootstrapConfig()
|
err = cfg.verifyLocalMember()
|
||||||
if (err == nil) && tt.shouldError {
|
if (err == nil) && tt.shouldError {
|
||||||
t.Errorf("%#v", *cluster)
|
t.Errorf("%#v", *cluster)
|
||||||
t.Errorf("#%d: Got no error where one was expected", i)
|
t.Errorf("#%d: Got no error where one was expected", i)
|
||||||
|
@ -155,6 +155,9 @@ func NewServer(cfg *ServerConfig) (*EtcdServer, error) {
|
|||||||
|
|
||||||
switch {
|
switch {
|
||||||
case !haveWAL && !cfg.NewCluster:
|
case !haveWAL && !cfg.NewCluster:
|
||||||
|
if err := cfg.VerifyJoinExisting(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
existingCluster, err := GetClusterFromRemotePeers(getRemotePeerURLs(cfg.Cluster, cfg.Name), cfg.Transport)
|
existingCluster, err := GetClusterFromRemotePeers(getRemotePeerURLs(cfg.Cluster, cfg.Name), cfg.Transport)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("cannot fetch cluster info from peer urls: %v", err)
|
return nil, fmt.Errorf("cannot fetch cluster info from peer urls: %v", err)
|
||||||
@ -168,7 +171,7 @@ func NewServer(cfg *ServerConfig) (*EtcdServer, error) {
|
|||||||
cfg.Print()
|
cfg.Print()
|
||||||
id, n, s, w = startNode(cfg, nil)
|
id, n, s, w = startNode(cfg, nil)
|
||||||
case !haveWAL && cfg.NewCluster:
|
case !haveWAL && cfg.NewCluster:
|
||||||
if err := cfg.VerifyBootstrapConfig(); err != nil {
|
if err := cfg.VerifyBootstrap(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
m := cfg.Cluster.MemberByName(cfg.Name)
|
m := cfg.Cluster.MemberByName(cfg.Name)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user