mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
etcdserver: move peer URLs check to config
This commit is contained in:
parent
3f358b6d5d
commit
1197c1f965
@ -24,8 +24,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/coreos/etcd/discovery"
|
"github.com/coreos/etcd/discovery"
|
||||||
@ -191,7 +189,11 @@ func Main() {
|
|||||||
|
|
||||||
// startEtcd launches the etcd server and HTTP handlers for client/server communication.
|
// startEtcd launches the etcd server and HTTP handlers for client/server communication.
|
||||||
func startEtcd() error {
|
func startEtcd() error {
|
||||||
cls, err := setupCluster()
|
apurls, err := flags.URLsFromFlags(fs, "initial-advertise-peer-urls", "addr", peerTLSInfo)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cls, err := setupCluster(apurls)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error setting up initial cluster: %v", err)
|
return fmt.Errorf("error setting up initial cluster: %v", err)
|
||||||
}
|
}
|
||||||
@ -268,6 +270,7 @@ func startEtcd() error {
|
|||||||
cfg := &etcdserver.ServerConfig{
|
cfg := &etcdserver.ServerConfig{
|
||||||
Name: *name,
|
Name: *name,
|
||||||
ClientURLs: acurls,
|
ClientURLs: acurls,
|
||||||
|
PeerURLs: apurls,
|
||||||
DataDir: *dir,
|
DataDir: *dir,
|
||||||
SnapCount: *snapCount,
|
SnapCount: *snapCount,
|
||||||
Cluster: cls,
|
Cluster: cls,
|
||||||
@ -306,7 +309,11 @@ func startEtcd() error {
|
|||||||
|
|
||||||
// startProxy launches an HTTP proxy for client communication which proxies to other etcd nodes.
|
// startProxy launches an HTTP proxy for client communication which proxies to other etcd nodes.
|
||||||
func startProxy() error {
|
func startProxy() error {
|
||||||
cls, err := setupCluster()
|
apurls, err := flags.URLsFromFlags(fs, "initial-advertise-peer-urls", "addr", peerTLSInfo)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cls, err := setupCluster(apurls)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error setting up initial cluster: %v", err)
|
return fmt.Errorf("error setting up initial cluster: %v", err)
|
||||||
}
|
}
|
||||||
@ -367,7 +374,7 @@ func startProxy() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// setupCluster sets up an initial cluster definition for bootstrap or discovery.
|
// setupCluster sets up an initial cluster definition for bootstrap or discovery.
|
||||||
func setupCluster() (*etcdserver.Cluster, error) {
|
func setupCluster(apurls []url.URL) (*etcdserver.Cluster, error) {
|
||||||
set := make(map[string]bool)
|
set := make(map[string]bool)
|
||||||
fs.Visit(func(f *flag.Flag) {
|
fs.Visit(func(f *flag.Flag) {
|
||||||
set[f.Name] = true
|
set[f.Name] = true
|
||||||
@ -375,12 +382,8 @@ func setupCluster() (*etcdserver.Cluster, error) {
|
|||||||
if set["discovery"] && set["initial-cluster"] {
|
if set["discovery"] && set["initial-cluster"] {
|
||||||
return nil, fmt.Errorf("both discovery and bootstrap-config are set")
|
return nil, fmt.Errorf("both discovery and bootstrap-config are set")
|
||||||
}
|
}
|
||||||
apurls, err := flags.URLsFromFlags(fs, "initial-advertise-peer-urls", "addr", peerTLSInfo)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var cls *etcdserver.Cluster
|
var cls *etcdserver.Cluster
|
||||||
|
var err error
|
||||||
switch {
|
switch {
|
||||||
case set["discovery"]:
|
case set["discovery"]:
|
||||||
// If using discovery, generate a temporary cluster based on
|
// If using discovery, generate a temporary cluster based on
|
||||||
@ -392,31 +395,10 @@ func setupCluster() (*etcdserver.Cluster, error) {
|
|||||||
default:
|
default:
|
||||||
// We're statically configured, and cluster has appropriately been set.
|
// We're statically configured, and cluster has appropriately been set.
|
||||||
cls, err = etcdserver.NewClusterFromString(*initialClusterToken, *initialCluster)
|
cls, err = etcdserver.NewClusterFromString(*initialClusterToken, *initialCluster)
|
||||||
// Ensure our own advertised peer URLs match those specified in cluster
|
|
||||||
if err == nil && !clusterPeerURLsMatch(*name, cls, apurls) {
|
|
||||||
cls = nil
|
|
||||||
err = fmt.Errorf("%s has different advertised URLs in the cluster and advertised peer URLs list", *name)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return cls, err
|
return cls, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// clusterPeerURLsMatch checks whether the peer URLs of the member by the given
|
|
||||||
// name in the given cluster match the provided set of URLs
|
|
||||||
func clusterPeerURLsMatch(name string, cls *etcdserver.Cluster, urls []url.URL) bool {
|
|
||||||
m := cls.MemberByName(name)
|
|
||||||
if m == nil {
|
|
||||||
// should never happen
|
|
||||||
log.Panicf("could not find %q in cluster!", name)
|
|
||||||
}
|
|
||||||
purls := make([]string, len(urls))
|
|
||||||
for i, u := range urls {
|
|
||||||
purls[i] = u.String()
|
|
||||||
}
|
|
||||||
sort.Strings(purls)
|
|
||||||
return reflect.DeepEqual(purls, m.PeerURLs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func genClusterString(name string, urls types.URLs) string {
|
func genClusterString(name string, urls types.URLs) string {
|
||||||
addrs := make([]string, 0)
|
addrs := make([]string, 0)
|
||||||
for _, u := range urls {
|
for _, u := range urls {
|
||||||
|
@ -20,18 +20,9 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/coreos/etcd/etcdserver"
|
|
||||||
"github.com/coreos/etcd/pkg/types"
|
"github.com/coreos/etcd/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func mustClsFromString(t *testing.T, s string) *etcdserver.Cluster {
|
|
||||||
cls, err := etcdserver.NewClusterFromString("", s)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("error creating cluster from %q: %v", s, err)
|
|
||||||
}
|
|
||||||
return cls
|
|
||||||
}
|
|
||||||
|
|
||||||
func mustNewURLs(t *testing.T, urls []string) []url.URL {
|
func mustNewURLs(t *testing.T, urls []string) []url.URL {
|
||||||
u, err := types.NewURLs(urls)
|
u, err := types.NewURLs(urls)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -40,50 +31,6 @@ func mustNewURLs(t *testing.T, urls []string) []url.URL {
|
|||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClusterPeerURLsMatch(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
cls *etcdserver.Cluster
|
|
||||||
urls []url.URL
|
|
||||||
|
|
||||||
w bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "default",
|
|
||||||
cls: mustClsFromString(t, "default=http://localhost:12345"),
|
|
||||||
urls: mustNewURLs(t, []string{"http://localhost:12345"}),
|
|
||||||
|
|
||||||
w: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "default",
|
|
||||||
cls: mustClsFromString(t, "default=http://localhost:7001,other=http://192.168.0.1:7002,default=http://localhost:12345"),
|
|
||||||
urls: mustNewURLs(t, []string{"http://localhost:7001", "http://localhost:12345"}),
|
|
||||||
|
|
||||||
w: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "infra1",
|
|
||||||
cls: mustClsFromString(t, "infra1=http://localhost:7001"),
|
|
||||||
urls: mustNewURLs(t, []string{"http://localhost:12345"}),
|
|
||||||
|
|
||||||
w: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "infra1",
|
|
||||||
cls: mustClsFromString(t, "infra1=http://localhost:7001,infra2=http://localhost:12345"),
|
|
||||||
urls: mustNewURLs(t, []string{"http://localhost:12345"}),
|
|
||||||
|
|
||||||
w: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for i, tt := range tests {
|
|
||||||
if g := clusterPeerURLsMatch(tt.name, tt.cls, tt.urls); g != tt.w {
|
|
||||||
t.Errorf("#%d: clusterPeerURLsMatch=%t, want %t", i, g, tt.w)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGenClusterString(t *testing.T) {
|
func TestGenClusterString(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
token string
|
token string
|
||||||
|
@ -20,6 +20,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"path"
|
||||||
|
"reflect"
|
||||||
|
"sort"
|
||||||
|
|
||||||
"github.com/coreos/etcd/pkg/types"
|
"github.com/coreos/etcd/pkg/types"
|
||||||
"github.com/coreos/etcd/raft"
|
"github.com/coreos/etcd/raft"
|
||||||
@ -31,6 +33,7 @@ type ServerConfig struct {
|
|||||||
DiscoveryURL string
|
DiscoveryURL string
|
||||||
DiscoveryProxy string
|
DiscoveryProxy string
|
||||||
ClientURLs types.URLs
|
ClientURLs types.URLs
|
||||||
|
PeerURLs types.URLs
|
||||||
DataDir string
|
DataDir string
|
||||||
SnapCount uint64
|
SnapCount uint64
|
||||||
Cluster *Cluster
|
Cluster *Cluster
|
||||||
@ -65,6 +68,13 @@ func (c *ServerConfig) VerifyBootstrapConfig() error {
|
|||||||
urlMap[url] = true
|
urlMap[url] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Advertised peer URLs must match those in the cluster peer list
|
||||||
|
apurls := c.PeerURLs.StringSlice()
|
||||||
|
sort.Strings(apurls)
|
||||||
|
if !reflect.DeepEqual(apurls, m.PeerURLs) {
|
||||||
|
return fmt.Errorf("%s has different advertised URLs in the cluster and advertised peer URLs list", c.Name)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,12 +16,26 @@
|
|||||||
|
|
||||||
package etcdserver
|
package etcdserver
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"net/url"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/coreos/etcd/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func mustNewURLs(t *testing.T, urls []string) []url.URL {
|
||||||
|
u, err := types.NewURLs(urls)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error creating new URLs from %q: %v", urls, err)
|
||||||
|
}
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
func TestBootstrapConfigVerify(t *testing.T) {
|
func TestBootstrapConfigVerify(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
clusterSetting string
|
clusterSetting string
|
||||||
newclst bool
|
newclst bool
|
||||||
|
apurls []string
|
||||||
disc string
|
disc string
|
||||||
shouldError bool
|
shouldError bool
|
||||||
}{
|
}{
|
||||||
@ -29,35 +43,63 @@ func TestBootstrapConfigVerify(t *testing.T) {
|
|||||||
// Node must exist in cluster
|
// Node must exist in cluster
|
||||||
"",
|
"",
|
||||||
true,
|
true,
|
||||||
|
nil,
|
||||||
"",
|
"",
|
||||||
|
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Cannot have duplicate URLs in cluster config
|
// Cannot have duplicate URLs in cluster config
|
||||||
"node1=http://localhost:7001,node2=http://localhost:7001,node2=http://localhost:7002",
|
"node1=http://localhost:7001,node2=http://localhost:7001,node2=http://localhost:7002",
|
||||||
true,
|
true,
|
||||||
|
nil,
|
||||||
"",
|
"",
|
||||||
|
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Node defined, ClusterState OK
|
// Node defined, ClusterState OK
|
||||||
"node1=http://localhost:7001,node2=http://localhost:7002",
|
"node1=http://localhost:7001,node2=http://localhost:7002",
|
||||||
true,
|
true,
|
||||||
|
[]string{"http://localhost:7001"},
|
||||||
"",
|
"",
|
||||||
|
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Node defined, discovery OK
|
// Node defined, discovery OK
|
||||||
"node1=http://localhost:7001",
|
"node1=http://localhost:7001",
|
||||||
false,
|
false,
|
||||||
|
[]string{"http://localhost:7001"},
|
||||||
"http://discovery",
|
"http://discovery",
|
||||||
|
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Cannot have ClusterState!=new && !discovery
|
// Cannot have ClusterState!=new && !discovery
|
||||||
"node1=http://localhost:7001",
|
"node1=http://localhost:7001",
|
||||||
false,
|
false,
|
||||||
|
nil,
|
||||||
"",
|
"",
|
||||||
|
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Advertised peer URLs must match those in cluster-state
|
||||||
|
"node1=http://localhost:7001",
|
||||||
|
true,
|
||||||
|
[]string{"http://localhost:12345"},
|
||||||
|
"",
|
||||||
|
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Advertised peer URLs must match those in cluster-state
|
||||||
|
"node1=http://localhost:7001,node1=http://localhost:12345",
|
||||||
|
true,
|
||||||
|
[]string{"http://localhost:12345"},
|
||||||
|
"",
|
||||||
|
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -67,13 +109,15 @@ func TestBootstrapConfigVerify(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("#%d: Got unexpected error: %v", i, err)
|
t.Fatalf("#%d: Got unexpected error: %v", i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg := ServerConfig{
|
cfg := ServerConfig{
|
||||||
Name: "node1",
|
Name: "node1",
|
||||||
DiscoveryURL: tt.disc,
|
DiscoveryURL: tt.disc,
|
||||||
Cluster: cluster,
|
Cluster: cluster,
|
||||||
NewCluster: tt.newclst,
|
NewCluster: tt.newclst,
|
||||||
}
|
}
|
||||||
|
if tt.apurls != nil {
|
||||||
|
cfg.PeerURLs = mustNewURLs(t, tt.apurls)
|
||||||
|
}
|
||||||
err = cfg.VerifyBootstrapConfig()
|
err = cfg.VerifyBootstrapConfig()
|
||||||
if (err == nil) && tt.shouldError {
|
if (err == nil) && tt.shouldError {
|
||||||
t.Errorf("%#v", *cluster)
|
t.Errorf("%#v", *cluster)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user