Browse Source

*: move srv into pkg discovery

Xiang Li 11 years ago
parent
commit
08e9c25ea5
5 changed files with 214 additions and 161 deletions
  1. 95 0
      discovery/srv.go
  2. 101 0
      discovery/srv_test.go
  3. 1 70
      etcdmain/etcd.go
  4. 2 91
      etcdmain/etcd_test.go
  5. 15 0
      pkg/testutil/testutil.go

+ 95 - 0
discovery/srv.go

@@ -0,0 +1,95 @@
+/*
+   Copyright 2014 CoreOS, Inc.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package discovery
+
+import (
+	"fmt"
+	"log"
+	"net"
+	"strings"
+
+	"github.com/coreos/etcd/pkg/types"
+)
+
+var (
+	// indirection for testing
+	lookupSRV = net.LookupSRV
+)
+
+// TODO(barakmich): Currently ignores priority and weight (as they don't make as much sense for a bootstrap)
+// Also doesn't do any lookups for the token (though it could)
+// Also sees each entry as a separate instance.
+func SRVGetCluster(name, dns string, defaultToken string, apurls types.URLs) (string, string, error) {
+	stringParts := make([]string, 0)
+	tempName := int(0)
+	tcpAPUrls := make([]string, 0)
+
+	// First, resolve the apurls
+	for _, url := range apurls {
+		tcpAddr, err := net.ResolveTCPAddr("tcp", url.Host)
+		if err != nil {
+			log.Printf("discovery: Couldn't resolve host %s during SRV discovery", url.Host)
+			return "", "", err
+		}
+		tcpAPUrls = append(tcpAPUrls, tcpAddr.String())
+	}
+
+	updateNodeMap := func(service, prefix string) error {
+		_, addrs, err := lookupSRV(service, "tcp", dns)
+		if err != nil {
+			return err
+		}
+		for _, srv := range addrs {
+			host := net.JoinHostPort(srv.Target, fmt.Sprintf("%d", srv.Port))
+			tcpAddr, err := net.ResolveTCPAddr("tcp", host)
+			if err != nil {
+				log.Printf("discovery: Couldn't resolve host %s during SRV discovery", host)
+				continue
+			}
+			n := ""
+			for _, url := range tcpAPUrls {
+				if url == tcpAddr.String() {
+					n = name
+				}
+			}
+			if n == "" {
+				n = fmt.Sprintf("%d", tempName)
+				tempName += 1
+			}
+			stringParts = append(stringParts, fmt.Sprintf("%s=%s%s", n, prefix, tcpAddr.String()))
+			log.Printf("discovery: Got bootstrap from DNS for %s at host %s to %s%s", service, host, prefix, tcpAddr.String())
+		}
+		return nil
+	}
+
+	failCount := 0
+	err := updateNodeMap("etcd-server-ssl", "https://")
+	if err != nil {
+		log.Printf("discovery: Error querying DNS SRV records for _etcd-server-ssl %s", err)
+		failCount += 1
+	}
+	err = updateNodeMap("etcd-server", "http://")
+	if err != nil {
+		log.Printf("discovery: Error querying DNS SRV records for _etcd-server %s", err)
+		failCount += 1
+	}
+	if failCount == 2 {
+		log.Printf("discovery: SRV discovery failed: too many errors querying DNS SRV records")
+		return "", "", err
+	}
+	return strings.Join(stringParts, ","), defaultToken, nil
+}

+ 101 - 0
discovery/srv_test.go

@@ -0,0 +1,101 @@
+/*
+   Copyright 2014 CoreOS, Inc.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package discovery
+
+import (
+	"errors"
+	"net"
+	"testing"
+
+	"github.com/coreos/etcd/pkg/testutil"
+)
+
+func TestSRVGetCluster(t *testing.T) {
+	defer func() { lookupSRV = net.LookupSRV }()
+
+	name := "dnsClusterTest"
+	tests := []struct {
+		withSSL    []*net.SRV
+		withoutSSL []*net.SRV
+		urls       []string
+		expected   string
+	}{
+		{
+			[]*net.SRV{},
+			[]*net.SRV{},
+			nil,
+			"",
+		},
+		{
+			[]*net.SRV{
+				&net.SRV{Target: "10.0.0.1", Port: 2480},
+				&net.SRV{Target: "10.0.0.2", Port: 2480},
+				&net.SRV{Target: "10.0.0.3", Port: 2480},
+			},
+			[]*net.SRV{},
+			nil,
+			"0=https://10.0.0.1:2480,1=https://10.0.0.2:2480,2=https://10.0.0.3:2480",
+		},
+		{
+			[]*net.SRV{
+				&net.SRV{Target: "10.0.0.1", Port: 2480},
+				&net.SRV{Target: "10.0.0.2", Port: 2480},
+				&net.SRV{Target: "10.0.0.3", Port: 2480},
+			},
+			[]*net.SRV{
+				&net.SRV{Target: "10.0.0.1", Port: 7001},
+			},
+			nil,
+			"0=https://10.0.0.1:2480,1=https://10.0.0.2:2480,2=https://10.0.0.3:2480,3=http://10.0.0.1:7001",
+		},
+		{
+			[]*net.SRV{
+				&net.SRV{Target: "10.0.0.1", Port: 2480},
+				&net.SRV{Target: "10.0.0.2", Port: 2480},
+				&net.SRV{Target: "10.0.0.3", Port: 2480},
+			},
+			[]*net.SRV{
+				&net.SRV{Target: "10.0.0.1", Port: 7001},
+			},
+			[]string{"https://10.0.0.1:2480"},
+			"dnsClusterTest=https://10.0.0.1:2480,0=https://10.0.0.2:2480,1=https://10.0.0.3:2480,2=http://10.0.0.1:7001",
+		},
+	}
+
+	for i, tt := range tests {
+		lookupSRV = func(service string, proto string, domain string) (string, []*net.SRV, error) {
+			if service == "etcd-server-ssl" {
+				return "", tt.withSSL, nil
+			}
+			if service == "etcd-server" {
+				return "", tt.withoutSSL, nil
+			}
+			return "", nil, errors.New("Unkown service in mock")
+		}
+		urls := testutil.MustNewURLs(t, tt.urls)
+		str, token, err := SRVGetCluster(name, "example.com", "token", urls)
+		if err != nil {
+			t.Fatalf("%d: err: %#v", i, err)
+		}
+		if token != "token" {
+			t.Errorf("%d: token: %s", i, token)
+		}
+		if str != tt.expected {
+			t.Errorf("#%d: cluster = %s, want %s", i, str, tt.expected)
+		}
+	}
+}

+ 1 - 70
etcdmain/etcd.go

@@ -40,11 +40,6 @@ const (
 	privateDirMode = 0700
 	privateDirMode = 0700
 )
 )
 
 
-var (
-	// indirection for testing
-	lookupSRV = net.LookupSRV
-)
-
 func Main() {
 func Main() {
 	cfg := NewConfig()
 	cfg := NewConfig()
 	err := cfg.Parse(os.Args[1:])
 	err := cfg.Parse(os.Args[1:])
@@ -260,7 +255,7 @@ func setupCluster(cfg *config) (*etcdserver.Cluster, error) {
 		clusterStr := genClusterString(cfg.name, cfg.apurls)
 		clusterStr := genClusterString(cfg.name, cfg.apurls)
 		cls, err = etcdserver.NewClusterFromString(cfg.durl, clusterStr)
 		cls, err = etcdserver.NewClusterFromString(cfg.durl, clusterStr)
 	case cfg.dnsCluster != "":
 	case cfg.dnsCluster != "":
-		clusterStr, clusterToken, err := genDNSClusterString(cfg.name, cfg.dnsCluster, cfg.initialClusterToken, cfg.apurls)
+		clusterStr, clusterToken, err := discovery.SRVGetCluster(cfg.name, cfg.dnsCluster, cfg.initialClusterToken, cfg.apurls)
 		if err != nil {
 		if err != nil {
 			return nil, err
 			return nil, err
 		}
 		}
@@ -279,67 +274,3 @@ func genClusterString(name string, urls types.URLs) string {
 	}
 	}
 	return strings.Join(addrs, ",")
 	return strings.Join(addrs, ",")
 }
 }
-
-// TODO(barakmich): Currently ignores priority and weight (as they don't make as much sense for a bootstrap)
-// Also doesn't do any lookups for the token (though it could)
-// Also sees each entry as a separate instance.
-func genDNSClusterString(name, dns string, defaultToken string, apurls types.URLs) (string, string, error) {
-	stringParts := make([]string, 0)
-	tempName := int(0)
-	tcpAPUrls := make([]string, 0)
-
-	// First, resolve the apurls
-	for _, url := range apurls {
-		tcpAddr, err := net.ResolveTCPAddr("tcp", url.Host)
-		if err != nil {
-			log.Printf("etcd: Couldn't resolve host %s during SRV discovery", url.Host)
-			return "", "", err
-		}
-		tcpAPUrls = append(tcpAPUrls, tcpAddr.String())
-	}
-
-	updateNodeMap := func(service, prefix string) error {
-		_, addrs, err := lookupSRV(service, "tcp", dns)
-		if err != nil {
-			return err
-		}
-		for _, srv := range addrs {
-			host := net.JoinHostPort(srv.Target, fmt.Sprintf("%d", srv.Port))
-			tcpAddr, err := net.ResolveTCPAddr("tcp", host)
-			if err != nil {
-				log.Printf("etcd: Couldn't resolve host %s during SRV discovery", host)
-				continue
-			}
-			n := ""
-			for _, url := range tcpAPUrls {
-				if url == tcpAddr.String() {
-					n = name
-				}
-			}
-			if n == "" {
-				n = fmt.Sprintf("%d", tempName)
-				tempName += 1
-			}
-			stringParts = append(stringParts, fmt.Sprintf("%s=%s%s", n, prefix, tcpAddr.String()))
-			log.Printf("etcd: Got bootstrap from DNS for %s at host %s to %s%s", service, host, prefix, tcpAddr.String())
-		}
-		return nil
-	}
-
-	failCount := 0
-	err := updateNodeMap("etcd-server-ssl", "https://")
-	if err != nil {
-		log.Printf("etcd: Error querying DNS SRV records for _etcd-server-ssl. Error: %s.", err)
-		failCount += 1
-	}
-	err = updateNodeMap("etcd-server", "http://")
-	if err != nil {
-		log.Printf("etcd: Error querying DNS SRV records for _etcd-server. Error: %s.", err)
-		failCount += 1
-	}
-	if failCount == 2 {
-		log.Printf("etcd: Too many errors querying DNS SRV records. Failing discovery.")
-		return "", "", err
-	}
-	return strings.Join(stringParts, ","), defaultToken, nil
-}

+ 2 - 91
etcdmain/etcd_test.go

@@ -17,25 +17,11 @@
 package etcdmain
 package etcdmain
 
 
 import (
 import (
-	"errors"
-	"net"
-	"net/url"
 	"testing"
 	"testing"
 
 
-	"github.com/coreos/etcd/pkg/types"
+	"github.com/coreos/etcd/pkg/testutil"
 )
 )
 
 
-func mustNewURLs(t *testing.T, urls []string) []url.URL {
-	if urls == nil {
-		return nil
-	}
-	u, err := types.NewURLs(urls)
-	if err != nil {
-		t.Fatalf("unexpected new urls error: %v", err)
-	}
-	return u
-}
-
 func TestGenClusterString(t *testing.T) {
 func TestGenClusterString(t *testing.T) {
 	tests := []struct {
 	tests := []struct {
 		token string
 		token string
@@ -52,85 +38,10 @@ func TestGenClusterString(t *testing.T) {
 		},
 		},
 	}
 	}
 	for i, tt := range tests {
 	for i, tt := range tests {
-		urls := mustNewURLs(t, tt.urls)
+		urls := testutil.MustNewURLs(t, tt.urls)
 		str := genClusterString(tt.token, urls)
 		str := genClusterString(tt.token, urls)
 		if str != tt.wstr {
 		if str != tt.wstr {
 			t.Errorf("#%d: cluster = %s, want %s", i, str, tt.wstr)
 			t.Errorf("#%d: cluster = %s, want %s", i, str, tt.wstr)
 		}
 		}
 	}
 	}
 }
 }
-
-func TestGenDNSClusterString(t *testing.T) {
-	name := "dnsClusterTest"
-	tests := []struct {
-		withSSL    []*net.SRV
-		withoutSSL []*net.SRV
-		urls       []string
-		expected   string
-	}{
-		{
-			[]*net.SRV{},
-			[]*net.SRV{},
-			nil,
-			"",
-		},
-		{
-			[]*net.SRV{
-				&net.SRV{Target: "10.0.0.1", Port: 2480},
-				&net.SRV{Target: "10.0.0.2", Port: 2480},
-				&net.SRV{Target: "10.0.0.3", Port: 2480},
-			},
-			[]*net.SRV{},
-			nil,
-			"0=https://10.0.0.1:2480,1=https://10.0.0.2:2480,2=https://10.0.0.3:2480",
-		},
-		{
-			[]*net.SRV{
-				&net.SRV{Target: "10.0.0.1", Port: 2480},
-				&net.SRV{Target: "10.0.0.2", Port: 2480},
-				&net.SRV{Target: "10.0.0.3", Port: 2480},
-			},
-			[]*net.SRV{
-				&net.SRV{Target: "10.0.0.1", Port: 7001},
-			},
-			nil,
-			"0=https://10.0.0.1:2480,1=https://10.0.0.2:2480,2=https://10.0.0.3:2480,3=http://10.0.0.1:7001",
-		},
-		{
-			[]*net.SRV{
-				&net.SRV{Target: "10.0.0.1", Port: 2480},
-				&net.SRV{Target: "10.0.0.2", Port: 2480},
-				&net.SRV{Target: "10.0.0.3", Port: 2480},
-			},
-			[]*net.SRV{
-				&net.SRV{Target: "10.0.0.1", Port: 7001},
-			},
-			[]string{"https://10.0.0.1:2480"},
-			"dnsClusterTest=https://10.0.0.1:2480,0=https://10.0.0.2:2480,1=https://10.0.0.3:2480,2=http://10.0.0.1:7001",
-		},
-	}
-
-	for i, tt := range tests {
-		lookupSRV = func(service string, proto string, domain string) (string, []*net.SRV, error) {
-			if service == "etcd-server-ssl" {
-				return "", tt.withSSL, nil
-			}
-			if service == "etcd-server" {
-				return "", tt.withoutSSL, nil
-			}
-			return "", nil, errors.New("Unkown service in mock")
-		}
-		defer func() { lookupSRV = net.LookupSRV }()
-		urls := mustNewURLs(t, tt.urls)
-		str, token, err := genDNSClusterString(name, "example.com", "token", urls)
-		if err != nil {
-			t.Fatalf("%d: err: %#v", i, err)
-		}
-		if token != "token" {
-			t.Errorf("%d: token: %s", i, token)
-		}
-		if str != tt.expected {
-			t.Errorf("#%d: cluster = %s, want %s", i, str, tt.expected)
-		}
-	}
-}

+ 15 - 0
pkg/testutil/testutil.go

@@ -17,7 +17,11 @@
 package testutil
 package testutil
 
 
 import (
 import (
+	"net/url"
 	"runtime"
 	"runtime"
+	"testing"
+
+	"github.com/coreos/etcd/pkg/types"
 )
 )
 
 
 // WARNING: This is a hack.
 // WARNING: This is a hack.
@@ -28,3 +32,14 @@ func ForceGosched() {
 		runtime.Gosched()
 		runtime.Gosched()
 	}
 	}
 }
 }
+
+func MustNewURLs(t *testing.T, urls []string) []url.URL {
+	if urls == nil {
+		return nil
+	}
+	u, err := types.NewURLs(urls)
+	if err != nil {
+		t.Fatalf("unexpected new urls error: %v", err)
+	}
+	return u
+}