google.golang.org/grpc@v1.72.2/xds/internal/balancer/clusterresolver/e2e_test/eds_impl_test.go (about)

     1  /*
     2   * Copyright 2022 gRPC authors.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package e2e_test
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"fmt"
    23  	"strings"
    24  	"sync/atomic"
    25  	"testing"
    26  	"time"
    27  
    28  	"github.com/google/go-cmp/cmp"
    29  	"github.com/google/uuid"
    30  	"google.golang.org/grpc"
    31  	"google.golang.org/grpc/balancer"
    32  	"google.golang.org/grpc/balancer/roundrobin"
    33  	"google.golang.org/grpc/codes"
    34  	"google.golang.org/grpc/credentials/insecure"
    35  	"google.golang.org/grpc/internal"
    36  	"google.golang.org/grpc/internal/balancer/stub"
    37  	"google.golang.org/grpc/internal/envconfig"
    38  	"google.golang.org/grpc/internal/grpctest"
    39  	"google.golang.org/grpc/internal/stubserver"
    40  	"google.golang.org/grpc/internal/testutils"
    41  	rrutil "google.golang.org/grpc/internal/testutils/roundrobin"
    42  	"google.golang.org/grpc/internal/testutils/xds/e2e"
    43  	"google.golang.org/grpc/internal/xds/bootstrap"
    44  	"google.golang.org/grpc/peer"
    45  	"google.golang.org/grpc/resolver"
    46  	"google.golang.org/grpc/resolver/manual"
    47  	"google.golang.org/grpc/serviceconfig"
    48  	"google.golang.org/grpc/status"
    49  	"google.golang.org/grpc/xds/internal/xdsclient"
    50  	"google.golang.org/grpc/xds/internal/xdsclient/xdsresource/version"
    51  	"google.golang.org/protobuf/types/known/wrapperspb"
    52  
    53  	v3clusterpb "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
    54  	v3corepb "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
    55  	v3endpointpb "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3"
    56  	v3discoverypb "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3"
    57  	testgrpc "google.golang.org/grpc/interop/grpc_testing"
    58  	testpb "google.golang.org/grpc/interop/grpc_testing"
    59  
    60  	_ "google.golang.org/grpc/xds/internal/balancer/clusterresolver" // Register the "cluster_resolver_experimental" LB policy.
    61  	"google.golang.org/grpc/xds/internal/balancer/priority"
    62  )
    63  
    64  const (
    65  	clusterName    = "cluster-my-service-client-side-xds"
    66  	edsServiceName = "endpoints-my-service-client-side-xds"
    67  	localityName1  = "my-locality-1"
    68  	localityName2  = "my-locality-2"
    69  	localityName3  = "my-locality-3"
    70  
    71  	defaultTestTimeout            = 5 * time.Second
    72  	defaultTestShortTimeout       = 10 * time.Millisecond
    73  	defaultTestWatchExpiryTimeout = 500 * time.Millisecond
    74  )
    75  
    76  type s struct {
    77  	grpctest.Tester
    78  }
    79  
    80  func Test(t *testing.T) {
    81  	grpctest.RunSubTests(t, s{})
    82  }
    83  
    84  // backendAddressesAndPorts extracts the address and port of each of the
    85  // StubServers passed in and returns them. Fails the test if any of the
    86  // StubServers passed have an invalid address.
    87  func backendAddressesAndPorts(t *testing.T, servers []*stubserver.StubServer) ([]resolver.Address, []uint32) {
    88  	addrs := make([]resolver.Address, len(servers))
    89  	ports := make([]uint32, len(servers))
    90  	for i := 0; i < len(servers); i++ {
    91  		addrs[i] = resolver.Address{Addr: servers[i].Address}
    92  		ports[i] = testutils.ParsePort(t, servers[i].Address)
    93  	}
    94  	return addrs, ports
    95  }
    96  
    97  func startTestServiceBackends(t *testing.T, numBackends int) ([]*stubserver.StubServer, func()) {
    98  	var servers []*stubserver.StubServer
    99  	for i := 0; i < numBackends; i++ {
   100  		servers = append(servers, stubserver.StartTestService(t, nil))
   101  		servers[i].StartServer()
   102  	}
   103  
   104  	return servers, func() {
   105  		for _, server := range servers {
   106  			server.Stop()
   107  		}
   108  	}
   109  }
   110  
   111  // clientEndpointsResource returns an EDS resource for the specified nodeID,
   112  // service name and localities.
   113  func clientEndpointsResource(nodeID, edsServiceName string, localities []e2e.LocalityOptions) e2e.UpdateOptions {
   114  	return e2e.UpdateOptions{
   115  		NodeID: nodeID,
   116  		Endpoints: []*v3endpointpb.ClusterLoadAssignment{e2e.EndpointResourceWithOptions(e2e.EndpointOptions{
   117  			ClusterName: edsServiceName,
   118  			Host:        "localhost",
   119  			Localities:  localities,
   120  		})},
   121  		SkipValidation: true,
   122  	}
   123  }
   124  
   125  // TestEDS_OneLocality tests the cluster_resolver LB policy using an EDS
   126  // resource with one locality. The following scenarios are tested:
   127  //  1. Single backend. Test verifies that RPCs reach this backend.
   128  //  2. Add a backend. Test verifies that RPCs are roundrobined across the two
   129  //     backends.
   130  //  3. Remove one backend. Test verifies that all RPCs reach the other backend.
   131  //  4. Replace the backend. Test verifies that all RPCs reach the new backend.
   132  func (s) TestEDS_OneLocality(t *testing.T) {
   133  	// Spin up a management server to receive xDS resources from.
   134  	managementServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{})
   135  
   136  	// Create bootstrap configuration pointing to the above management server.
   137  	nodeID := uuid.New().String()
   138  	bootstrapContents := e2e.DefaultBootstrapContents(t, nodeID, managementServer.Address)
   139  
   140  	// Start backend servers which provide an implementation of the TestService.
   141  	servers, cleanup2 := startTestServiceBackends(t, 3)
   142  	defer cleanup2()
   143  	addrs, ports := backendAddressesAndPorts(t, servers)
   144  
   145  	// Create xDS resources for consumption by the test. We start off with a
   146  	// single backend in a single EDS locality.
   147  	resources := clientEndpointsResource(nodeID, edsServiceName, []e2e.LocalityOptions{{
   148  		Name:     localityName1,
   149  		Weight:   1,
   150  		Backends: []e2e.BackendOptions{{Ports: []uint32{ports[0]}}},
   151  	}})
   152  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   153  	defer cancel()
   154  	if err := managementServer.Update(ctx, resources); err != nil {
   155  		t.Fatal(err)
   156  	}
   157  
   158  	// Create an xDS client for use by the cluster_resolver LB policy.
   159  	config, err := bootstrap.NewConfigFromContents(bootstrapContents)
   160  	if err != nil {
   161  		t.Fatalf("Failed to parse bootstrap contents: %s, %v", string(bootstrapContents), err)
   162  	}
   163  	pool := xdsclient.NewPool(config)
   164  	client, close, err := pool.NewClientForTesting(xdsclient.OptionsForTesting{
   165  		Name: t.Name(),
   166  	})
   167  	if err != nil {
   168  		t.Fatalf("Failed to create xDS client: %v", err)
   169  	}
   170  	defer close()
   171  
   172  	// Create a manual resolver and push a service config specifying the use of
   173  	// the cluster_resolver LB policy with a single discovery mechanism.
   174  	r := manual.NewBuilderWithScheme("whatever")
   175  	jsonSC := fmt.Sprintf(`{
   176  			"loadBalancingConfig":[{
   177  				"cluster_resolver_experimental":{
   178  					"discoveryMechanisms": [{
   179  						"cluster": "%s",
   180  						"type": "EDS",
   181  						"edsServiceName": "%s",
   182  						"outlierDetection": {}
   183  					}],
   184  					"xdsLbPolicy":[{"round_robin":{}}]
   185  				}
   186  			}]
   187  		}`, clusterName, edsServiceName)
   188  	scpr := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(jsonSC)
   189  	r.InitialState(xdsclient.SetClient(resolver.State{ServiceConfig: scpr}, client))
   190  
   191  	// Create a ClientConn and make a successful RPC.
   192  	cc, err := grpc.NewClient(r.Scheme()+":///test.service", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
   193  	if err != nil {
   194  		t.Fatalf("failed to create new client for local test server: %v", err)
   195  	}
   196  	defer cc.Close()
   197  
   198  	// Ensure RPCs are being roundrobined across the single backend.
   199  	testClient := testgrpc.NewTestServiceClient(cc)
   200  	if err := rrutil.CheckRoundRobinRPCs(ctx, testClient, addrs[:1]); err != nil {
   201  		t.Fatal(err)
   202  	}
   203  
   204  	// Add a backend to the same locality, and ensure RPCs are sent in a
   205  	// roundrobin fashion across the two backends.
   206  	resources = clientEndpointsResource(nodeID, edsServiceName, []e2e.LocalityOptions{{
   207  		Name:     localityName1,
   208  		Weight:   1,
   209  		Backends: []e2e.BackendOptions{{Ports: []uint32{ports[0]}}, {Ports: []uint32{ports[1]}}},
   210  	}})
   211  	if err := managementServer.Update(ctx, resources); err != nil {
   212  		t.Fatal(err)
   213  	}
   214  	if err := rrutil.CheckRoundRobinRPCs(ctx, testClient, addrs[:2]); err != nil {
   215  		t.Fatal(err)
   216  	}
   217  
   218  	// Remove the first backend, and ensure all RPCs are sent to the second
   219  	// backend.
   220  	resources = clientEndpointsResource(nodeID, edsServiceName, []e2e.LocalityOptions{{
   221  		Name:     localityName1,
   222  		Weight:   1,
   223  		Backends: []e2e.BackendOptions{{Ports: []uint32{ports[1]}}},
   224  	}})
   225  	if err := managementServer.Update(ctx, resources); err != nil {
   226  		t.Fatal(err)
   227  	}
   228  	if err := rrutil.CheckRoundRobinRPCs(ctx, testClient, addrs[1:2]); err != nil {
   229  		t.Fatal(err)
   230  	}
   231  
   232  	// Replace the backend, and ensure all RPCs are sent to the new backend.
   233  	resources = clientEndpointsResource(nodeID, edsServiceName, []e2e.LocalityOptions{{
   234  		Name:     localityName1,
   235  		Weight:   1,
   236  		Backends: []e2e.BackendOptions{{Ports: []uint32{ports[2]}}},
   237  	}})
   238  	if err := managementServer.Update(ctx, resources); err != nil {
   239  		t.Fatal(err)
   240  	}
   241  	if err := rrutil.CheckRoundRobinRPCs(ctx, testClient, addrs[2:3]); err != nil {
   242  		t.Fatal(err)
   243  	}
   244  }
   245  
   246  // TestEDS_MultipleLocalities tests the cluster_resolver LB policy using an EDS
   247  // resource with multiple localities. The following scenarios are tested:
   248  //  1. Two localities, each with a single backend. Test verifies that RPCs are
   249  //     weighted roundrobined across these two backends.
   250  //  2. Add another locality, with a single backend. Test verifies that RPCs are
   251  //     weighted roundrobined across all the backends.
   252  //  3. Remove one locality. Test verifies that RPCs are weighted roundrobined
   253  //     across backends from the remaining localities.
   254  //  4. Add a backend to one locality. Test verifies that RPCs are weighted
   255  //     roundrobined across localities.
   256  //  5. Change the weight of one of the localities. Test verifies that RPCs are
   257  //     weighted roundrobined across the localities.
   258  //
   259  // In our LB policy tree, one of the descendents of the "cluster_resolver" LB
   260  // policy is the "weighted_target" LB policy which performs weighted roundrobin
   261  // across localities (and this has a randomness component associated with it).
   262  // Therefore, the moment we have backends from more than one locality, RPCs are
   263  // weighted roundrobined across them.
   264  func (s) TestEDS_MultipleLocalities(t *testing.T) {
   265  	// Spin up a management server to receive xDS resources from.
   266  	managementServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{})
   267  
   268  	// Create bootstrap configuration pointing to the above management server.
   269  	nodeID := uuid.New().String()
   270  	bootstrapContents := e2e.DefaultBootstrapContents(t, nodeID, managementServer.Address)
   271  
   272  	// Start backend servers which provide an implementation of the TestService.
   273  	servers, cleanup2 := startTestServiceBackends(t, 4)
   274  	defer cleanup2()
   275  	addrs, ports := backendAddressesAndPorts(t, servers)
   276  
   277  	// Create xDS resources for consumption by the test. We start off with two
   278  	// localities, and single backend in each of them.
   279  	resources := clientEndpointsResource(nodeID, edsServiceName, []e2e.LocalityOptions{
   280  		{
   281  			Name:     localityName1,
   282  			Weight:   1,
   283  			Backends: []e2e.BackendOptions{{Ports: []uint32{ports[0]}}},
   284  		},
   285  		{
   286  			Name:     localityName2,
   287  			Weight:   1,
   288  			Backends: []e2e.BackendOptions{{Ports: []uint32{ports[1]}}},
   289  		},
   290  	})
   291  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   292  	defer cancel()
   293  	if err := managementServer.Update(ctx, resources); err != nil {
   294  		t.Fatal(err)
   295  	}
   296  
   297  	// Create an xDS client for use by the cluster_resolver LB policy.
   298  	config, err := bootstrap.NewConfigFromContents(bootstrapContents)
   299  	if err != nil {
   300  		t.Fatalf("Failed to parse bootstrap contents: %s, %v", string(bootstrapContents), err)
   301  	}
   302  	pool := xdsclient.NewPool(config)
   303  	client, close, err := pool.NewClientForTesting(xdsclient.OptionsForTesting{
   304  		Name: t.Name(),
   305  	})
   306  	if err != nil {
   307  		t.Fatalf("Failed to create xDS client: %v", err)
   308  	}
   309  	defer close()
   310  
   311  	// Create a manual resolver and push service config specifying the use of
   312  	// the cluster_resolver LB policy with a single discovery mechanism.
   313  	r := manual.NewBuilderWithScheme("whatever")
   314  	jsonSC := fmt.Sprintf(`{
   315  			"loadBalancingConfig":[{
   316  				"cluster_resolver_experimental":{
   317  					"discoveryMechanisms": [{
   318  						"cluster": "%s",
   319  						"type": "EDS",
   320  						"edsServiceName": "%s",
   321  						"outlierDetection": {}
   322  					}],
   323  					"xdsLbPolicy":[{"round_robin":{}}]
   324  				}
   325  			}]
   326  		}`, clusterName, edsServiceName)
   327  	scpr := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(jsonSC)
   328  	r.InitialState(xdsclient.SetClient(resolver.State{ServiceConfig: scpr}, client))
   329  
   330  	// Create a ClientConn and make a successful RPC.
   331  	cc, err := grpc.NewClient(r.Scheme()+":///test.service", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
   332  	if err != nil {
   333  		t.Fatalf("failed to create new client for local test server: %v", err)
   334  	}
   335  	defer cc.Close()
   336  
   337  	// Ensure RPCs are being weighted roundrobined across the two backends.
   338  	testClient := testgrpc.NewTestServiceClient(cc)
   339  	if err := rrutil.CheckWeightedRoundRobinRPCs(ctx, testClient, addrs[0:2]); err != nil {
   340  		t.Fatal(err)
   341  	}
   342  
   343  	// Add another locality with a single backend, and ensure RPCs are being
   344  	// weighted roundrobined across the three backends.
   345  	resources = clientEndpointsResource(nodeID, edsServiceName, []e2e.LocalityOptions{
   346  		{
   347  			Name:     localityName1,
   348  			Weight:   1,
   349  			Backends: []e2e.BackendOptions{{Ports: []uint32{ports[0]}}},
   350  		},
   351  		{
   352  			Name:     localityName2,
   353  			Weight:   1,
   354  			Backends: []e2e.BackendOptions{{Ports: []uint32{ports[1]}}},
   355  		},
   356  		{
   357  			Name:     localityName3,
   358  			Weight:   1,
   359  			Backends: []e2e.BackendOptions{{Ports: []uint32{ports[2]}}},
   360  		},
   361  	})
   362  	if err := managementServer.Update(ctx, resources); err != nil {
   363  		t.Fatal(err)
   364  	}
   365  	if err := rrutil.CheckWeightedRoundRobinRPCs(ctx, testClient, addrs[0:3]); err != nil {
   366  		t.Fatal(err)
   367  	}
   368  
   369  	// Remove the first locality, and ensure RPCs are being weighted
   370  	// roundrobined across the remaining two backends.
   371  	resources = clientEndpointsResource(nodeID, edsServiceName, []e2e.LocalityOptions{
   372  		{
   373  			Name:     localityName2,
   374  			Weight:   1,
   375  			Backends: []e2e.BackendOptions{{Ports: []uint32{ports[1]}}},
   376  		},
   377  		{
   378  			Name:     localityName3,
   379  			Weight:   1,
   380  			Backends: []e2e.BackendOptions{{Ports: []uint32{ports[2]}}},
   381  		},
   382  	})
   383  	if err := managementServer.Update(ctx, resources); err != nil {
   384  		t.Fatal(err)
   385  	}
   386  	if err := rrutil.CheckWeightedRoundRobinRPCs(ctx, testClient, addrs[1:3]); err != nil {
   387  		t.Fatal(err)
   388  	}
   389  
   390  	// Add a backend to one locality, and ensure weighted roundrobin. Since RPCs
   391  	// are roundrobined across localities, locality2's backend will receive
   392  	// twice the traffic.
   393  	resources = clientEndpointsResource(nodeID, edsServiceName, []e2e.LocalityOptions{
   394  		{
   395  			Name:     localityName2,
   396  			Weight:   1,
   397  			Backends: []e2e.BackendOptions{{Ports: []uint32{ports[1]}}},
   398  		},
   399  		{
   400  			Name:     localityName3,
   401  			Weight:   1,
   402  			Backends: []e2e.BackendOptions{{Ports: []uint32{ports[2]}}, {Ports: []uint32{ports[3]}}},
   403  		},
   404  	})
   405  	if err := managementServer.Update(ctx, resources); err != nil {
   406  		t.Fatal(err)
   407  	}
   408  	wantAddrs := []resolver.Address{addrs[1], addrs[1], addrs[2], addrs[3]}
   409  	if err := rrutil.CheckWeightedRoundRobinRPCs(ctx, testClient, wantAddrs); err != nil {
   410  		t.Fatal(err)
   411  	}
   412  }
   413  
   414  // TestEDS_EndpointsHealth tests the cluster_resolver LB policy using an EDS
   415  // resource which specifies endpoint health information and verifies that
   416  // traffic is routed only to backends deemed capable of receiving traffic.
   417  func (s) TestEDS_EndpointsHealth(t *testing.T) {
   418  	// Spin up a management server to receive xDS resources from.
   419  	managementServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{})
   420  
   421  	// Create bootstrap configuration pointing to the above management server.
   422  	nodeID := uuid.New().String()
   423  	bootstrapContents := e2e.DefaultBootstrapContents(t, nodeID, managementServer.Address)
   424  
   425  	// Start backend servers which provide an implementation of the TestService.
   426  	servers, cleanup2 := startTestServiceBackends(t, 12)
   427  	defer cleanup2()
   428  	addrs, ports := backendAddressesAndPorts(t, servers)
   429  
   430  	// Create xDS resources for consumption by the test.  Two localities with
   431  	// six backends each, with two of the six backends being healthy. Both
   432  	// UNKNOWN and HEALTHY are considered by gRPC for load balancing.
   433  	resources := clientEndpointsResource(nodeID, edsServiceName, []e2e.LocalityOptions{
   434  		{
   435  			Name:   localityName1,
   436  			Weight: 1,
   437  			Backends: []e2e.BackendOptions{
   438  				{Ports: []uint32{ports[0]}, HealthStatus: v3corepb.HealthStatus_UNKNOWN},
   439  				{Ports: []uint32{ports[1]}, HealthStatus: v3corepb.HealthStatus_HEALTHY},
   440  				{Ports: []uint32{ports[2]}, HealthStatus: v3corepb.HealthStatus_UNHEALTHY},
   441  				{Ports: []uint32{ports[3]}, HealthStatus: v3corepb.HealthStatus_DRAINING},
   442  				{Ports: []uint32{ports[4]}, HealthStatus: v3corepb.HealthStatus_TIMEOUT},
   443  				{Ports: []uint32{ports[5]}, HealthStatus: v3corepb.HealthStatus_DEGRADED},
   444  			},
   445  		},
   446  		{
   447  			Name:   localityName2,
   448  			Weight: 1,
   449  			Backends: []e2e.BackendOptions{
   450  				{Ports: []uint32{ports[6]}, HealthStatus: v3corepb.HealthStatus_UNKNOWN},
   451  				{Ports: []uint32{ports[7]}, HealthStatus: v3corepb.HealthStatus_HEALTHY},
   452  				{Ports: []uint32{ports[8]}, HealthStatus: v3corepb.HealthStatus_UNHEALTHY},
   453  				{Ports: []uint32{ports[9]}, HealthStatus: v3corepb.HealthStatus_DRAINING},
   454  				{Ports: []uint32{ports[10]}, HealthStatus: v3corepb.HealthStatus_TIMEOUT},
   455  				{Ports: []uint32{ports[11]}, HealthStatus: v3corepb.HealthStatus_DEGRADED},
   456  			},
   457  		},
   458  	})
   459  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   460  	defer cancel()
   461  	if err := managementServer.Update(ctx, resources); err != nil {
   462  		t.Fatal(err)
   463  	}
   464  
   465  	// Create an xDS client for use by the cluster_resolver LB policy.
   466  	config, err := bootstrap.NewConfigFromContents(bootstrapContents)
   467  	if err != nil {
   468  		t.Fatalf("Failed to parse bootstrap contents: %s, %v", string(bootstrapContents), err)
   469  	}
   470  	pool := xdsclient.NewPool(config)
   471  	client, close, err := pool.NewClientForTesting(xdsclient.OptionsForTesting{
   472  		Name: t.Name(),
   473  	})
   474  	if err != nil {
   475  		t.Fatalf("Failed to create xDS client: %v", err)
   476  	}
   477  	defer close()
   478  
   479  	// Create a manual resolver and push service config specifying the use of
   480  	// the cluster_resolver LB policy with a single discovery mechanism.
   481  	r := manual.NewBuilderWithScheme("whatever")
   482  	jsonSC := fmt.Sprintf(`{
   483  			"loadBalancingConfig":[{
   484  				"cluster_resolver_experimental":{
   485  					"discoveryMechanisms": [{
   486  						"cluster": "%s",
   487  						"type": "EDS",
   488  						"edsServiceName": "%s",
   489  						"outlierDetection": {}
   490  					}],
   491  					"xdsLbPolicy":[{"round_robin":{}}]
   492  				}
   493  			}]
   494  		}`, clusterName, edsServiceName)
   495  	scpr := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(jsonSC)
   496  	r.InitialState(xdsclient.SetClient(resolver.State{ServiceConfig: scpr}, client))
   497  
   498  	// Create a ClientConn and make a successful RPC.
   499  	cc, err := grpc.NewClient(r.Scheme()+":///test.service", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
   500  	if err != nil {
   501  		t.Fatalf("failed to create new client for local test server: %v", err)
   502  	}
   503  	defer cc.Close()
   504  
   505  	// Ensure RPCs are being weighted roundrobined across healthy backends from
   506  	// both localities.
   507  	testClient := testgrpc.NewTestServiceClient(cc)
   508  	if err := rrutil.CheckWeightedRoundRobinRPCs(ctx, testClient, append(addrs[0:2], addrs[6:8]...)); err != nil {
   509  		t.Fatal(err)
   510  	}
   511  }
   512  
   513  // TestEDS_EmptyUpdate tests the cluster_resolver LB policy using an EDS
   514  // resource with no localities and verifies that RPCs fail with "all priorities
   515  // removed" error.
   516  func (s) TestEDS_EmptyUpdate(t *testing.T) {
   517  	// Spin up a management server to receive xDS resources from.
   518  	managementServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{})
   519  
   520  	// Create bootstrap configuration pointing to the above management server.
   521  	nodeID := uuid.New().String()
   522  	bootstrapContents := e2e.DefaultBootstrapContents(t, nodeID, managementServer.Address)
   523  
   524  	// Start backend servers which provide an implementation of the TestService.
   525  	servers, cleanup2 := startTestServiceBackends(t, 4)
   526  	defer cleanup2()
   527  	addrs, ports := backendAddressesAndPorts(t, servers)
   528  
   529  	oldCacheTimeout := priority.DefaultSubBalancerCloseTimeout
   530  	priority.DefaultSubBalancerCloseTimeout = 100 * time.Microsecond
   531  	defer func() { priority.DefaultSubBalancerCloseTimeout = oldCacheTimeout }()
   532  
   533  	// Create xDS resources for consumption by the test. The first update is an
   534  	// empty update. This should put the channel in TRANSIENT_FAILURE.
   535  	resources := clientEndpointsResource(nodeID, edsServiceName, nil)
   536  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   537  	defer cancel()
   538  	if err := managementServer.Update(ctx, resources); err != nil {
   539  		t.Fatal(err)
   540  	}
   541  
   542  	// Create an xDS client for use by the cluster_resolver LB policy.
   543  	config, err := bootstrap.NewConfigFromContents(bootstrapContents)
   544  	if err != nil {
   545  		t.Fatalf("Failed to parse bootstrap contents: %s, %v", string(bootstrapContents), err)
   546  	}
   547  	pool := xdsclient.NewPool(config)
   548  	client, close, err := pool.NewClientForTesting(xdsclient.OptionsForTesting{
   549  		Name: t.Name(),
   550  	})
   551  	if err != nil {
   552  		t.Fatalf("Failed to create xDS client: %v", err)
   553  	}
   554  	defer close()
   555  
   556  	// Create a manual resolver and push service config specifying the use of
   557  	// the cluster_resolver LB policy with a single discovery mechanism.
   558  	r := manual.NewBuilderWithScheme("whatever")
   559  	jsonSC := fmt.Sprintf(`{
   560  			"loadBalancingConfig":[{
   561  				"cluster_resolver_experimental":{
   562  					"discoveryMechanisms": [{
   563  						"cluster": "%s",
   564  						"type": "EDS",
   565  						"edsServiceName": "%s",
   566  						"outlierDetection": {}
   567  					}],
   568  					"xdsLbPolicy":[{"round_robin":{}}]
   569  				}
   570  			}]
   571  		}`, clusterName, edsServiceName)
   572  	scpr := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(jsonSC)
   573  	r.InitialState(xdsclient.SetClient(resolver.State{ServiceConfig: scpr}, client))
   574  
   575  	// Create a ClientConn and ensure that RPCs fail with "all priorities
   576  	// removed" error. This is the expected error when the cluster_resolver LB
   577  	// policy receives an EDS update with no localities.
   578  	cc, err := grpc.NewClient(r.Scheme()+":///test.service", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
   579  	if err != nil {
   580  		t.Fatalf("failed to create new client for local test server: %v", err)
   581  	}
   582  	defer cc.Close()
   583  	testClient := testgrpc.NewTestServiceClient(cc)
   584  	if err := waitForProducedZeroAddressesError(ctx, t, testClient); err != nil {
   585  		t.Fatal(err)
   586  	}
   587  
   588  	// Add a locality with one backend and ensure RPCs are successful.
   589  	resources = clientEndpointsResource(nodeID, edsServiceName, []e2e.LocalityOptions{{
   590  		Name:     localityName1,
   591  		Weight:   1,
   592  		Backends: []e2e.BackendOptions{{Ports: []uint32{ports[0]}}},
   593  	}})
   594  	if err := managementServer.Update(ctx, resources); err != nil {
   595  		t.Fatal(err)
   596  	}
   597  	if err := rrutil.CheckRoundRobinRPCs(ctx, testClient, addrs[:1]); err != nil {
   598  		t.Fatal(err)
   599  	}
   600  
   601  	// Push another empty update and ensure that RPCs fail with "all priorities
   602  	// removed" error again.
   603  	resources = clientEndpointsResource(nodeID, edsServiceName, nil)
   604  	if err := managementServer.Update(ctx, resources); err != nil {
   605  		t.Fatal(err)
   606  	}
   607  	if err := waitForProducedZeroAddressesError(ctx, t, testClient); err != nil {
   608  		t.Fatal(err)
   609  	}
   610  }
   611  
   612  // TestEDS_ResourceRemoved tests the case where the EDS resource requested by
   613  // the clusterresolver LB policy is removed from the management server. The test
   614  // verifies that the EDS watch is not canceled and that RPCs continue to succeed
   615  // with the previously received configuration.
   616  func (s) TestEDS_ResourceRemoved(t *testing.T) {
   617  	// Start an xDS management server that uses a couple of channels to
   618  	// notify the test about the following events:
   619  	// - an EDS requested with the expected resource name is requested
   620  	// - EDS resource is unrequested, i.e, an EDS request with no resource name
   621  	//   is received, which indicates that we are no longer interested in that
   622  	//   resource.
   623  	edsResourceRequestedCh := make(chan struct{}, 1)
   624  	edsResourceCanceledCh := make(chan struct{}, 1)
   625  	managementServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{
   626  		OnStreamRequest: func(_ int64, req *v3discoverypb.DiscoveryRequest) error {
   627  			if req.GetTypeUrl() == version.V3EndpointsURL {
   628  				switch len(req.GetResourceNames()) {
   629  				case 0:
   630  					select {
   631  					case edsResourceCanceledCh <- struct{}{}:
   632  					default:
   633  					}
   634  				case 1:
   635  					if req.GetResourceNames()[0] == edsServiceName {
   636  						select {
   637  						case edsResourceRequestedCh <- struct{}{}:
   638  						default:
   639  						}
   640  					}
   641  				default:
   642  					t.Errorf("Unexpected number of resources, %d, in an EDS request", len(req.GetResourceNames()))
   643  				}
   644  			}
   645  			return nil
   646  		},
   647  	})
   648  
   649  	// Create bootstrap configuration pointing to the above management server.
   650  	nodeID := uuid.New().String()
   651  	bootstrapContents := e2e.DefaultBootstrapContents(t, nodeID, managementServer.Address)
   652  
   653  	server := stubserver.StartTestService(t, nil)
   654  	defer server.Stop()
   655  
   656  	// Configure cluster and endpoints resources in the management server.
   657  	resources := e2e.UpdateOptions{
   658  		NodeID:         nodeID,
   659  		Clusters:       []*v3clusterpb.Cluster{e2e.DefaultCluster(clusterName, edsServiceName, e2e.SecurityLevelNone)},
   660  		Endpoints:      []*v3endpointpb.ClusterLoadAssignment{e2e.DefaultEndpoint(edsServiceName, "localhost", []uint32{testutils.ParsePort(t, server.Address)})},
   661  		SkipValidation: true,
   662  	}
   663  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   664  	defer cancel()
   665  	if err := managementServer.Update(ctx, resources); err != nil {
   666  		t.Fatal(err)
   667  	}
   668  
   669  	// Create xDS client, configure cds_experimental LB policy with a manual
   670  	// resolver, and dial the test backends.
   671  	cc, cleanup := setupAndDial(t, bootstrapContents)
   672  	defer cleanup()
   673  
   674  	client := testgrpc.NewTestServiceClient(cc)
   675  	if _, err := client.EmptyCall(ctx, &testpb.Empty{}); err != nil {
   676  		t.Fatalf("EmptyCall() failed: %v", err)
   677  	}
   678  
   679  	// Delete the endpoints resource from the management server.
   680  	resources.Endpoints = nil
   681  	if err := managementServer.Update(ctx, resources); err != nil {
   682  		t.Fatal(err)
   683  	}
   684  
   685  	// Ensure that RPCs continue to succeed for the next second, and that the
   686  	// EDS watch is not canceled.
   687  	for end := time.Now().Add(time.Second); time.Now().Before(end); <-time.After(defaultTestShortTimeout) {
   688  		if _, err := client.EmptyCall(ctx, &testpb.Empty{}); err != nil {
   689  			t.Fatalf("EmptyCall() failed: %v", err)
   690  		}
   691  		select {
   692  		case <-edsResourceCanceledCh:
   693  			t.Fatal("EDS watch canceled when not expected to be canceled")
   694  		default:
   695  		}
   696  	}
   697  }
   698  
   699  // TestEDS_ClusterResourceDoesNotContainEDSServiceName tests the case where the
   700  // Cluster resource sent by the management server does not contain an EDS
   701  // service name. The test verifies that the cluster_resolver LB policy uses the
   702  // cluster name for the EDS resource.
   703  func (s) TestEDS_ClusterResourceDoesNotContainEDSServiceName(t *testing.T) {
   704  	edsResourceCh := make(chan string, 1)
   705  	managementServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{
   706  		OnStreamRequest: func(_ int64, req *v3discoverypb.DiscoveryRequest) error {
   707  			if req.GetTypeUrl() != version.V3EndpointsURL {
   708  				return nil
   709  			}
   710  			if len(req.GetResourceNames()) > 0 {
   711  				select {
   712  				case edsResourceCh <- req.GetResourceNames()[0]:
   713  				default:
   714  				}
   715  			}
   716  			return nil
   717  		},
   718  	})
   719  
   720  	// Create bootstrap configuration pointing to the above management server.
   721  	nodeID := uuid.New().String()
   722  	bootstrapContents := e2e.DefaultBootstrapContents(t, nodeID, managementServer.Address)
   723  
   724  	server := stubserver.StartTestService(t, nil)
   725  	defer server.Stop()
   726  
   727  	// Configure cluster and endpoints resources with the same name in the management server. The cluster resource does not specify an EDS service name.
   728  	resources := e2e.UpdateOptions{
   729  		NodeID:         nodeID,
   730  		Clusters:       []*v3clusterpb.Cluster{e2e.DefaultCluster(clusterName, "", e2e.SecurityLevelNone)},
   731  		Endpoints:      []*v3endpointpb.ClusterLoadAssignment{e2e.DefaultEndpoint(clusterName, "localhost", []uint32{testutils.ParsePort(t, server.Address)})},
   732  		SkipValidation: true,
   733  	}
   734  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   735  	defer cancel()
   736  	if err := managementServer.Update(ctx, resources); err != nil {
   737  		t.Fatal(err)
   738  	}
   739  
   740  	// Create xDS client, configure cds_experimental LB policy with a manual
   741  	// resolver, and dial the test backends.
   742  	cc, cleanup := setupAndDial(t, bootstrapContents)
   743  	defer cleanup()
   744  
   745  	client := testgrpc.NewTestServiceClient(cc)
   746  	if _, err := client.EmptyCall(ctx, &testpb.Empty{}); err != nil {
   747  		t.Fatalf("EmptyCall() failed: %v", err)
   748  	}
   749  
   750  	select {
   751  	case <-ctx.Done():
   752  		t.Fatal("Timeout when waiting for EDS request to be received on the management server")
   753  	case name := <-edsResourceCh:
   754  		if name != clusterName {
   755  			t.Fatalf("Received EDS request with resource name %q, want %q", name, clusterName)
   756  		}
   757  	}
   758  }
   759  
   760  // TestEDS_ClusterResourceUpdates verifies different scenarios with regards to
   761  // cluster resource updates.
   762  //
   763  //   - The first cluster resource contains an eds_service_name. The test verifies
   764  //     that an EDS request is sent for the received eds_service_name. It also
   765  //     verifies that a subsequent RPC gets routed to a backend belonging to that
   766  //     service name.
   767  //   - The next cluster resource update contains no eds_service_name. The test
   768  //     verifies that a subsequent EDS request is sent for the cluster_name and
   769  //     that the previously received eds_service_name is no longer requested. It
   770  //     also verifies that a subsequent RPC gets routed to a backend belonging to
   771  //     the service represented by the cluster_name.
   772  //   - The next cluster resource update changes the circuit breaking
   773  //     configuration, but does not change the service name. The test verifies
   774  //     that a subsequent RPC gets routed to the same backend as before.
   775  func (s) TestEDS_ClusterResourceUpdates(t *testing.T) {
   776  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   777  	defer cancel()
   778  
   779  	// Start an xDS management server that pushes the EDS resource names onto a
   780  	// channel.
   781  	edsResourceNameCh := make(chan []string, 1)
   782  	managementServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{
   783  		OnStreamRequest: func(_ int64, req *v3discoverypb.DiscoveryRequest) error {
   784  			if req.GetTypeUrl() != version.V3EndpointsURL {
   785  				return nil
   786  			}
   787  			if len(req.GetResourceNames()) == 0 {
   788  				// This is the case for ACKs. Do nothing here.
   789  				return nil
   790  			}
   791  			select {
   792  			case <-ctx.Done():
   793  			case edsResourceNameCh <- req.GetResourceNames():
   794  			}
   795  			return nil
   796  		},
   797  		AllowResourceSubset: true,
   798  	})
   799  
   800  	// Create bootstrap configuration pointing to the above management server.
   801  	nodeID := uuid.New().String()
   802  	bootstrapContents := e2e.DefaultBootstrapContents(t, nodeID, managementServer.Address)
   803  
   804  	// Start two test backends and extract their host and port. The first
   805  	// backend is used for the EDS resource identified by the eds_service_name,
   806  	// and the second backend is used for the EDS resource identified by the
   807  	// cluster_name.
   808  	servers, cleanup2 := startTestServiceBackends(t, 2)
   809  	defer cleanup2()
   810  	addrs, ports := backendAddressesAndPorts(t, servers)
   811  
   812  	// Configure cluster and endpoints resources in the management server.
   813  	resources := e2e.UpdateOptions{
   814  		NodeID:   nodeID,
   815  		Clusters: []*v3clusterpb.Cluster{e2e.DefaultCluster(clusterName, edsServiceName, e2e.SecurityLevelNone)},
   816  		Endpoints: []*v3endpointpb.ClusterLoadAssignment{
   817  			e2e.DefaultEndpoint(edsServiceName, "localhost", []uint32{uint32(ports[0])}),
   818  			e2e.DefaultEndpoint(clusterName, "localhost", []uint32{uint32(ports[1])}),
   819  		},
   820  		SkipValidation: true,
   821  	}
   822  	if err := managementServer.Update(ctx, resources); err != nil {
   823  		t.Fatal(err)
   824  	}
   825  
   826  	// Create xDS client, configure cds_experimental LB policy with a manual
   827  	// resolver, and dial the test backends.
   828  	cc, cleanup := setupAndDial(t, bootstrapContents)
   829  	defer cleanup()
   830  
   831  	client := testgrpc.NewTestServiceClient(cc)
   832  	peer := &peer.Peer{}
   833  	if _, err := client.EmptyCall(ctx, &testpb.Empty{}, grpc.Peer(peer)); err != nil {
   834  		t.Fatalf("EmptyCall() failed: %v", err)
   835  	}
   836  	if peer.Addr.String() != addrs[0].Addr {
   837  		t.Fatalf("EmptyCall() routed to backend %q, want %q", peer.Addr, addrs[0].Addr)
   838  	}
   839  
   840  	// Ensure EDS watch is registered for eds_service_name.
   841  	select {
   842  	case <-ctx.Done():
   843  		t.Fatal("Timeout when waiting for EDS request to be received on the management server")
   844  	case names := <-edsResourceNameCh:
   845  		if !cmp.Equal(names, []string{edsServiceName}) {
   846  			t.Fatalf("Received EDS request with resource names %v, want %v", names, []string{edsServiceName})
   847  		}
   848  	}
   849  
   850  	// Change the cluster resource to not contain an eds_service_name.
   851  	resources.Clusters = []*v3clusterpb.Cluster{e2e.DefaultCluster(clusterName, "", e2e.SecurityLevelNone)}
   852  	if err := managementServer.Update(ctx, resources); err != nil {
   853  		t.Fatal(err)
   854  	}
   855  
   856  	// Ensure that an EDS watch for eds_service_name is canceled and new watch
   857  	// for cluster_name is registered. The actual order in which this happens is
   858  	// not deterministic, i.e the watch for old resource could be canceled
   859  	// before the new one is registered or vice-versa. In either case,
   860  	// eventually, we want to see a request to the management server for just
   861  	// the cluster_name.
   862  	for ; ctx.Err() == nil; <-time.After(defaultTestShortTimeout) {
   863  		names := <-edsResourceNameCh
   864  		if cmp.Equal(names, []string{clusterName}) {
   865  			break
   866  		}
   867  	}
   868  	if ctx.Err() != nil {
   869  		t.Fatalf("Timeout when waiting for old EDS watch %q to be canceled and new one %q to be registered", edsServiceName, clusterName)
   870  	}
   871  
   872  	// Make an RPC, and ensure that it gets routed to second backend,
   873  	// corresponding to the cluster_name.
   874  	for ; ctx.Err() == nil; <-time.After(defaultTestShortTimeout) {
   875  		if _, err := client.EmptyCall(ctx, &testpb.Empty{}, grpc.Peer(peer)); err != nil {
   876  			continue
   877  		}
   878  		if peer.Addr.String() == addrs[1].Addr {
   879  			break
   880  		}
   881  	}
   882  	if ctx.Err() != nil {
   883  		t.Fatalf("Timeout when waiting for EmptyCall() to be routed to correct backend %q", addrs[1].Addr)
   884  	}
   885  
   886  	// Change cluster resource circuit breaking count.
   887  	resources.Clusters[0].CircuitBreakers = &v3clusterpb.CircuitBreakers{
   888  		Thresholds: []*v3clusterpb.CircuitBreakers_Thresholds{
   889  			{
   890  				Priority:    v3corepb.RoutingPriority_DEFAULT,
   891  				MaxRequests: wrapperspb.UInt32(512),
   892  			},
   893  		},
   894  	}
   895  	if err := managementServer.Update(ctx, resources); err != nil {
   896  		t.Fatal(err)
   897  	}
   898  
   899  	// Ensure that RPCs continue to get routed to the second backend for the
   900  	// next second.
   901  	for end := time.Now().Add(time.Second); time.Now().Before(end); <-time.After(defaultTestShortTimeout) {
   902  		if _, err := client.EmptyCall(ctx, &testpb.Empty{}, grpc.Peer(peer)); err != nil {
   903  			t.Fatalf("EmptyCall() failed: %v", err)
   904  		}
   905  		if peer.Addr.String() != addrs[1].Addr {
   906  			t.Fatalf("EmptyCall() routed to backend %q, want %q", peer.Addr, addrs[1].Addr)
   907  		}
   908  	}
   909  }
   910  
   911  // TestEDS_BadUpdateWithoutPreviousGoodUpdate tests the case where the
   912  // management server sends a bad update (one that is NACKed by the xDS client).
   913  // Since the cluster_resolver LB policy does not have a previously received good
   914  // update, it is expected to treat this bad update as though it received an
   915  // update with no endpoints. Hence RPCs are expected to fail with "all
   916  // priorities removed" error.
   917  func (s) TestEDS_BadUpdateWithoutPreviousGoodUpdate(t *testing.T) {
   918  	// Spin up a management server to receive xDS resources from.
   919  	managementServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{})
   920  
   921  	// Create bootstrap configuration pointing to the above management server.
   922  	nodeID := uuid.New().String()
   923  	bootstrapContents := e2e.DefaultBootstrapContents(t, nodeID, managementServer.Address)
   924  
   925  	// Start a backend server that implements the TestService.
   926  	server := stubserver.StartTestService(t, nil)
   927  	defer server.Stop()
   928  
   929  	// Create an EDS resource with a load balancing weight of 0. This will
   930  	// result in the resource being NACKed by the xDS client. Since the
   931  	// cluster_resolver LB policy does not have a previously received good EDS
   932  	// update, it should treat this update as an empty EDS update.
   933  	resources := clientEndpointsResource(nodeID, edsServiceName, []e2e.LocalityOptions{{
   934  		Name:     localityName1,
   935  		Weight:   1,
   936  		Backends: []e2e.BackendOptions{{Ports: []uint32{testutils.ParsePort(t, server.Address)}}},
   937  	}})
   938  	resources.Endpoints[0].Endpoints[0].LbEndpoints[0].LoadBalancingWeight = &wrapperspb.UInt32Value{Value: 0}
   939  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   940  	defer cancel()
   941  	if err := managementServer.Update(ctx, resources); err != nil {
   942  		t.Fatal(err)
   943  	}
   944  
   945  	// Create an xDS client for use by the cluster_resolver LB policy.
   946  	config, err := bootstrap.NewConfigFromContents(bootstrapContents)
   947  	if err != nil {
   948  		t.Fatalf("Failed to parse bootstrap contents: %s, %v", string(bootstrapContents), err)
   949  	}
   950  	pool := xdsclient.NewPool(config)
   951  	xdsClient, close, err := pool.NewClientForTesting(xdsclient.OptionsForTesting{
   952  		Name: t.Name(),
   953  	})
   954  	if err != nil {
   955  		t.Fatalf("Failed to create xDS client: %v", err)
   956  	}
   957  	defer close()
   958  
   959  	// Create a manual resolver and push a service config specifying the use of
   960  	// the cluster_resolver LB policy with a single discovery mechanism.
   961  	r := manual.NewBuilderWithScheme("whatever")
   962  	jsonSC := fmt.Sprintf(`{
   963  			"loadBalancingConfig":[{
   964  				"cluster_resolver_experimental":{
   965  					"discoveryMechanisms": [{
   966  						"cluster": "%s",
   967  						"type": "EDS",
   968  						"edsServiceName": "%s",
   969  						"outlierDetection": {}
   970  					}],
   971  					"xdsLbPolicy":[{"round_robin":{}}]
   972  				}
   973  			}]
   974  		}`, clusterName, edsServiceName)
   975  	scpr := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(jsonSC)
   976  	r.InitialState(xdsclient.SetClient(resolver.State{ServiceConfig: scpr}, xdsClient))
   977  
   978  	// Create a ClientConn and verify that RPCs fail with "all priorities
   979  	// removed" error.
   980  	cc, err := grpc.NewClient(r.Scheme()+":///test.service", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
   981  	if err != nil {
   982  		t.Fatalf("failed to create new client for local test server: %v", err)
   983  	}
   984  	defer cc.Close()
   985  	client := testgrpc.NewTestServiceClient(cc)
   986  	if err := waitForProducedZeroAddressesError(ctx, t, client); err != nil {
   987  		t.Fatal(err)
   988  	}
   989  }
   990  
   991  // TestEDS_BadUpdateWithPreviousGoodUpdate tests the case where the
   992  // cluster_resolver LB policy receives a good EDS update from the management
   993  // server and the test verifies that RPCs are successful. Then, a bad update is
   994  // received from the management server (one that is NACKed by the xDS client).
   995  // The test verifies that the previously received good update is still being
   996  // used and that RPCs are still successful.
   997  func (s) TestEDS_BadUpdateWithPreviousGoodUpdate(t *testing.T) {
   998  	// Spin up a management server to receive xDS resources from.
   999  	managementServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{})
  1000  
  1001  	// Create bootstrap configuration pointing to the above management server.
  1002  	nodeID := uuid.New().String()
  1003  	bootstrapContents := e2e.DefaultBootstrapContents(t, nodeID, managementServer.Address)
  1004  
  1005  	// Start a backend server that implements the TestService.
  1006  	server := stubserver.StartTestService(t, nil)
  1007  	defer server.Stop()
  1008  
  1009  	// Create an EDS resource for consumption by the test.
  1010  	resources := clientEndpointsResource(nodeID, edsServiceName, []e2e.LocalityOptions{{
  1011  		Name:     localityName1,
  1012  		Weight:   1,
  1013  		Backends: []e2e.BackendOptions{{Ports: []uint32{testutils.ParsePort(t, server.Address)}}},
  1014  	}})
  1015  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
  1016  	defer cancel()
  1017  	if err := managementServer.Update(ctx, resources); err != nil {
  1018  		t.Fatal(err)
  1019  	}
  1020  
  1021  	// Create an xDS client for use by the cluster_resolver LB policy.
  1022  	config, err := bootstrap.NewConfigFromContents(bootstrapContents)
  1023  	if err != nil {
  1024  		t.Fatalf("Failed to parse bootstrap contents: %s, %v", string(bootstrapContents), err)
  1025  	}
  1026  	pool := xdsclient.NewPool(config)
  1027  	xdsClient, close, err := pool.NewClientForTesting(xdsclient.OptionsForTesting{
  1028  		Name: t.Name(),
  1029  	})
  1030  	if err != nil {
  1031  		t.Fatalf("Failed to create xDS client: %v", err)
  1032  	}
  1033  	defer close()
  1034  
  1035  	// Create a manual resolver and push a service config specifying the use of
  1036  	// the cluster_resolver LB policy with a single discovery mechanism.
  1037  	r := manual.NewBuilderWithScheme("whatever")
  1038  	jsonSC := fmt.Sprintf(`{
  1039  			"loadBalancingConfig":[{
  1040  				"cluster_resolver_experimental":{
  1041  					"discoveryMechanisms": [{
  1042  						"cluster": "%s",
  1043  						"type": "EDS",
  1044  						"edsServiceName": "%s",
  1045  						"outlierDetection": {}
  1046  					}],
  1047  					"xdsLbPolicy":[{"round_robin":{}}]
  1048  				}
  1049  			}]
  1050  		}`, clusterName, edsServiceName)
  1051  	scpr := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(jsonSC)
  1052  	r.InitialState(xdsclient.SetClient(resolver.State{ServiceConfig: scpr}, xdsClient))
  1053  
  1054  	// Create a ClientConn and make a successful RPC.
  1055  	cc, err := grpc.NewClient(r.Scheme()+":///test.service", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
  1056  	if err != nil {
  1057  		t.Fatalf("failed to create new client for local test server: %v", err)
  1058  	}
  1059  	defer cc.Close()
  1060  
  1061  	// Ensure RPCs are being roundrobined across the single backend.
  1062  	client := testgrpc.NewTestServiceClient(cc)
  1063  	if err := rrutil.CheckRoundRobinRPCs(ctx, client, []resolver.Address{{Addr: server.Address}}); err != nil {
  1064  		t.Fatal(err)
  1065  	}
  1066  
  1067  	// Update the endpoints resource in the management server with a load
  1068  	// balancing weight of 0. This will result in the resource being NACKed by
  1069  	// the xDS client. But since the cluster_resolver LB policy has a previously
  1070  	// received good EDS update, it should continue using it.
  1071  	resources.Endpoints[0].Endpoints[0].LbEndpoints[0].LoadBalancingWeight = &wrapperspb.UInt32Value{Value: 0}
  1072  	if err := managementServer.Update(ctx, resources); err != nil {
  1073  		t.Fatal(err)
  1074  	}
  1075  
  1076  	// Ensure that RPCs continue to succeed for the next second.
  1077  	for end := time.Now().Add(time.Second); time.Now().Before(end); <-time.After(defaultTestShortTimeout) {
  1078  		if err := rrutil.CheckRoundRobinRPCs(ctx, client, []resolver.Address{{Addr: server.Address}}); err != nil {
  1079  			t.Fatal(err)
  1080  		}
  1081  	}
  1082  }
  1083  
  1084  // TestEDS_ResourceNotFound tests the case where the requested EDS resource does
  1085  // not exist on the management server. Once the watch timer associated with the
  1086  // requested resource expires, the cluster_resolver LB policy receives a
  1087  // "resource-not-found" callback from the xDS client and is expected to treat it
  1088  // as though it received an update with no endpoints. Hence RPCs are expected to
  1089  // fail with "all priorities removed" error.
  1090  func (s) TestEDS_ResourceNotFound(t *testing.T) {
  1091  	// Spin up a management server to receive xDS resources from.
  1092  	mgmtServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{})
  1093  
  1094  	// Create an xDS client talking to the above management server, configured
  1095  	// with a short watch expiry timeout.
  1096  	nodeID := uuid.New().String()
  1097  	bc := e2e.DefaultBootstrapContents(t, nodeID, mgmtServer.Address)
  1098  	config, err := bootstrap.NewConfigFromContents(bc)
  1099  	if err != nil {
  1100  		t.Fatalf("Failed to parse bootstrap contents: %s, %v", string(bc), err)
  1101  	}
  1102  	pool := xdsclient.NewPool(config)
  1103  	xdsClient, close, err := pool.NewClientForTesting(xdsclient.OptionsForTesting{
  1104  		Name:               t.Name(),
  1105  		WatchExpiryTimeout: defaultTestWatchExpiryTimeout,
  1106  	})
  1107  	if err != nil {
  1108  		t.Fatalf("Failed to create an xDS client: %v", err)
  1109  	}
  1110  	defer close()
  1111  
  1112  	// Configure no resources on the management server.
  1113  	resources := e2e.UpdateOptions{NodeID: nodeID, SkipValidation: true}
  1114  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
  1115  	defer cancel()
  1116  	if err := mgmtServer.Update(ctx, resources); err != nil {
  1117  		t.Fatalf("Failed to update management server with resources: %v, err: %v", resources, err)
  1118  	}
  1119  
  1120  	// Create a manual resolver and push a service config specifying the use of
  1121  	// the cluster_resolver LB policy with a single discovery mechanism.
  1122  	r := manual.NewBuilderWithScheme("whatever")
  1123  	jsonSC := fmt.Sprintf(`{
  1124  			"loadBalancingConfig":[{
  1125  				"cluster_resolver_experimental":{
  1126  					"discoveryMechanisms": [{
  1127  						"cluster": "%s",
  1128  						"type": "EDS",
  1129  						"edsServiceName": "%s",
  1130  						"outlierDetection": {}
  1131  					}],
  1132  					"xdsLbPolicy":[{"round_robin":{}}]
  1133  				}
  1134  			}]
  1135  		}`, clusterName, edsServiceName)
  1136  	scpr := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(jsonSC)
  1137  	r.InitialState(xdsclient.SetClient(resolver.State{ServiceConfig: scpr}, xdsClient))
  1138  
  1139  	// Create a ClientConn and verify that RPCs fail with "all priorities
  1140  	// removed" error.
  1141  	cc, err := grpc.NewClient(r.Scheme()+":///test.service", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
  1142  	if err != nil {
  1143  		t.Fatalf("failed to create new client for local test server: %v", err)
  1144  	}
  1145  	defer cc.Close()
  1146  	client := testgrpc.NewTestServiceClient(cc)
  1147  	if err := waitForProducedZeroAddressesError(ctx, t, client); err != nil {
  1148  		t.Fatal(err)
  1149  	}
  1150  }
  1151  
  1152  // waitForAllPrioritiesRemovedError repeatedly makes RPCs using the
  1153  // TestServiceClient until they fail with an error which indicates that no
  1154  // resolver addresses have been produced. A non-nil error is returned if the
  1155  // context expires before RPCs fail with the expected error.
  1156  func waitForProducedZeroAddressesError(ctx context.Context, t *testing.T, client testgrpc.TestServiceClient) error {
  1157  	for ; ctx.Err() == nil; <-time.After(time.Millisecond) {
  1158  		_, err := client.EmptyCall(ctx, &testpb.Empty{})
  1159  		if err == nil {
  1160  			t.Log("EmptyCall() succeeded after error in Discovery Mechanism")
  1161  			continue
  1162  		}
  1163  		if code := status.Code(err); code != codes.Unavailable {
  1164  			t.Logf("EmptyCall() returned code: %v, want: %v", code, codes.Unavailable)
  1165  			continue
  1166  		}
  1167  		if !strings.Contains(err.Error(), "no children to pick from") {
  1168  			t.Logf("EmptyCall() = %v, want %v", err, "no children to pick from")
  1169  			continue
  1170  		}
  1171  		return nil
  1172  	}
  1173  	return errors.New("timeout when waiting for RPCs to fail with UNAVAILABLE status and produced zero addresses")
  1174  }
  1175  
  1176  // Test runs a server which listens on multiple ports. The test updates xds resouce
  1177  // cache to contain a single endpoint with multiple addresses. The test intercepts
  1178  // the resolver updates sent to the petiole policy and verifies that the
  1179  // additional endpoint addresses are correctly propagated.
  1180  func (s) TestEDS_EndpointWithMultipleAddresses(t *testing.T) {
  1181  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
  1182  	defer cancel()
  1183  
  1184  	// Start a backend server which listens to multiple ports to simulate a
  1185  	// backend with multiple addresses.
  1186  	server := &stubserver.StubServer{
  1187  		EmptyCallF: func(context.Context, *testpb.Empty) (*testpb.Empty, error) { return &testpb.Empty{}, nil },
  1188  		UnaryCallF: func(context.Context, *testpb.SimpleRequest) (*testpb.SimpleResponse, error) {
  1189  			return &testpb.SimpleResponse{}, nil
  1190  		},
  1191  	}
  1192  	lis1, err := testutils.LocalTCPListener()
  1193  	if err != nil {
  1194  		t.Fatalf("Failed to create listener: %v", err)
  1195  	}
  1196  	defer lis1.Close()
  1197  	lis2, err := testutils.LocalTCPListener()
  1198  	if err != nil {
  1199  		t.Fatalf("Failed to create listener: %v", err)
  1200  	}
  1201  	defer lis2.Close()
  1202  	lis3, err := testutils.LocalTCPListener()
  1203  	if err != nil {
  1204  		t.Fatalf("Failed to create listener: %v", err)
  1205  	}
  1206  	defer lis3.Close()
  1207  
  1208  	server.Listener = lis1
  1209  	if err := server.StartServer(); err != nil {
  1210  		t.Fatalf("Failed to start stub server: %v", err)
  1211  	}
  1212  	go server.S.Serve(lis2)
  1213  	go server.S.Serve(lis3)
  1214  
  1215  	t.Logf("Started test service backend at addresses %q, %q, %q", lis1.Addr(), lis2.Addr(), lis3.Addr())
  1216  
  1217  	ports := []uint32{
  1218  		testutils.ParsePort(t, lis1.Addr().String()),
  1219  		testutils.ParsePort(t, lis2.Addr().String()),
  1220  		testutils.ParsePort(t, lis3.Addr().String()),
  1221  	}
  1222  
  1223  	testCases := []struct {
  1224  		name                      string
  1225  		dualstackEndpointsEnabled bool
  1226  		wantEndpointPorts         []uint32
  1227  		wantAddrPorts             []uint32
  1228  	}{
  1229  		{
  1230  			name:                      "flag_enabled",
  1231  			dualstackEndpointsEnabled: true,
  1232  			wantEndpointPorts:         ports,
  1233  			wantAddrPorts:             ports[:1],
  1234  		},
  1235  		{
  1236  			name:              "flag_disabled",
  1237  			wantEndpointPorts: ports[:1],
  1238  			wantAddrPorts:     ports[:1],
  1239  		},
  1240  	}
  1241  
  1242  	for _, tc := range testCases {
  1243  		t.Run(tc.name, func(t *testing.T) {
  1244  			origDualstackEndpointsEnabled := envconfig.XDSDualstackEndpointsEnabled
  1245  			defer func() {
  1246  				envconfig.XDSDualstackEndpointsEnabled = origDualstackEndpointsEnabled
  1247  			}()
  1248  			envconfig.XDSDualstackEndpointsEnabled = tc.dualstackEndpointsEnabled
  1249  
  1250  			// Wrap the round robin balancer to intercept resolver updates.
  1251  			originalRRBuilder := balancer.Get(roundrobin.Name)
  1252  			defer func() {
  1253  				balancer.Register(originalRRBuilder)
  1254  			}()
  1255  			resolverState := atomic.Pointer[resolver.State]{}
  1256  			resolverState.Store(&resolver.State{})
  1257  			stub.Register(roundrobin.Name, stub.BalancerFuncs{
  1258  				Init: func(bd *stub.BalancerData) {
  1259  					bd.Data = originalRRBuilder.Build(bd.ClientConn, bd.BuildOptions)
  1260  				},
  1261  				Close: func(bd *stub.BalancerData) {
  1262  					bd.Data.(balancer.Balancer).Close()
  1263  				},
  1264  				UpdateClientConnState: func(bd *stub.BalancerData, ccs balancer.ClientConnState) error {
  1265  					resolverState.Store(&ccs.ResolverState)
  1266  					return bd.Data.(balancer.Balancer).UpdateClientConnState(ccs)
  1267  				},
  1268  			})
  1269  
  1270  			// Spin up a management server to receive xDS resources from.
  1271  			mgmtServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{})
  1272  
  1273  			// Create bootstrap configuration pointing to the above management server.
  1274  			nodeID := uuid.New().String()
  1275  			bootstrapContents := e2e.DefaultBootstrapContents(t, nodeID, mgmtServer.Address)
  1276  			config, err := bootstrap.NewConfigFromContents(bootstrapContents)
  1277  			if err != nil {
  1278  				t.Fatalf("Failed to parse bootstrap contents: %s, %v", string(bootstrapContents), err)
  1279  			}
  1280  			pool := xdsclient.NewPool(config)
  1281  
  1282  			// Create xDS resources for consumption by the test. We start off with a
  1283  			// single backend in a single EDS locality.
  1284  			resources := clientEndpointsResource(nodeID, edsServiceName, []e2e.LocalityOptions{{
  1285  				Name:   localityName1,
  1286  				Weight: 1,
  1287  				Backends: []e2e.BackendOptions{{
  1288  					Ports: ports,
  1289  				}},
  1290  			}})
  1291  			if err := mgmtServer.Update(ctx, resources); err != nil {
  1292  				t.Fatal(err)
  1293  			}
  1294  
  1295  			// Create an xDS client talking to the above management server, configured
  1296  			// with a short watch expiry timeout.
  1297  			xdsClient, close, err := pool.NewClientForTesting(xdsclient.OptionsForTesting{
  1298  				Name: t.Name(),
  1299  			})
  1300  			if err != nil {
  1301  				t.Fatalf("Failed to create an xDS client: %v", err)
  1302  			}
  1303  			defer close()
  1304  
  1305  			// Create a manual resolver and push a service config specifying the use of
  1306  			// the cluster_resolver LB policy with a single discovery mechanism.
  1307  			r := manual.NewBuilderWithScheme("whatever")
  1308  			jsonSC := fmt.Sprintf(`{
  1309  				"loadBalancingConfig":[{
  1310  					"cluster_resolver_experimental":{
  1311  						"discoveryMechanisms": [{
  1312  							"cluster": "%s",
  1313  							"type": "EDS",
  1314  							"edsServiceName": "%s",
  1315  							"outlierDetection": {}
  1316  						}],
  1317  						"xdsLbPolicy":[{"round_robin":{}}]
  1318  					}
  1319  				}]
  1320  			}`, clusterName, edsServiceName)
  1321  			scpr := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(jsonSC)
  1322  			r.InitialState(xdsclient.SetClient(resolver.State{ServiceConfig: scpr}, xdsClient))
  1323  
  1324  			cc, err := grpc.NewClient(r.Scheme()+":///test.service", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r))
  1325  			if err != nil {
  1326  				t.Fatalf("failed to create new client for local test server: %v", err)
  1327  			}
  1328  			defer cc.Close()
  1329  			client := testgrpc.NewTestServiceClient(cc)
  1330  			if err := rrutil.CheckRoundRobinRPCs(ctx, client, []resolver.Address{{Addr: lis1.Addr().String()}}); err != nil {
  1331  				t.Fatal(err)
  1332  			}
  1333  
  1334  			gotState := resolverState.Load()
  1335  
  1336  			gotEndpointPorts := []uint32{}
  1337  			for _, a := range gotState.Endpoints[0].Addresses {
  1338  				gotEndpointPorts = append(gotEndpointPorts, testutils.ParsePort(t, a.Addr))
  1339  			}
  1340  			if diff := cmp.Diff(gotEndpointPorts, tc.wantEndpointPorts); diff != "" {
  1341  				t.Errorf("Unexpected endpoint address ports in resolver update, diff (-got +want): %v", diff)
  1342  			}
  1343  
  1344  			gotAddrPorts := []uint32{}
  1345  			for _, a := range gotState.Addresses {
  1346  				gotAddrPorts = append(gotAddrPorts, testutils.ParsePort(t, a.Addr))
  1347  			}
  1348  			if diff := cmp.Diff(gotAddrPorts, tc.wantAddrPorts); diff != "" {
  1349  				t.Errorf("Unexpected address ports in resolver update, diff (-got +want): %v", diff)
  1350  			}
  1351  		})
  1352  	}
  1353  }