Browse Source

Merge pull request #7733 from heyitsanthony/fix-client-foreign-dial

clientv3: let client dial endpoints not in the balancer
Anthony Romano 8 years ago
parent
commit
2951e7f6e4
2 changed files with 30 additions and 1 deletions
  1. 6 1
      clientv3/client.go
  2. 24 0
      clientv3/integration/dial_test.go

+ 6 - 1
clientv3/client.go

@@ -219,6 +219,11 @@ func (c *Client) dialSetupOpts(endpoint string, dopts ...grpc.DialOption) (opts
 
 
 	f := func(host string, t time.Duration) (net.Conn, error) {
 	f := func(host string, t time.Duration) (net.Conn, error) {
 		proto, host, _ := parseEndpoint(c.balancer.getEndpoint(host))
 		proto, host, _ := parseEndpoint(c.balancer.getEndpoint(host))
+		if host == "" && endpoint != "" {
+			// dialing an endpoint not in the balancer; use
+			// endpoint passed into dial
+			proto, host, _ = parseEndpoint(endpoint)
+		}
 		if proto == "" {
 		if proto == "" {
 			return nil, fmt.Errorf("unknown scheme for %q", host)
 			return nil, fmt.Errorf("unknown scheme for %q", host)
 		}
 		}
@@ -358,7 +363,7 @@ func newClient(cfg *Config) (*Client, error) {
 	}
 	}
 
 
 	client.balancer = newSimpleBalancer(cfg.Endpoints)
 	client.balancer = newSimpleBalancer(cfg.Endpoints)
-	conn, err := client.dial(cfg.Endpoints[0], grpc.WithBalancer(client.balancer))
+	conn, err := client.dial("", grpc.WithBalancer(client.balancer))
 	if err != nil {
 	if err != nil {
 		client.cancel()
 		client.cancel()
 		client.balancer.Close()
 		client.balancer.Close()

+ 24 - 0
clientv3/integration/dial_test.go

@@ -20,6 +20,7 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/coreos/etcd/clientv3"
 	"github.com/coreos/etcd/clientv3"
+	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
 	"github.com/coreos/etcd/integration"
 	"github.com/coreos/etcd/integration"
 	"github.com/coreos/etcd/pkg/testutil"
 	"github.com/coreos/etcd/pkg/testutil"
 	"golang.org/x/net/context"
 	"golang.org/x/net/context"
@@ -109,3 +110,26 @@ func TestRejectOldCluster(t *testing.T) {
 	}
 	}
 	cli.Close()
 	cli.Close()
 }
 }
+
+// TestDialForeignEndpoint checks an endpoint that is not registered
+// with the balancer can be dialed.
+func TestDialForeignEndpoint(t *testing.T) {
+	defer testutil.AfterTest(t)
+	clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 2})
+	defer clus.Terminate(t)
+
+	conn, err := clus.Client(0).Dial(clus.Client(1).Endpoints()[0])
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer conn.Close()
+
+	// grpc can return a lazy connection that's not connected yet; confirm
+	// that it can communicate with the cluster.
+	kvc := clientv3.NewKVFromKVClient(pb.NewKVClient(conn))
+	ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Second)
+	defer cancel()
+	if _, gerr := kvc.Get(ctx, "abc"); gerr != nil {
+		t.Fatal(err)
+	}
+}