Treat URLs have same IP address as same

- To solve validation error problem using URLs in hostname #2123
This commit is contained in:
Shota Fukumori (sora_h)
2015-01-26 16:26:21 +09:00
parent 9c7f66c5d9
commit f8ce5996b0
4 changed files with 157 additions and 4 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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)
}
}