google.golang.org/grpc@v1.72.2/xds/internal/balancer/clusterimpl/tests/balancer_test.go (about) 1 /* 2 * 3 * Copyright 2023 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 package clusterimpl_test 20 21 import ( 22 "context" 23 "fmt" 24 "net" 25 "strconv" 26 "strings" 27 "testing" 28 "time" 29 30 "github.com/google/uuid" 31 "google.golang.org/grpc" 32 "google.golang.org/grpc/codes" 33 "google.golang.org/grpc/connectivity" 34 "google.golang.org/grpc/credentials/insecure" 35 "google.golang.org/grpc/internal" 36 "google.golang.org/grpc/internal/grpctest" 37 "google.golang.org/grpc/internal/stubserver" 38 "google.golang.org/grpc/internal/testutils" 39 "google.golang.org/grpc/internal/testutils/xds/e2e" 40 "google.golang.org/grpc/internal/testutils/xds/fakeserver" 41 "google.golang.org/grpc/peer" 42 "google.golang.org/grpc/resolver" 43 "google.golang.org/grpc/status" 44 "google.golang.org/protobuf/types/known/durationpb" 45 "google.golang.org/protobuf/types/known/wrapperspb" 46 47 v3clusterpb "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" 48 v3corepb "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" 49 v3endpointpb "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" 50 v3listenerpb "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" 51 v3routepb "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" 52 v3pickfirstpb "github.com/envoyproxy/go-control-plane/envoy/extensions/load_balancing_policies/pick_first/v3" 53 v3lrspb "github.com/envoyproxy/go-control-plane/envoy/service/load_stats/v3" 54 testgrpc "google.golang.org/grpc/interop/grpc_testing" 55 testpb "google.golang.org/grpc/interop/grpc_testing" 56 57 _ "google.golang.org/grpc/xds" 58 ) 59 60 const ( 61 defaultTestTimeout = 5 * time.Second 62 defaultTestShortTimeout = 100 * time.Millisecond 63 ) 64 65 type s struct { 66 grpctest.Tester 67 } 68 69 func Test(t *testing.T) { 70 grpctest.RunSubTests(t, s{}) 71 } 72 73 // TestConfigUpdateWithSameLoadReportingServerConfig tests the scenario where 74 // the clusterimpl LB policy receives a config update with no change in the load 75 // reporting server configuration. The test verifies that the existing load 76 // reporting stream is not terminated and that a new load reporting stream is not 77 // created. 78 func (s) TestConfigUpdateWithSameLoadReportingServerConfig(t *testing.T) { 79 // Create an xDS management server that serves ADS and LRS requests. 80 mgmtServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{SupportLoadReportingService: true}) 81 82 // Create bootstrap configuration pointing to the above management server. 83 nodeID := uuid.New().String() 84 bc := e2e.DefaultBootstrapContents(t, nodeID, mgmtServer.Address) 85 testutils.CreateBootstrapFileForTesting(t, bc) 86 87 // Create an xDS resolver with the above bootstrap configuration. 88 var resolverBuilder resolver.Builder 89 var err error 90 if newResolver := internal.NewXDSResolverWithConfigForTesting; newResolver != nil { 91 resolverBuilder, err = newResolver.(func([]byte) (resolver.Builder, error))(bc) 92 if err != nil { 93 t.Fatalf("Failed to create xDS resolver for testing: %v", err) 94 } 95 } 96 97 // Start a server backend exposing the test service. 98 server := stubserver.StartTestService(t, nil) 99 defer server.Stop() 100 101 // Configure the xDS management server with default resources. Override the 102 // default cluster to include an LRS server config pointing to self. 103 const serviceName = "my-test-xds-service" 104 resources := e2e.DefaultClientResources(e2e.ResourceParams{ 105 DialTarget: serviceName, 106 NodeID: nodeID, 107 Host: "localhost", 108 Port: testutils.ParsePort(t, server.Address), 109 SecLevel: e2e.SecurityLevelNone, 110 }) 111 resources.Clusters[0].LrsServer = &v3corepb.ConfigSource{ 112 ConfigSourceSpecifier: &v3corepb.ConfigSource_Self{ 113 Self: &v3corepb.SelfConfigSource{}, 114 }, 115 } 116 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 117 defer cancel() 118 if err := mgmtServer.Update(ctx, resources); err != nil { 119 t.Fatal(err) 120 } 121 122 // Create a ClientConn and make a successful RPC. 123 cc, err := grpc.NewClient(fmt.Sprintf("xds:///%s", serviceName), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(resolverBuilder)) 124 if err != nil { 125 t.Fatalf("failed to dial local test server: %v", err) 126 } 127 defer cc.Close() 128 129 client := testgrpc.NewTestServiceClient(cc) 130 if _, err := client.EmptyCall(ctx, &testpb.Empty{}); err != nil { 131 t.Fatalf("rpc EmptyCall() failed: %v", err) 132 } 133 134 // Ensure that an LRS stream is created. 135 if _, err := mgmtServer.LRSServer.LRSStreamOpenChan.Receive(ctx); err != nil { 136 t.Fatalf("Failure when waiting for an LRS stream to be opened: %v", err) 137 } 138 139 // Configure a new resource on the management server with drop config that 140 // drops all RPCs, but with no change in the load reporting server config. 141 resources.Endpoints = []*v3endpointpb.ClusterLoadAssignment{ 142 e2e.EndpointResourceWithOptions(e2e.EndpointOptions{ 143 ClusterName: "endpoints-" + serviceName, 144 Host: "localhost", 145 Localities: []e2e.LocalityOptions{ 146 { 147 Backends: []e2e.BackendOptions{{Ports: []uint32{testutils.ParsePort(t, server.Address)}}}, 148 Weight: 1, 149 }, 150 }, 151 DropPercents: map[string]int{"test-drop-everything": 100}, 152 }), 153 } 154 if err := mgmtServer.Update(ctx, resources); err != nil { 155 t.Fatal(err) 156 } 157 158 // Repeatedly send RPCs until we sees that they are getting dropped, or the 159 // test context deadline expires. The former indicates that new config with 160 // drops has been applied. 161 for ; ctx.Err() == nil; <-time.After(defaultTestShortTimeout) { 162 _, err := client.EmptyCall(ctx, &testpb.Empty{}) 163 if err != nil && status.Code(err) == codes.Unavailable && strings.Contains(err.Error(), "RPC is dropped") { 164 break 165 } 166 } 167 if ctx.Err() != nil { 168 t.Fatalf("Timeout when waiting for RPCs to be dropped after config update") 169 } 170 171 // Ensure that the old LRS stream is not closed. 172 sCtx, sCancel := context.WithTimeout(ctx, defaultTestShortTimeout) 173 defer sCancel() 174 if _, err := mgmtServer.LRSServer.LRSStreamCloseChan.Receive(sCtx); err == nil { 175 t.Fatal("LRS stream closed when expected not to") 176 } 177 178 // Also ensure that a new LRS stream is not created. 179 sCtx, sCancel = context.WithTimeout(ctx, defaultTestShortTimeout) 180 defer sCancel() 181 if _, err := mgmtServer.LRSServer.LRSStreamOpenChan.Receive(sCtx); err == nil { 182 t.Fatal("New LRS stream created when expected not to") 183 } 184 } 185 186 // Tests whether load is reported correctly when using pickfirst with endpoints 187 // in multiple localities. 188 func (s) TestLoadReportingPickFirstMultiLocality(t *testing.T) { 189 // Create an xDS management server that serves ADS and LRS requests. 190 mgmtServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{SupportLoadReportingService: true}) 191 192 // Create bootstrap configuration pointing to the above management server. 193 nodeID := uuid.New().String() 194 bc := e2e.DefaultBootstrapContents(t, nodeID, mgmtServer.Address) 195 196 // Create an xDS resolver with the above bootstrap configuration. 197 var resolverBuilder resolver.Builder 198 var err error 199 if newResolver := internal.NewXDSResolverWithConfigForTesting; newResolver != nil { 200 resolverBuilder, err = newResolver.(func([]byte) (resolver.Builder, error))(bc) 201 if err != nil { 202 t.Fatalf("Failed to create xDS resolver for testing: %v", err) 203 } 204 } 205 206 // Start two server backends exposing the test service. 207 server1 := stubserver.StartTestService(t, nil) 208 defer server1.Stop() 209 210 server2 := stubserver.StartTestService(t, nil) 211 defer server2.Stop() 212 213 // Configure the xDS management server. 214 const serviceName = "my-test-xds-service" 215 routeConfigName := "route-" + serviceName 216 clusterName := "cluster-" + serviceName 217 endpointsName := "endpoints-" + serviceName 218 resources := e2e.UpdateOptions{ 219 NodeID: nodeID, 220 Listeners: []*v3listenerpb.Listener{e2e.DefaultClientListener(serviceName, routeConfigName)}, 221 Routes: []*v3routepb.RouteConfiguration{e2e.DefaultRouteConfig(routeConfigName, serviceName, clusterName)}, 222 Clusters: []*v3clusterpb.Cluster{ 223 { 224 Name: clusterName, 225 ClusterDiscoveryType: &v3clusterpb.Cluster_Type{Type: v3clusterpb.Cluster_EDS}, 226 EdsClusterConfig: &v3clusterpb.Cluster_EdsClusterConfig{ 227 EdsConfig: &v3corepb.ConfigSource{ 228 ConfigSourceSpecifier: &v3corepb.ConfigSource_Ads{ 229 Ads: &v3corepb.AggregatedConfigSource{}, 230 }, 231 }, 232 ServiceName: endpointsName, 233 }, 234 // Specify a custom load balancing policy to use pickfirst. 235 LoadBalancingPolicy: &v3clusterpb.LoadBalancingPolicy{ 236 Policies: []*v3clusterpb.LoadBalancingPolicy_Policy{ 237 { 238 TypedExtensionConfig: &v3corepb.TypedExtensionConfig{ 239 TypedConfig: testutils.MarshalAny(t, &v3pickfirstpb.PickFirst{}), 240 }, 241 }, 242 }, 243 }, 244 // Include a fake LRS server config pointing to self. 245 LrsServer: &v3corepb.ConfigSource{ 246 ConfigSourceSpecifier: &v3corepb.ConfigSource_Self{ 247 Self: &v3corepb.SelfConfigSource{}, 248 }, 249 }, 250 }, 251 }, 252 Endpoints: []*v3endpointpb.ClusterLoadAssignment{e2e.EndpointResourceWithOptions(e2e.EndpointOptions{ 253 ClusterName: endpointsName, 254 Host: "localhost", 255 Localities: []e2e.LocalityOptions{ 256 { 257 Backends: []e2e.BackendOptions{ 258 {Ports: []uint32{testutils.ParsePort(t, server1.Address)}}, 259 }, 260 Weight: 1, 261 }, 262 { 263 Backends: []e2e.BackendOptions{ 264 {Ports: []uint32{testutils.ParsePort(t, server2.Address)}}, 265 }, 266 Weight: 2, 267 }, 268 }, 269 })}, 270 } 271 272 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 273 defer cancel() 274 if err := mgmtServer.Update(ctx, resources); err != nil { 275 t.Fatal(err) 276 } 277 278 // Create a ClientConn and make a successful RPC. 279 cc, err := grpc.NewClient(fmt.Sprintf("xds:///%s", serviceName), 280 grpc.WithTransportCredentials(insecure.NewCredentials()), 281 grpc.WithResolvers(resolverBuilder)) 282 if err != nil { 283 t.Fatalf("Failed to dial local test server: %v", err) 284 } 285 defer cc.Close() 286 287 client := testgrpc.NewTestServiceClient(cc) 288 var peer peer.Peer 289 if _, err := client.EmptyCall(ctx, &testpb.Empty{}, grpc.Peer(&peer)); err != nil { 290 t.Fatalf("rpc EmptyCall() failed: %v", err) 291 } 292 293 // Verify that the request was sent to server 1. 294 if got, want := peer.Addr.String(), server1.Address; got != want { 295 t.Errorf("peer.Addr = %q, want = %q", got, want) 296 } 297 298 // Ensure that an LRS stream is created. 299 if _, err = mgmtServer.LRSServer.LRSStreamOpenChan.Receive(ctx); err != nil { 300 t.Fatalf("Failure when waiting for an LRS stream to be opened: %v", err) 301 } 302 303 // Handle the initial LRS request from the xDS client. 304 if _, err = mgmtServer.LRSServer.LRSRequestChan.Receive(ctx); err != nil { 305 t.Fatalf("Failure waiting for initial LRS request: %v", err) 306 } 307 308 resp := fakeserver.Response{ 309 Resp: &v3lrspb.LoadStatsResponse{ 310 SendAllClusters: true, 311 LoadReportingInterval: durationpb.New(10 * time.Millisecond), 312 }, 313 } 314 mgmtServer.LRSServer.LRSResponseChan <- &resp 315 316 // Wait for load to be reported for locality of server 1. 317 if err := waitForSuccessfulLoadReport(ctx, mgmtServer.LRSServer, "region-1"); err != nil { 318 t.Fatalf("Server 1 did not receive load due to error: %v", err) 319 } 320 321 // Stop server 1 and send one more rpc. Now the request should go to server 2. 322 server1.Stop() 323 324 // Wait for the balancer to pick up the server state change. 325 testutils.AwaitState(ctx, t, cc, connectivity.Idle) 326 if _, err := client.EmptyCall(ctx, &testpb.Empty{}, grpc.Peer(&peer)); err != nil { 327 t.Fatalf("rpc EmptyCall() failed: %v", err) 328 } 329 330 // Verify that the request was sent to server 2. 331 if got, want := peer.Addr.String(), server2.Address; got != want { 332 t.Errorf("peer.Addr = %q, want = %q", got, want) 333 } 334 335 // Wait for load to be reported for locality of server 2. 336 if err := waitForSuccessfulLoadReport(ctx, mgmtServer.LRSServer, "region-2"); err != nil { 337 t.Fatalf("Server 2 did not receive load due to error: %v", err) 338 } 339 } 340 341 // waitForSuccessfulLoadReport waits for a successful request to be reported for 342 // the specified locality region. 343 func waitForSuccessfulLoadReport(ctx context.Context, lrsServer *fakeserver.Server, region string) error { 344 for { 345 select { 346 case <-ctx.Done(): 347 return ctx.Err() 348 case req := <-lrsServer.LRSRequestChan.C: 349 loadStats := req.(*fakeserver.Request).Req.(*v3lrspb.LoadStatsRequest) 350 for _, load := range loadStats.ClusterStats { 351 for _, locality := range load.UpstreamLocalityStats { 352 if locality.TotalSuccessfulRequests > 0 && locality.Locality.Region == region { 353 return nil 354 } 355 } 356 } 357 } 358 } 359 } 360 361 // Tests that circuit breaking limits RPCs E2E. 362 func (s) TestCircuitBreaking(t *testing.T) { 363 // Create an xDS management server that serves ADS requests. 364 mgmtServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{}) 365 366 // Create bootstrap configuration pointing to the above management server. 367 nodeID := uuid.New().String() 368 bc := e2e.DefaultBootstrapContents(t, nodeID, mgmtServer.Address) 369 testutils.CreateBootstrapFileForTesting(t, bc) 370 371 // Create an xDS resolver with the above bootstrap configuration. 372 var resolverBuilder resolver.Builder 373 var err error 374 if newResolver := internal.NewXDSResolverWithConfigForTesting; newResolver != nil { 375 resolverBuilder, err = newResolver.(func([]byte) (resolver.Builder, error))(bc) 376 if err != nil { 377 t.Fatalf("Failed to create xDS resolver for testing: %v", err) 378 } 379 } 380 381 // Start a server backend exposing the test service. 382 f := &stubserver.StubServer{ 383 EmptyCallF: func(ctx context.Context, _ *testpb.Empty) (*testpb.Empty, error) { 384 return &testpb.Empty{}, nil 385 }, 386 FullDuplexCallF: func(stream testgrpc.TestService_FullDuplexCallServer) error { 387 for { 388 if _, err := stream.Recv(); err != nil { 389 return err 390 } 391 } 392 }, 393 } 394 server := stubserver.StartTestService(t, f) 395 defer server.Stop() 396 397 // Configure the xDS management server with default resources. 398 const serviceName = "my-test-xds-service" 399 const maxRequests = 3 400 resources := e2e.DefaultClientResources(e2e.ResourceParams{ 401 DialTarget: serviceName, 402 NodeID: nodeID, 403 Host: "localhost", 404 Port: testutils.ParsePort(t, server.Address), 405 }) 406 resources.Clusters[0].CircuitBreakers = &v3clusterpb.CircuitBreakers{ 407 Thresholds: []*v3clusterpb.CircuitBreakers_Thresholds{ 408 { 409 Priority: v3corepb.RoutingPriority_DEFAULT, 410 MaxRequests: wrapperspb.UInt32(maxRequests), 411 }, 412 }, 413 } 414 415 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 416 defer cancel() 417 if err := mgmtServer.Update(ctx, resources); err != nil { 418 t.Fatal(err) 419 } 420 421 // Create a ClientConn and make a successful RPC. 422 cc, err := grpc.NewClient(fmt.Sprintf("xds:///%s", serviceName), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(resolverBuilder)) 423 if err != nil { 424 t.Fatalf("failed to dial local test server: %v", err) 425 } 426 defer cc.Close() 427 428 client := testgrpc.NewTestServiceClient(cc) 429 430 // Start maxRequests streams. 431 for range maxRequests { 432 if _, err := client.FullDuplexCall(ctx); err != nil { 433 t.Fatalf("rpc FullDuplexCall() failed: %v", err) 434 } 435 } 436 437 // Since we are at the max, new streams should fail. It's possible some are 438 // allowed due to inherent raciness in the tracking, however. 439 for i := 0; i < 100; i++ { 440 stream, err := client.FullDuplexCall(ctx) 441 if status.Code(err) == codes.Unavailable { 442 return 443 } 444 if err == nil { 445 // Terminate the stream (the server immediately exits upon a client 446 // CloseSend) to ensure we never go over the limit. 447 stream.CloseSend() 448 stream.Recv() 449 } 450 time.Sleep(10 * time.Millisecond) 451 } 452 453 t.Fatalf("RPCs unexpectedly allowed beyond circuit breaking maximum") 454 } 455 456 // Tests that circuit breaking limits RPCs in LOGICAL_DNS clusters E2E. 457 func (s) TestCircuitBreakingLogicalDNS(t *testing.T) { 458 // Create an xDS management server that serves ADS requests. 459 mgmtServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{}) 460 461 // Create bootstrap configuration pointing to the above management server. 462 nodeID := uuid.New().String() 463 bc := e2e.DefaultBootstrapContents(t, nodeID, mgmtServer.Address) 464 testutils.CreateBootstrapFileForTesting(t, bc) 465 466 // Create an xDS resolver with the above bootstrap configuration. 467 var resolverBuilder resolver.Builder 468 var err error 469 if newResolver := internal.NewXDSResolverWithConfigForTesting; newResolver != nil { 470 resolverBuilder, err = newResolver.(func([]byte) (resolver.Builder, error))(bc) 471 if err != nil { 472 t.Fatalf("Failed to create xDS resolver for testing: %v", err) 473 } 474 } 475 476 // Start a server backend exposing the test service. 477 f := &stubserver.StubServer{ 478 EmptyCallF: func(ctx context.Context, _ *testpb.Empty) (*testpb.Empty, error) { 479 return &testpb.Empty{}, nil 480 }, 481 FullDuplexCallF: func(stream testgrpc.TestService_FullDuplexCallServer) error { 482 for { 483 if _, err := stream.Recv(); err != nil { 484 return err 485 } 486 } 487 }, 488 } 489 server := stubserver.StartTestService(t, f) 490 defer server.Stop() 491 host, port := hostAndPortFromAddress(t, server.Address) 492 493 // Configure the xDS management server with default resources. Override the 494 // default cluster to include a circuit breaking config. 495 const serviceName = "my-test-xds-service" 496 const maxRequests = 3 497 resources := e2e.DefaultClientResources(e2e.ResourceParams{ 498 DialTarget: serviceName, 499 NodeID: nodeID, 500 Host: "localhost", 501 Port: testutils.ParsePort(t, server.Address), 502 }) 503 resources.Clusters = []*v3clusterpb.Cluster{ 504 e2e.ClusterResourceWithOptions(e2e.ClusterOptions{ 505 ClusterName: "cluster-" + serviceName, 506 Type: e2e.ClusterTypeLogicalDNS, 507 DNSHostName: host, 508 DNSPort: port, 509 }), 510 } 511 resources.Clusters[0].CircuitBreakers = &v3clusterpb.CircuitBreakers{ 512 Thresholds: []*v3clusterpb.CircuitBreakers_Thresholds{ 513 { 514 Priority: v3corepb.RoutingPriority_DEFAULT, 515 MaxRequests: wrapperspb.UInt32(maxRequests), 516 }, 517 }, 518 } 519 resources.Endpoints = nil 520 521 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 522 defer cancel() 523 if err := mgmtServer.Update(ctx, resources); err != nil { 524 t.Fatal(err) 525 } 526 527 // Create a ClientConn and make a successful RPC. 528 cc, err := grpc.NewClient(fmt.Sprintf("xds:///%s", serviceName), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(resolverBuilder)) 529 if err != nil { 530 t.Fatalf("failed to dial local test server: %v", err) 531 } 532 defer cc.Close() 533 534 client := testgrpc.NewTestServiceClient(cc) 535 536 // Start maxRequests streams. 537 for range maxRequests { 538 if _, err := client.FullDuplexCall(ctx); err != nil { 539 t.Fatalf("rpc FullDuplexCall() failed: %v", err) 540 } 541 } 542 543 // Since we are at the max, new streams should fail. It's possible some are 544 // allowed due to inherent raciness in the tracking, however. 545 for i := 0; i < 100; i++ { 546 stream, err := client.FullDuplexCall(ctx) 547 if status.Code(err) == codes.Unavailable { 548 return 549 } 550 if err == nil { 551 // Terminate the stream (the server immediately exits upon a client 552 // CloseSend) to ensure we never go over the limit. 553 stream.CloseSend() 554 stream.Recv() 555 } 556 time.Sleep(10 * time.Millisecond) 557 } 558 559 t.Fatalf("RPCs unexpectedly allowed beyond circuit breaking maximum") 560 } 561 562 func hostAndPortFromAddress(t *testing.T, addr string) (string, uint32) { 563 t.Helper() 564 565 host, p, err := net.SplitHostPort(addr) 566 if err != nil { 567 t.Fatalf("Invalid serving address: %v", addr) 568 } 569 port, err := strconv.ParseUint(p, 10, 32) 570 if err != nil { 571 t.Fatalf("Invalid serving port %q: %v", p, err) 572 } 573 return host, uint32(port) 574 } 575 576 // Tests that LRS works correctly in a LOGICAL_DNS cluster. 577 func (s) TestLRSLogicalDNS(t *testing.T) { 578 // Create an xDS management server that serves ADS and LRS requests. 579 mgmtServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{SupportLoadReportingService: true}) 580 581 // Create bootstrap configuration pointing to the above management server. 582 nodeID := uuid.New().String() 583 bc := e2e.DefaultBootstrapContents(t, nodeID, mgmtServer.Address) 584 testutils.CreateBootstrapFileForTesting(t, bc) 585 586 // Create an xDS resolver with the above bootstrap configuration. 587 var resolverBuilder resolver.Builder 588 var err error 589 if newResolver := internal.NewXDSResolverWithConfigForTesting; newResolver != nil { 590 resolverBuilder, err = newResolver.(func([]byte) (resolver.Builder, error))(bc) 591 if err != nil { 592 t.Fatalf("Failed to create xDS resolver for testing: %v", err) 593 } 594 } 595 596 // Start a server backend exposing the test service. 597 server := stubserver.StartTestService(t, nil) 598 defer server.Stop() 599 host, port := hostAndPortFromAddress(t, server.Address) 600 601 // Configure the xDS management server with default resources. Override the 602 // default cluster to include an LRS server config pointing to self. 603 const serviceName = "my-test-xds-service" 604 resources := e2e.DefaultClientResources(e2e.ResourceParams{ 605 DialTarget: serviceName, 606 NodeID: nodeID, 607 Host: "localhost", 608 Port: testutils.ParsePort(t, server.Address), 609 SecLevel: e2e.SecurityLevelNone, 610 }) 611 resources.Clusters = []*v3clusterpb.Cluster{ 612 e2e.ClusterResourceWithOptions(e2e.ClusterOptions{ 613 ClusterName: "cluster-" + serviceName, 614 Type: e2e.ClusterTypeLogicalDNS, 615 DNSHostName: host, 616 DNSPort: port, 617 }), 618 } 619 resources.Clusters[0].LrsServer = &v3corepb.ConfigSource{ 620 ConfigSourceSpecifier: &v3corepb.ConfigSource_Self{ 621 Self: &v3corepb.SelfConfigSource{}, 622 }, 623 } 624 resources.Endpoints = nil 625 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 626 defer cancel() 627 if err := mgmtServer.Update(ctx, resources); err != nil { 628 t.Fatal(err) 629 } 630 631 // Create a ClientConn and make a successful RPC. 632 cc, err := grpc.NewClient(fmt.Sprintf("xds:///%s", serviceName), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(resolverBuilder)) 633 if err != nil { 634 t.Fatalf("failed to dial local test server: %v", err) 635 } 636 defer cc.Close() 637 638 client := testgrpc.NewTestServiceClient(cc) 639 if _, err := client.EmptyCall(ctx, &testpb.Empty{}); err != nil { 640 t.Fatalf("rpc EmptyCall() failed: %v", err) 641 } 642 643 // Ensure that an LRS stream is created. 644 if _, err := mgmtServer.LRSServer.LRSStreamOpenChan.Receive(ctx); err != nil { 645 t.Fatalf("Failure when waiting for an LRS stream to be opened: %v", err) 646 } 647 648 // Handle the initial LRS request from the xDS client. 649 if _, err = mgmtServer.LRSServer.LRSRequestChan.Receive(ctx); err != nil { 650 t.Fatalf("Failure waiting for initial LRS request: %v", err) 651 } 652 653 resp := fakeserver.Response{ 654 Resp: &v3lrspb.LoadStatsResponse{ 655 SendAllClusters: true, 656 LoadReportingInterval: durationpb.New(10 * time.Millisecond), 657 }, 658 } 659 mgmtServer.LRSServer.LRSResponseChan <- &resp 660 661 // Wait for load to be reported for locality of server 1. 662 if err := waitForSuccessfulLoadReport(ctx, mgmtServer.LRSServer, ""); err != nil { 663 t.Fatalf("Server did not receive load due to error: %v", err) 664 } 665 }