google.golang.org/grpc@v1.62.1/xds/internal/resolver/watch_service_test.go (about) 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 }