github.com/lfch/etcd-io/tests/v3@v3.0.0-20221004140520-eac99acd3e9d/integration/clientv3/connectivity/dial_test.go (about)

     1  // Copyright 2016 The etcd Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package connectivity_test
    16  
    17  import (
    18  	"context"
    19  	"math/rand"
    20  	"strings"
    21  	"testing"
    22  	"time"
    23  
    24  	pb "github.com/lfch/etcd-io/api/v3/etcdserverpb"
    25  	"github.com/lfch/etcd-io/client/pkg/v3/transport"
    26  	"github.com/lfch/etcd-io/client/v3"
    27  	integration2 "github.com/lfch/etcd-io/tests/v3/framework/integration"
    28  	clientv3test "github.com/lfch/etcd-io/tests/v3/integration/clientv3"
    29  	"google.golang.org/grpc"
    30  )
    31  
    32  var (
    33  	testTLSInfo = transport.TLSInfo{
    34  		KeyFile:        integration2.MustAbsPath("../../../fixtures/server.key.insecure"),
    35  		CertFile:       integration2.MustAbsPath("../../../fixtures/server.crt"),
    36  		TrustedCAFile:  integration2.MustAbsPath("../../../fixtures/ca.crt"),
    37  		ClientCertAuth: true,
    38  	}
    39  
    40  	testTLSInfoExpired = transport.TLSInfo{
    41  		KeyFile:        integration2.MustAbsPath("../../fixtures-expired/server.key.insecure"),
    42  		CertFile:       integration2.MustAbsPath("../../fixtures-expired/server.crt"),
    43  		TrustedCAFile:  integration2.MustAbsPath("../../fixtures-expired/ca.crt"),
    44  		ClientCertAuth: true,
    45  	}
    46  )
    47  
    48  // TestDialTLSExpired tests client with expired certs fails to dial.
    49  func TestDialTLSExpired(t *testing.T) {
    50  	integration2.BeforeTest(t)
    51  	clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, PeerTLS: &testTLSInfo, ClientTLS: &testTLSInfo})
    52  	defer clus.Terminate(t)
    53  
    54  	tls, err := testTLSInfoExpired.ClientConfig()
    55  	if err != nil {
    56  		t.Fatal(err)
    57  	}
    58  	// expect remote errors "tls: bad certificate"
    59  	_, err = integration2.NewClient(t, clientv3.Config{
    60  		Endpoints:   []string{clus.Members[0].GRPCURL()},
    61  		DialTimeout: 3 * time.Second,
    62  		DialOptions: []grpc.DialOption{grpc.WithBlock()},
    63  		TLS:         tls,
    64  	})
    65  	if !clientv3test.IsClientTimeout(err) {
    66  		t.Fatalf("expected dial timeout error, got %v", err)
    67  	}
    68  }
    69  
    70  // TestDialTLSNoConfig ensures the client fails to dial / times out
    71  // when TLS endpoints (https, unixs) are given but no tls config.
    72  func TestDialTLSNoConfig(t *testing.T) {
    73  	integration2.BeforeTest(t)
    74  	clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 1, ClientTLS: &testTLSInfo})
    75  	defer clus.Terminate(t)
    76  	// expect "signed by unknown authority"
    77  	c, err := integration2.NewClient(t, clientv3.Config{
    78  		Endpoints:   []string{clus.Members[0].GRPCURL()},
    79  		DialTimeout: time.Second,
    80  		DialOptions: []grpc.DialOption{grpc.WithBlock()},
    81  	})
    82  	defer func() {
    83  		if c != nil {
    84  			c.Close()
    85  		}
    86  	}()
    87  	if !clientv3test.IsClientTimeout(err) {
    88  		t.Fatalf("expected dial timeout error, got %v", err)
    89  	}
    90  }
    91  
    92  // TestDialSetEndpointsBeforeFail ensures SetEndpoints can replace unavailable
    93  // endpoints with available ones.
    94  func TestDialSetEndpointsBeforeFail(t *testing.T) {
    95  	testDialSetEndpoints(t, true)
    96  }
    97  
    98  func TestDialSetEndpointsAfterFail(t *testing.T) {
    99  	testDialSetEndpoints(t, false)
   100  }
   101  
   102  // testDialSetEndpoints ensures SetEndpoints can replace unavailable endpoints with available ones.
   103  func testDialSetEndpoints(t *testing.T, setBefore bool) {
   104  	integration2.BeforeTest(t)
   105  	clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3})
   106  	defer clus.Terminate(t)
   107  
   108  	// get endpoint list
   109  	eps := make([]string, 3)
   110  	for i := range eps {
   111  		eps[i] = clus.Members[i].GRPCURL()
   112  	}
   113  	toKill := rand.Intn(len(eps))
   114  
   115  	cfg := clientv3.Config{
   116  		Endpoints:   []string{eps[toKill]},
   117  		DialTimeout: 1 * time.Second,
   118  		DialOptions: []grpc.DialOption{grpc.WithBlock()},
   119  	}
   120  	cli, err := integration2.NewClient(t, cfg)
   121  	if err != nil {
   122  		t.Fatal(err)
   123  	}
   124  	defer cli.Close()
   125  
   126  	if setBefore {
   127  		cli.SetEndpoints(eps[toKill%3], eps[(toKill+1)%3])
   128  	}
   129  	// make a dead node
   130  	clus.Members[toKill].Stop(t)
   131  	clus.WaitLeader(t)
   132  
   133  	if !setBefore {
   134  		cli.SetEndpoints(eps[toKill%3], eps[(toKill+1)%3])
   135  	}
   136  	time.Sleep(time.Second * 2)
   137  	ctx, cancel := context.WithTimeout(context.Background(), integration2.RequestWaitTimeout)
   138  	if _, err = cli.Get(ctx, "foo", clientv3.WithSerializable()); err != nil {
   139  		t.Fatal(err)
   140  	}
   141  	cancel()
   142  }
   143  
   144  // TestSwitchSetEndpoints ensures SetEndpoints can switch one endpoint
   145  // with a new one that doesn't include original endpoint.
   146  func TestSwitchSetEndpoints(t *testing.T) {
   147  	integration2.BeforeTest(t)
   148  	clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 3})
   149  	defer clus.Terminate(t)
   150  
   151  	// get non partitioned members endpoints
   152  	eps := []string{clus.Members[1].GRPCURL(), clus.Members[2].GRPCURL()}
   153  
   154  	cli := clus.Client(0)
   155  	clus.Members[0].InjectPartition(t, clus.Members[1:]...)
   156  
   157  	cli.SetEndpoints(eps...)
   158  
   159  	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
   160  	defer cancel()
   161  	if _, err := cli.Get(ctx, "foo"); err != nil {
   162  		t.Fatal(err)
   163  	}
   164  }
   165  
   166  func TestRejectOldCluster(t *testing.T) {
   167  	integration2.BeforeTest(t)
   168  	// 2 endpoints to test multi-endpoint Status
   169  	clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 2})
   170  	defer clus.Terminate(t)
   171  
   172  	cfg := clientv3.Config{
   173  		Endpoints:        []string{clus.Members[0].GRPCURL(), clus.Members[1].GRPCURL()},
   174  		DialTimeout:      5 * time.Second,
   175  		DialOptions:      []grpc.DialOption{grpc.WithBlock()},
   176  		RejectOldCluster: true,
   177  	}
   178  	cli, err := integration2.NewClient(t, cfg)
   179  	if err != nil {
   180  		t.Fatal(err)
   181  	}
   182  	cli.Close()
   183  }
   184  
   185  // TestDialForeignEndpoint checks an endpoint that is not registered
   186  // with the balancer can be dialed.
   187  func TestDialForeignEndpoint(t *testing.T) {
   188  	integration2.BeforeTest(t)
   189  	clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 2})
   190  	defer clus.Terminate(t)
   191  
   192  	conn, err := clus.Client(0).Dial(clus.Client(1).Endpoints()[0])
   193  	if err != nil {
   194  		t.Fatal(err)
   195  	}
   196  	defer conn.Close()
   197  
   198  	// grpc can return a lazy connection that's not connected yet; confirm
   199  	// that it can communicate with the cluster.
   200  	kvc := clientv3.NewKVFromKVClient(pb.NewKVClient(conn), clus.Client(0))
   201  	ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Second)
   202  	defer cancel()
   203  	if _, gerr := kvc.Get(ctx, "abc"); gerr != nil {
   204  		t.Fatal(err)
   205  	}
   206  }
   207  
   208  // TestSetEndpointAndPut checks that a Put following a SetEndpoints
   209  // to a working endpoint will always succeed.
   210  func TestSetEndpointAndPut(t *testing.T) {
   211  	integration2.BeforeTest(t)
   212  	clus := integration2.NewCluster(t, &integration2.ClusterConfig{Size: 2})
   213  	defer clus.Terminate(t)
   214  
   215  	clus.Client(1).SetEndpoints(clus.Members[0].GRPCURL())
   216  	_, err := clus.Client(1).Put(context.TODO(), "foo", "bar")
   217  	if err != nil && !strings.Contains(err.Error(), "closing") {
   218  		t.Fatal(err)
   219  	}
   220  }