...

Source file src/google.golang.org/grpc/xds/internal/resolver/watch_service_test.go

Documentation: google.golang.org/grpc/xds/internal/resolver

     1  /*
     2   *
     3   * Copyright 2020 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 resolver_test
    20  
    21  import (
    22  	"context"
    23  	"testing"
    24  
    25  	"github.com/envoyproxy/go-control-plane/pkg/wellknown"
    26  	"github.com/google/uuid"
    27  	"google.golang.org/grpc/internal/testutils"
    28  	"google.golang.org/grpc/internal/testutils/xds/e2e"
    29  	"google.golang.org/grpc/resolver"
    30  	"google.golang.org/protobuf/types/known/wrapperspb"
    31  
    32  	v3listenerpb "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
    33  	v3routepb "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
    34  	v3routerpb "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/router/v3"
    35  	v3httppb "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
    36  )
    37  
    38  // Tests the case where the listener resource starts pointing to a new route
    39  // configuration resource after the xDS resolver has successfully resolved the
    40  // service name and pushed an update on the channel. The test verifies that the
    41  // resolver stops requesting the old route configuration resource and requests
    42  // the new resource, and once successfully resolved, verifies that the update
    43  // from the resolver matches expected service config.
    44  func (s) TestServiceWatch_ListenerPointsToNewRouteConfiguration(t *testing.T) {
    45  	// Spin up an xDS management server for the test.
    46  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
    47  	defer cancel()
    48  	nodeID := uuid.New().String()
    49  	mgmtServer, lisCh, routeCfgCh := setupManagementServerForTest(ctx, t, nodeID)
    50  
    51  	// Configure resources on the management server.
    52  	listeners := []*v3listenerpb.Listener{e2e.DefaultClientListener(defaultTestServiceName, defaultTestRouteConfigName)}
    53  	routes := []*v3routepb.RouteConfiguration{e2e.DefaultRouteConfig(defaultTestRouteConfigName, defaultTestServiceName, defaultTestClusterName)}
    54  	configureResourcesOnManagementServer(ctx, t, mgmtServer, nodeID, listeners, routes)
    55  
    56  	stateCh, _, _ := buildResolverForTarget(t, resolver.Target{URL: *testutils.MustParseURL("xds:///" + defaultTestServiceName)})
    57  
    58  	// Verify initial update from the resolver.
    59  	waitForResourceNames(ctx, t, lisCh, []string{defaultTestServiceName})
    60  	waitForResourceNames(ctx, t, routeCfgCh, []string{defaultTestRouteConfigName})
    61  	verifyUpdateFromResolver(ctx, t, stateCh, wantDefaultServiceConfig)
    62  
    63  	// Update the listener resource to point to a new route configuration name.
    64  	// Leave the old route configuration resource unchanged.
    65  	newTestRouteConfigName := defaultTestRouteConfigName + "-new"
    66  	listeners = []*v3listenerpb.Listener{e2e.DefaultClientListener(defaultTestServiceName, newTestRouteConfigName)}
    67  	configureResourcesOnManagementServer(ctx, t, mgmtServer, nodeID, listeners, routes)
    68  
    69  	// Verify that the new route configuration resource is requested.
    70  	waitForResourceNames(ctx, t, routeCfgCh, []string{newTestRouteConfigName})
    71  
    72  	// Update the old route configuration resource by adding a new route.
    73  	routes[0].VirtualHosts[0].Routes = append(routes[0].VirtualHosts[0].Routes, &v3routepb.Route{
    74  		Match: &v3routepb.RouteMatch{
    75  			PathSpecifier: &v3routepb.RouteMatch_Prefix{Prefix: "/foo/bar"},
    76  			CaseSensitive: &wrapperspb.BoolValue{Value: false},
    77  		},
    78  		Action: &v3routepb.Route_Route{
    79  			Route: &v3routepb.RouteAction{
    80  				ClusterSpecifier: &v3routepb.RouteAction_Cluster{Cluster: "some-random-cluster"},
    81  			},
    82  		},
    83  	})
    84  	configureResourcesOnManagementServer(ctx, t, mgmtServer, nodeID, listeners, routes)
    85  
    86  	// Wait for no update from the resolver.
    87  	verifyNoUpdateFromResolver(ctx, t, stateCh)
    88  
    89  	// Update the management server with the new route configuration resource.
    90  	routes = append(routes, e2e.DefaultRouteConfig(newTestRouteConfigName, defaultTestServiceName, defaultTestClusterName))
    91  	configureResourcesOnManagementServer(ctx, t, mgmtServer, nodeID, listeners, routes)
    92  
    93  	// Ensure update from the resolver.
    94  	verifyUpdateFromResolver(ctx, t, stateCh, wantDefaultServiceConfig)
    95  }
    96  
    97  // Tests the case where the listener resource changes to contain an inline route
    98  // configuration and changes back to having a route configuration resource name.
    99  // Verifies that the expected xDS resource names are requested by the resolver
   100  // and that the update from the resolver matches expected service config.
   101  func (s) TestServiceWatch_ListenerPointsToInlineRouteConfiguration(t *testing.T) {
   102  	// Spin up an xDS management server for the test.
   103  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   104  	defer cancel()
   105  	nodeID := uuid.New().String()
   106  	mgmtServer, lisCh, routeCfgCh := setupManagementServerForTest(ctx, t, nodeID)
   107  
   108  	// Configure resources on the management server.
   109  	listeners := []*v3listenerpb.Listener{e2e.DefaultClientListener(defaultTestServiceName, defaultTestRouteConfigName)}
   110  	routes := []*v3routepb.RouteConfiguration{e2e.DefaultRouteConfig(defaultTestRouteConfigName, defaultTestServiceName, defaultTestClusterName)}
   111  	configureResourcesOnManagementServer(ctx, t, mgmtServer, nodeID, listeners, routes)
   112  
   113  	stateCh, _, _ := buildResolverForTarget(t, resolver.Target{URL: *testutils.MustParseURL("xds:///" + defaultTestServiceName)})
   114  
   115  	// Verify initial update from the resolver.
   116  	waitForResourceNames(ctx, t, lisCh, []string{defaultTestServiceName})
   117  	waitForResourceNames(ctx, t, routeCfgCh, []string{defaultTestRouteConfigName})
   118  	verifyUpdateFromResolver(ctx, t, stateCh, wantDefaultServiceConfig)
   119  
   120  	// Update listener to contain an inline route configuration.
   121  	hcm := testutils.MarshalAny(t, &v3httppb.HttpConnectionManager{
   122  		RouteSpecifier: &v3httppb.HttpConnectionManager_RouteConfig{
   123  			RouteConfig: &v3routepb.RouteConfiguration{
   124  				Name: defaultTestRouteConfigName,
   125  				VirtualHosts: []*v3routepb.VirtualHost{{
   126  					Domains: []string{defaultTestServiceName},
   127  					Routes: []*v3routepb.Route{{
   128  						Match: &v3routepb.RouteMatch{
   129  							PathSpecifier: &v3routepb.RouteMatch_Prefix{Prefix: "/"},
   130  						},
   131  						Action: &v3routepb.Route_Route{
   132  							Route: &v3routepb.RouteAction{
   133  								ClusterSpecifier: &v3routepb.RouteAction_Cluster{Cluster: defaultTestClusterName},
   134  							},
   135  						},
   136  					}},
   137  				}},
   138  			},
   139  		},
   140  		HttpFilters: []*v3httppb.HttpFilter{e2e.HTTPFilter("router", &v3routerpb.Router{})},
   141  	})
   142  	listeners = []*v3listenerpb.Listener{{
   143  		Name:        defaultTestServiceName,
   144  		ApiListener: &v3listenerpb.ApiListener{ApiListener: hcm},
   145  		FilterChains: []*v3listenerpb.FilterChain{{
   146  			Name: "filter-chain-name",
   147  			Filters: []*v3listenerpb.Filter{{
   148  				Name:       wellknown.HTTPConnectionManager,
   149  				ConfigType: &v3listenerpb.Filter_TypedConfig{TypedConfig: hcm},
   150  			}},
   151  		}},
   152  	}}
   153  	configureResourcesOnManagementServer(ctx, t, mgmtServer, nodeID, listeners, nil)
   154  
   155  	// Verify that the old route configuration is not requested anymore.
   156  	waitForResourceNames(ctx, t, routeCfgCh, []string{})
   157  	verifyUpdateFromResolver(ctx, t, stateCh, wantDefaultServiceConfig)
   158  
   159  	// Update listener back to contain a route configuration name.
   160  	listeners = []*v3listenerpb.Listener{e2e.DefaultClientListener(defaultTestServiceName, defaultTestRouteConfigName)}
   161  	configureResourcesOnManagementServer(ctx, t, mgmtServer, nodeID, listeners, routes)
   162  
   163  	// Verify that that route configuration resource is requested.
   164  	waitForResourceNames(ctx, t, routeCfgCh, []string{defaultTestRouteConfigName})
   165  
   166  	// Verify that appropriate SC is pushed on the channel.
   167  	verifyUpdateFromResolver(ctx, t, stateCh, wantDefaultServiceConfig)
   168  }
   169  

View as plain text