@@ -663,3 +663,114 @@ func (s) TestLRSLogicalDNS(t *testing.T) {
663663 t .Fatalf ("Server did not receive load due to error: %v" , err )
664664 }
665665}
666+
667+ // TestReResolution verifies that when a SubConn turns transient failure,
668+ // re-resolution is triggered.
669+ func (s ) TestReResolution (t * testing.T ) {
670+ // Create an xDS management server that serves ADS requests.
671+ mgmtServer := e2e .StartManagementServer (t , e2e.ManagementServerOptions {})
672+
673+ // Create bootstrap configuration pointing to the above management server.
674+ nodeID := uuid .New ().String ()
675+ bc := e2e .DefaultBootstrapContents (t , nodeID , mgmtServer .Address )
676+ testutils .CreateBootstrapFileForTesting (t , bc )
677+
678+ // Create an xDS resolver with the above bootstrap configuration.
679+ if internal .NewXDSResolverWithConfigForTesting == nil {
680+ t .Fatalf ("internal.NewXDSResolverWithConfigForTesting is nil" )
681+ }
682+ resolverBuilder , err := internal .NewXDSResolverWithConfigForTesting .(func ([]byte ) (resolver.Builder , error ))(bc )
683+ if err != nil {
684+ t .Fatalf ("Failed to create xDS resolver for testing: %v" , err )
685+ }
686+
687+ // Start two server backends exposing the test service.
688+ backend1 := stubserver .StartTestService (t , nil )
689+ defer backend1 .Stop ()
690+ backend1Host , backend1Port := hostAndPortFromAddress (t , backend1 .Address )
691+
692+ backend2 := stubserver .StartTestService (t , nil )
693+ defer backend2 .Stop ()
694+ backend2Host , backend2Port := hostAndPortFromAddress (t , backend2 .Address )
695+
696+ // Configure the xDS management server with Logical DNS cluster pointing to backend1.
697+ const serviceName = "test-xds-service"
698+ resources := e2e .DefaultClientResources (e2e.ResourceParams {
699+ DialTarget : serviceName ,
700+ NodeID : nodeID ,
701+ Host : backend1Host ,
702+ Port : backend1Port ,
703+ })
704+ resources .Clusters = []* v3clusterpb.Cluster {
705+ e2e .ClusterResourceWithOptions (e2e.ClusterOptions {
706+ ClusterName : "cluster-" + serviceName ,
707+ Type : e2e .ClusterTypeLogicalDNS ,
708+ DNSHostName : backend1Host ,
709+ DNSPort : backend1Port ,
710+ }),
711+ }
712+ resources .Endpoints = nil
713+
714+ ctx , cancel := context .WithTimeout (context .Background (), defaultTestTimeout )
715+ defer cancel ()
716+
717+ if err := mgmtServer .Update (ctx , resources ); err != nil {
718+ t .Fatal (err )
719+ }
720+
721+ // Create a ClientConn and make a successful RPC.
722+ cc , err := grpc .NewClient (fmt .Sprintf ("xds:///%s" , serviceName ), grpc .WithTransportCredentials (insecure .NewCredentials ()),
723+ grpc .WithResolvers (resolverBuilder ),
724+ )
725+ if err != nil {
726+ t .Fatalf ("failed to dial local test server: %v" , err )
727+ }
728+ defer cc .Close ()
729+
730+ cc .Connect ()
731+ client := testgrpc .NewTestServiceClient (cc )
732+ testutils .AwaitState (ctx , t , cc , connectivity .Ready )
733+
734+ // Perform initial RPC to backend1, expect success.
735+ var peer peer.Peer
736+ if _ , err := client .EmptyCall (ctx , & testpb.Empty {}, grpc .Peer (& peer )); err != nil {
737+ t .Fatalf ("Expected initial rpc to backend1 to succeed, got: %v" , err )
738+ }
739+
740+ // Verify that the request was sent to backend 1.
741+ if got , want := peer .Addr .String (), backend1 .Address ; got != want {
742+ t .Fatalf ("EmptyCall() routed to backend %q, want %q" , peer .Addr , backend1 .Address )
743+ }
744+
745+ // Stop backend1 to simulate failure.
746+ backend1 .Stop ()
747+
748+ // Update management server with Logical DNS cluster pointing to backend2 now.
749+ resources .Clusters [0 ] = e2e .ClusterResourceWithOptions (e2e.ClusterOptions {
750+ ClusterName : "cluster-" + serviceName ,
751+ Type : e2e .ClusterTypeLogicalDNS ,
752+ DNSHostName : backend2Host ,
753+ DNSPort : backend2Port ,
754+ })
755+
756+ if err := mgmtServer .Update (ctx , resources ); err != nil {
757+ t .Fatalf ("failed to update management server resources to backend2: %v" , err )
758+ }
759+
760+ // Wait for client to re-resolve and start routing to backend2.
761+ for {
762+ if ctx .Err () != nil {
763+ t .Fatalf ("Timed out while waiting for RPC to be routed to backend2: %v" , ctx .Err ())
764+ }
765+ if _ , err := client .EmptyCall (ctx , & testpb.Empty {}, grpc .Peer (& peer ), grpc .WaitForReady (true )); err != nil {
766+ t .Logf ("RPC failed, possibly during switchover: %v" , err )
767+ time .Sleep (100 * time .Millisecond )
768+ continue
769+ }
770+ if peer .Addr .String () == backend2 .Address {
771+ break
772+ }
773+ t .Logf ("RPC routed to %q, waiting for %q" , peer .Addr .String (), backend2 .Address )
774+ time .Sleep (100 * time .Millisecond )
775+ }
776+ }
0 commit comments