Bläddra i källkod

Treat URLs have same IP address as same

- To solve validation error problem using URLs in hostname #2123
Shota Fukumori (sora_h) 11 år sedan
förälder
incheckning
f8ce5996b0
4 ändrade filer med 157 tillägg och 4 borttagningar
  1. 3 2
      etcdserver/cluster.go
  2. 3 2
      etcdserver/config.go
  3. 46 0
      pkg/netutil/netutil.go
  4. 105 0
      pkg/netutil/netutil_test.go

+ 3 - 2
etcdserver/cluster.go

@@ -22,12 +22,12 @@ import (
 	"log"
 	"net/url"
 	"path"
-	"reflect"
 	"sort"
 	"strings"
 	"sync"
 
 	"github.com/coreos/etcd/pkg/flags"
+	"github.com/coreos/etcd/pkg/netutil"
 	"github.com/coreos/etcd/pkg/types"
 	"github.com/coreos/etcd/raft/raftpb"
 	"github.com/coreos/etcd/store"
@@ -391,7 +391,8 @@ func ValidateClusterAndAssignIDs(local *Cluster, existing *Cluster) error {
 	sort.Sort(SortableMemberSliceByPeerURLs(lms))
 
 	for i := range ems {
-		if !reflect.DeepEqual(ems[i].PeerURLs, lms[i].PeerURLs) {
+		// TODO: Remove URLStringsEqual after improvement of using hostnames #2150 #2123
+		if !netutil.URLStringsEqual(ems[i].PeerURLs, lms[i].PeerURLs) {
 			return fmt.Errorf("unmatched member while checking PeerURLs")
 		}
 		lms[i].ID = ems[i].ID

+ 3 - 2
etcdserver/config.go

@@ -19,9 +19,9 @@ import (
 	"log"
 	"net/http"
 	"path"
-	"reflect"
 	"sort"
 
+	"github.com/coreos/etcd/pkg/netutil"
 	"github.com/coreos/etcd/pkg/types"
 	"github.com/coreos/etcd/raft"
 )
@@ -74,9 +74,10 @@ func (c *ServerConfig) VerifyBootstrapConfig() error {
 	}
 
 	// Advertised peer URLs must match those in the cluster peer list
+	// TODO: Remove URLStringsEqual after improvement of using hostnames #2150 #2123
 	apurls := c.PeerURLs.StringSlice()
 	sort.Strings(apurls)
-	if !reflect.DeepEqual(apurls, m.PeerURLs) {
+	if !netutil.URLStringsEqual(apurls, m.PeerURLs) {
 		return fmt.Errorf("%s has different advertised URLs in the cluster and advertised peer URLs list", c.Name)
 	}
 	return nil

+ 46 - 0
pkg/netutil/netutil.go

@@ -18,6 +18,7 @@ import (
 	"log"
 	"net"
 	"net/url"
+	"reflect"
 )
 
 var (
@@ -53,3 +54,48 @@ func ResolveTCPAddrs(urls ...[]url.URL) error {
 	}
 	return nil
 }
+
+// URLsEqual checks equality of url.URLS between two arrays.
+// This check pass even if an URL is in hostname and opposite is in IP address.
+func URLsEqual(a []url.URL, b []url.URL) bool {
+	if len(a) != len(b) {
+		return false
+	}
+	for i, urlA := range a {
+		urlB := b[i]
+
+		if !reflect.DeepEqual(urlA, urlB) {
+			urls := []url.URL{urlA, urlB}
+			ResolveTCPAddrs(urls)
+			if !reflect.DeepEqual(urls[0], urls[1]) {
+				return false
+			}
+		}
+	}
+
+	return true
+}
+
+func URLStringsEqual(a []string, b []string) bool {
+	if len(a) != len(b) {
+		return false
+	}
+	urlsA := make([]url.URL, len(a))
+	for _, str := range a {
+		u, err := url.Parse(str)
+		if err != nil {
+			return false
+		}
+		urlsA = append(urlsA, *u)
+	}
+	urlsB := make([]url.URL, len(b))
+	for _, str := range b {
+		u, err := url.Parse(str)
+		if err != nil {
+			return false
+		}
+		urlsB = append(urlsB, *u)
+	}
+
+	return URLsEqual(urlsA, urlsB)
+}

+ 105 - 0
pkg/netutil/netutil_test.go

@@ -136,3 +136,108 @@ func TestResolveTCPAddrs(t *testing.T) {
 		}
 	}
 }
+
+func TestURLsEqual(t *testing.T) {
+	defer func() { resolveTCPAddr = net.ResolveTCPAddr }()
+	resolveTCPAddr = func(network, addr string) (*net.TCPAddr, error) {
+		host, port, err := net.SplitHostPort(addr)
+		if host != "example.com" {
+			return nil, errors.New("cannot resolve host.")
+		}
+		i, err := strconv.Atoi(port)
+		if err != nil {
+			return nil, err
+		}
+		return &net.TCPAddr{IP: net.ParseIP("10.0.10.1"), Port: i, Zone: ""}, nil
+	}
+
+	tests := []struct {
+		a      []url.URL
+		b      []url.URL
+		expect bool
+	}{
+		{
+			a:      []url.URL{{Scheme: "http", Host: "127.0.0.1:4001"}},
+			b:      []url.URL{{Scheme: "http", Host: "127.0.0.1:4001"}},
+			expect: true,
+		},
+		{
+			a:      []url.URL{{Scheme: "http", Host: "example.com:4001"}},
+			b:      []url.URL{{Scheme: "http", Host: "10.0.10.1:4001"}},
+			expect: true,
+		},
+		{
+			a:      []url.URL{{Scheme: "http", Host: "127.0.0.1:4001"}, {Scheme: "http", Host: "127.0.0.1:7001"}},
+			b:      []url.URL{{Scheme: "http", Host: "127.0.0.1:4001"}, {Scheme: "http", Host: "127.0.0.1:7001"}},
+			expect: true,
+		},
+		{
+			a:      []url.URL{{Scheme: "http", Host: "example.com:4001"}, {Scheme: "http", Host: "127.0.0.1:7001"}},
+			b:      []url.URL{{Scheme: "http", Host: "example.com:4001"}, {Scheme: "http", Host: "127.0.0.1:7001"}},
+			expect: true,
+		},
+		{
+			a:      []url.URL{{Scheme: "http", Host: "10.0.10.1:4001"}, {Scheme: "http", Host: "127.0.0.1:7001"}},
+			b:      []url.URL{{Scheme: "http", Host: "example.com:4001"}, {Scheme: "http", Host: "127.0.0.1:7001"}},
+			expect: true,
+		},
+		{
+			a:      []url.URL{{Scheme: "http", Host: "127.0.0.1:4001"}},
+			b:      []url.URL{{Scheme: "http", Host: "127.0.0.1:7001"}},
+			expect: false,
+		},
+		{
+			a:      []url.URL{{Scheme: "http", Host: "example.com:7001"}},
+			b:      []url.URL{{Scheme: "http", Host: "10.0.10.1:4001"}},
+			expect: false,
+		},
+		{
+			a:      []url.URL{{Scheme: "http", Host: "127.0.0.1:4001"}},
+			b:      []url.URL{{Scheme: "http", Host: "10.0.0.1:4001"}},
+			expect: false,
+		},
+		{
+			a:      []url.URL{{Scheme: "http", Host: "example.com:4001"}},
+			b:      []url.URL{{Scheme: "http", Host: "10.0.0.1:4001"}},
+			expect: false,
+		},
+		{
+			a:      []url.URL{{Scheme: "http", Host: "127.0.0.1:4001"}, {Scheme: "http", Host: "127.0.0.1:7001"}},
+			b:      []url.URL{{Scheme: "http", Host: "127.0.0.1:7001"}, {Scheme: "http", Host: "127.0.0.1:7001"}},
+			expect: false,
+		},
+		{
+			a:      []url.URL{{Scheme: "http", Host: "example.com:4001"}, {Scheme: "http", Host: "127.0.0.1:7001"}},
+			b:      []url.URL{{Scheme: "http", Host: "127.0.0.1:7001"}, {Scheme: "http", Host: "127.0.0.1:7001"}},
+			expect: false,
+		},
+		{
+			a:      []url.URL{{Scheme: "http", Host: "127.0.0.1:4001"}, {Scheme: "http", Host: "127.0.0.1:7001"}},
+			b:      []url.URL{{Scheme: "http", Host: "10.0.0.1:4001"}, {Scheme: "http", Host: "127.0.0.1:7001"}},
+			expect: false,
+		},
+		{
+			a:      []url.URL{{Scheme: "http", Host: "example.com:4001"}, {Scheme: "http", Host: "127.0.0.1:7001"}},
+			b:      []url.URL{{Scheme: "http", Host: "10.0.0.1:4001"}, {Scheme: "http", Host: "127.0.0.1:7001"}},
+			expect: false,
+		},
+		{
+			a:      []url.URL{{Scheme: "http", Host: "10.0.0.1:4001"}},
+			b:      []url.URL{{Scheme: "http", Host: "10.0.0.1:4001"}, {Scheme: "http", Host: "127.0.0.1:7001"}},
+			expect: false,
+		},
+	}
+
+	for _, test := range tests {
+		result := URLsEqual(test.a, test.b)
+		if result != test.expect {
+			t.Errorf("a:%v b:%v, expected %v but %v", test.a, test.b, test.expect, result)
+		}
+	}
+}
+func TestURLStringsEqual(t *testing.T) {
+	result := URLStringsEqual([]string{"http://127.0.0.1:8080"}, []string{"http://127.0.0.1:8080"})
+	if !result {
+		t.Errorf("unexpected result %v", result)
+	}
+}