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 }