From c3355c8604ad0b07d704bde8ca88d1e52a76be49 Mon Sep 17 00:00:00 2001 From: Pranjali-2501 Date: Wed, 26 Nov 2025 16:22:16 +0000 Subject: [PATCH 1/3] resource validation changes --- internal/envconfig/envconfig.go | 5 + .../xds/xdsclient/xdsresource/filter_chain.go | 2 +- .../xdsresource/route_config_resource_type.go | 4 +- .../xds/xdsclient/xdsresource/type_eds.go | 1 + .../xds/xdsclient/xdsresource/type_rds.go | 3 + .../xdsclient/xdsresource/unmarshal_eds.go | 1 + .../xdsresource/unmarshal_eds_test.go | 22 +++-- .../xdsclient/xdsresource/unmarshal_lds.go | 2 +- .../xdsclient/xdsresource/unmarshal_rds.go | 22 +++-- .../xdsresource/unmarshal_rds_test.go | 97 ++++++++++++++++++- 10 files changed, 139 insertions(+), 20 deletions(-) diff --git a/internal/envconfig/envconfig.go b/internal/envconfig/envconfig.go index 91f760936c02..6874045a982c 100644 --- a/internal/envconfig/envconfig.go +++ b/internal/envconfig/envconfig.go @@ -77,6 +77,11 @@ var ( // - Target resolution is disabled. // - The DNS resolver is being used. EnableDefaultPortForProxyTarget = boolFromEnv("GRPC_EXPERIMENTAL_ENABLE_DEFAULT_PORT_FOR_PROXY_TARGET", true) + + // XDSAuthorityRewrite is set if xDS authority rewriting is enabled, + // according to gRFC A81. It can be enabled by setting + // GRPC_EXPERIMENTAL_XDS_AUTHORITY_REWRITE to true. + XDSAuthorityRewrite = boolFromEnv("GRPC_EXPERIMENTAL_XDS_AUTHORITY_REWRITE", false) ) func boolFromEnv(envVar string, def bool) bool { diff --git a/internal/xds/xdsclient/xdsresource/filter_chain.go b/internal/xds/xdsclient/xdsresource/filter_chain.go index 76ace1090d68..fcb1b566a4a9 100644 --- a/internal/xds/xdsclient/xdsresource/filter_chain.go +++ b/internal/xds/xdsclient/xdsresource/filter_chain.go @@ -680,7 +680,7 @@ func processNetworkFilters(filters []*v3listenerpb.Filter) (*FilterChain, error) // server-side." - A36 // Can specify v3 here, as will never get to this function // if v2. - routeU, err := generateRDSUpdateFromRouteConfiguration(hcm.GetRouteConfig()) + routeU, err := generateRDSUpdateFromRouteConfiguration(nil, hcm.GetRouteConfig()) if err != nil { return nil, fmt.Errorf("failed to parse inline RDS resp: %v", err) } diff --git a/internal/xds/xdsclient/xdsresource/route_config_resource_type.go b/internal/xds/xdsclient/xdsresource/route_config_resource_type.go index 81033c91f5d9..6e86829c8caa 100644 --- a/internal/xds/xdsclient/xdsresource/route_config_resource_type.go +++ b/internal/xds/xdsclient/xdsresource/route_config_resource_type.go @@ -37,8 +37,8 @@ type routeConfigResourceDecoder struct { bootstrapConfig *bootstrap.Config } -func (d *routeConfigResourceDecoder) Decode(resource *xdsclient.AnyProto, _ xdsclient.DecodeOptions) (*xdsclient.DecodeResult, error) { - name, rc, err := unmarshalRouteConfigResource(resource.ToAny()) +func (d *routeConfigResourceDecoder) Decode(resource *xdsclient.AnyProto, opts xdsclient.DecodeOptions) (*xdsclient.DecodeResult, error) { + name, rc, err := unmarshalRouteConfigResource(&opts, resource.ToAny()) if name == "" { // Name is unset only when protobuf deserialization fails. return nil, err diff --git a/internal/xds/xdsclient/xdsresource/type_eds.go b/internal/xds/xdsclient/xdsresource/type_eds.go index a8d568e18263..39b2ba74ddcb 100644 --- a/internal/xds/xdsclient/xdsresource/type_eds.go +++ b/internal/xds/xdsclient/xdsresource/type_eds.go @@ -54,6 +54,7 @@ type Endpoint struct { Weight uint32 HashKey string Metadata map[string]any + Hostname string } // Locality contains information of a locality. diff --git a/internal/xds/xdsclient/xdsresource/type_rds.go b/internal/xds/xdsclient/xdsresource/type_rds.go index 0cde9738d5f1..48e8051b3222 100644 --- a/internal/xds/xdsclient/xdsresource/type_rds.go +++ b/internal/xds/xdsclient/xdsresource/type_rds.go @@ -150,6 +150,9 @@ type Route struct { // ClusterSpecifierPlugin is the name of the Cluster Specifier Plugin that // this Route is linked to, if specified by xDS. ClusterSpecifierPlugin string + // AutoHostRewrite indicates that the ":authority" header can be rewritten + // to the hostname of the upstream endpoint. + AutoHostRewrite bool } // WeightedCluster contains settings for an xds ActionType.WeightedCluster. diff --git a/internal/xds/xdsclient/xdsresource/unmarshal_eds.go b/internal/xds/xdsclient/xdsresource/unmarshal_eds.go index c5b9723a79a3..ebf47961c45d 100644 --- a/internal/xds/xdsclient/xdsresource/unmarshal_eds.go +++ b/internal/xds/xdsclient/xdsresource/unmarshal_eds.go @@ -132,6 +132,7 @@ func parseEndpoints(lbEndpoints []*v3endpointpb.LbEndpoint, uniqueEndpointAddrs Weight: weight, HashKey: hashKey, Metadata: endpointMetadata, + Hostname: lbEndpoint.GetEndpoint().GetHostname(), }) } return endpoints, nil diff --git a/internal/xds/xdsclient/xdsresource/unmarshal_eds_test.go b/internal/xds/xdsclient/xdsresource/unmarshal_eds_test.go index 3020b4953116..421d270f1ec4 100644 --- a/internal/xds/xdsclient/xdsresource/unmarshal_eds_test.go +++ b/internal/xds/xdsclient/xdsresource/unmarshal_eds_test.go @@ -130,11 +130,11 @@ func (s) TestEDSParseRespProto(t *testing.T) { name: "good", m: func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 1, []endpointOpts{{addrWithPort: "addr1:314"}}, &addLocalityOptions{ + clab0.addLocality("locality-1", 1, 1, []endpointOpts{{addrWithPort: "addr1:314", hostname: "addr1"}}, &addLocalityOptions{ Health: []v3corepb.HealthStatus{v3corepb.HealthStatus_UNHEALTHY}, Weight: []uint32{271}, }) - clab0.addLocality("locality-2", 1, 0, []endpointOpts{{addrWithPort: "addr2:159"}}, &addLocalityOptions{ + clab0.addLocality("locality-2", 1, 0, []endpointOpts{{addrWithPort: "addr2:159", hostname: "addr2"}}, &addLocalityOptions{ Health: []v3corepb.HealthStatus{v3corepb.HealthStatus_DRAINING}, Weight: []uint32{828}, }) @@ -148,6 +148,7 @@ func (s) TestEDSParseRespProto(t *testing.T) { Addresses: []string{"addr1:314"}, HealthStatus: EndpointHealthStatusUnhealthy, Weight: 271, + Hostname: "addr1", }}, ID: clients.Locality{SubZone: "locality-1"}, Priority: 1, @@ -158,6 +159,7 @@ func (s) TestEDSParseRespProto(t *testing.T) { Addresses: []string{"addr2:159"}, HealthStatus: EndpointHealthStatusDraining, Weight: 828, + Hostname: "addr2", }}, ID: clients.Locality{SubZone: "locality-2"}, Priority: 0, @@ -171,12 +173,12 @@ func (s) TestEDSParseRespProto(t *testing.T) { name: "good duplicate locality with different priority", m: func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 1, []endpointOpts{{addrWithPort: "addr1:314"}}, &addLocalityOptions{ + clab0.addLocality("locality-1", 1, 1, []endpointOpts{{addrWithPort: "addr1:314", hostname: "addr1"}}, &addLocalityOptions{ Health: []v3corepb.HealthStatus{v3corepb.HealthStatus_UNHEALTHY}, Weight: []uint32{271}, }) // Same locality name, but with different priority. - clab0.addLocality("locality-1", 1, 0, []endpointOpts{{addrWithPort: "addr2:159"}}, &addLocalityOptions{ + clab0.addLocality("locality-1", 1, 0, []endpointOpts{{addrWithPort: "addr2:159", hostname: "addr2"}}, &addLocalityOptions{ Health: []v3corepb.HealthStatus{v3corepb.HealthStatus_DRAINING}, Weight: []uint32{828}, }) @@ -190,6 +192,7 @@ func (s) TestEDSParseRespProto(t *testing.T) { Addresses: []string{"addr1:314"}, HealthStatus: EndpointHealthStatusUnhealthy, Weight: 271, + Hostname: "addr1", }}, ID: clients.Locality{SubZone: "locality-1"}, Priority: 1, @@ -200,6 +203,7 @@ func (s) TestEDSParseRespProto(t *testing.T) { Addresses: []string{"addr2:159"}, HealthStatus: EndpointHealthStatusDraining, Weight: 828, + Hostname: "addr2", }}, ID: clients.Locality{SubZone: "locality-1"}, Priority: 0, @@ -466,11 +470,11 @@ func (s) TestUnmarshalEndpoints(t *testing.T) { testutils.SetEnvConfig(t, &envconfig.XDSHTTPConnectEnabled, true) var v3EndpointsAny = testutils.MarshalAny(t, func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 1, []endpointOpts{{addrWithPort: "addr1:314"}}, &addLocalityOptions{ + clab0.addLocality("locality-1", 1, 1, []endpointOpts{{addrWithPort: "addr1:314", hostname: "addr1"}}, &addLocalityOptions{ Health: []v3corepb.HealthStatus{v3corepb.HealthStatus_UNHEALTHY}, Weight: []uint32{271}, }) - clab0.addLocality("locality-2", 1, 0, []endpointOpts{{addrWithPort: "addr2:159"}}, &addLocalityOptions{ + clab0.addLocality("locality-2", 1, 0, []endpointOpts{{addrWithPort: "addr2:159", hostname: "addr2"}}, &addLocalityOptions{ Health: []v3corepb.HealthStatus{v3corepb.HealthStatus_DRAINING}, Weight: []uint32{828}, }) @@ -520,6 +524,7 @@ func (s) TestUnmarshalEndpoints(t *testing.T) { Addresses: []string{"addr1:314"}, HealthStatus: EndpointHealthStatusUnhealthy, Weight: 271, + Hostname: "addr1", }}, ID: clients.Locality{SubZone: "locality-1"}, Priority: 1, @@ -530,6 +535,7 @@ func (s) TestUnmarshalEndpoints(t *testing.T) { Addresses: []string{"addr2:159"}, HealthStatus: EndpointHealthStatusDraining, Weight: 828, + Hostname: "addr2", }}, ID: clients.Locality{SubZone: "locality-2"}, Priority: 0, @@ -551,6 +557,7 @@ func (s) TestUnmarshalEndpoints(t *testing.T) { Addresses: []string{"addr1:314"}, HealthStatus: EndpointHealthStatusUnhealthy, Weight: 271, + Hostname: "addr1", }}, ID: clients.Locality{SubZone: "locality-1"}, Priority: 1, @@ -561,6 +568,7 @@ func (s) TestUnmarshalEndpoints(t *testing.T) { Addresses: []string{"addr2:159"}, HealthStatus: EndpointHealthStatusDraining, Weight: 828, + Hostname: "addr2", }}, ID: clients.Locality{SubZone: "locality-2"}, Priority: 0, @@ -1382,6 +1390,7 @@ type endpointOpts struct { addrWithPort string additionalAddrWithPorts []string metadata *v3corepb.Metadata + hostname string } func addressFromStr(addrWithPort string) *v3corepb.Address { @@ -1420,6 +1429,7 @@ func (clab *claBuilder) addLocality(subzone string, weight uint32, priority uint Endpoint: &v3endpointpb.Endpoint{ Address: addressFromStr(e.addrWithPort), AdditionalAddresses: additionalAddrs, + Hostname: e.hostname, }, }, Metadata: e.metadata, diff --git a/internal/xds/xdsclient/xdsresource/unmarshal_lds.go b/internal/xds/xdsclient/xdsresource/unmarshal_lds.go index 25c607b48a4d..4c38894036f2 100644 --- a/internal/xds/xdsclient/xdsresource/unmarshal_lds.go +++ b/internal/xds/xdsclient/xdsresource/unmarshal_lds.go @@ -95,7 +95,7 @@ func processClientSideListener(lis *v3listenerpb.Listener) (*ListenerUpdate, err } update.RouteConfigName = name case *v3httppb.HttpConnectionManager_RouteConfig: - routeU, err := generateRDSUpdateFromRouteConfiguration(apiLis.GetRouteConfig()) + routeU, err := generateRDSUpdateFromRouteConfiguration(nil, apiLis.GetRouteConfig()) if err != nil { return nil, fmt.Errorf("failed to parse inline RDS resp: %v", err) } diff --git a/internal/xds/xdsclient/xdsresource/unmarshal_rds.go b/internal/xds/xdsclient/xdsresource/unmarshal_rds.go index 479d023f40ac..aaba42e80593 100644 --- a/internal/xds/xdsclient/xdsresource/unmarshal_rds.go +++ b/internal/xds/xdsclient/xdsresource/unmarshal_rds.go @@ -25,6 +25,8 @@ import ( "time" "google.golang.org/grpc/codes" + "google.golang.org/grpc/internal/envconfig" + "google.golang.org/grpc/internal/xds/clients/xdsclient" "google.golang.org/grpc/internal/xds/clusterspecifier" "google.golang.org/grpc/internal/xds/matcher" "google.golang.org/protobuf/proto" @@ -34,7 +36,7 @@ import ( v3typepb "github.com/envoyproxy/go-control-plane/envoy/type/v3" ) -func unmarshalRouteConfigResource(r *anypb.Any) (string, RouteConfigUpdate, error) { +func unmarshalRouteConfigResource(opts *xdsclient.DecodeOptions, r *anypb.Any) (string, RouteConfigUpdate, error) { r, err := UnwrapResource(r) if err != nil { return "", RouteConfigUpdate{}, fmt.Errorf("failed to unwrap resource: %v", err) @@ -48,7 +50,7 @@ func unmarshalRouteConfigResource(r *anypb.Any) (string, RouteConfigUpdate, erro return "", RouteConfigUpdate{}, fmt.Errorf("failed to unmarshal resource: %v", err) } - u, err := generateRDSUpdateFromRouteConfiguration(rc) + u, err := generateRDSUpdateFromRouteConfiguration(opts, rc) if err != nil { return rc.GetName(), RouteConfigUpdate{}, err } @@ -67,12 +69,12 @@ func unmarshalRouteConfigResource(r *anypb.Any) (string, RouteConfigUpdate, erro // The RouteConfiguration includes a list of virtualHosts, which may have zero // or more elements. We are interested in the element whose domains field // matches the server name specified in the "xds:" URI. The only field in the -// VirtualHost proto that the we are interested in is the list of routes. We +// VirtualHost proto that we are interested in is the list of routes. We // only look at the last route in the list (the default route), whose match -// field must be empty and whose route field must be set. Inside that route +// field must be empty and whose route field must be set. Inside that route // message, the cluster field will contain the clusterName or weighted clusters // we are looking for. -func generateRDSUpdateFromRouteConfiguration(rc *v3routepb.RouteConfiguration) (RouteConfigUpdate, error) { +func generateRDSUpdateFromRouteConfiguration(opts *xdsclient.DecodeOptions, rc *v3routepb.RouteConfiguration) (RouteConfigUpdate, error) { vhs := make([]*VirtualHost, 0, len(rc.GetVirtualHosts())) csps, err := processClusterSpecifierPlugins(rc.ClusterSpecifierPlugins) if err != nil { @@ -83,7 +85,7 @@ func generateRDSUpdateFromRouteConfiguration(rc *v3routepb.RouteConfiguration) ( // ignored and not emitted by the xdsclient. var cspNames = make(map[string]bool) for _, vh := range rc.GetVirtualHosts() { - routes, cspNs, err := routesProtoToSlice(vh.Routes, csps) + routes, cspNs, err := routesProtoToSlice(opts, vh.Routes, csps) if err != nil { return RouteConfigUpdate{}, fmt.Errorf("received route is invalid: %v", err) } @@ -206,7 +208,7 @@ func generateRetryConfig(rp *v3routepb.RetryPolicy) (*RetryConfig, error) { return cfg, nil } -func routesProtoToSlice(routes []*v3routepb.Route, csps map[string]clusterspecifier.BalancerConfig) ([]*Route, map[string]bool, error) { +func routesProtoToSlice(opts *xdsclient.DecodeOptions, routes []*v3routepb.Route, csps map[string]clusterspecifier.BalancerConfig) ([]*Route, map[string]bool, error) { var routesRet []*Route var cspNames = make(map[string]bool) for _, r := range routes { @@ -302,6 +304,12 @@ func routesProtoToSlice(routes []*v3routepb.Route, csps map[string]clusterspecif case *v3routepb.Route_Route: action := r.GetRoute() + if envconfig.XDSAuthorityRewrite { + if opts != nil && opts.ServerConfig != nil && opts.ServerConfig.SupportsServerFeature(xdsclient.ServerFeatureTrustedXDSServer) { + route.AutoHostRewrite = action.GetAutoHostRewrite().GetValue() + } + } + // Hash Policies are only applicable for a Ring Hash LB. hp, err := hashPoliciesProtoToSlice(action.HashPolicy) if err != nil { diff --git a/internal/xds/xdsclient/xdsresource/unmarshal_rds_test.go b/internal/xds/xdsclient/xdsresource/unmarshal_rds_test.go index 90d80c8be6b7..a34b405ec245 100644 --- a/internal/xds/xdsclient/xdsresource/unmarshal_rds_test.go +++ b/internal/xds/xdsclient/xdsresource/unmarshal_rds_test.go @@ -29,8 +29,10 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "google.golang.org/grpc/codes" + "google.golang.org/grpc/internal/envconfig" "google.golang.org/grpc/internal/pretty" "google.golang.org/grpc/internal/testutils" + "google.golang.org/grpc/internal/xds/clients/xdsclient" "google.golang.org/grpc/internal/xds/clusterspecifier" "google.golang.org/grpc/internal/xds/httpfilter" "google.golang.org/grpc/internal/xds/matcher" @@ -710,7 +712,7 @@ func (s) TestRDSGenerateRDSUpdateFromRouteConfiguration(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - gotUpdate, gotError := generateRDSUpdateFromRouteConfiguration(test.rc) + gotUpdate, gotError := generateRDSUpdateFromRouteConfiguration(nil, test.rc) if (gotError != nil) != test.wantError || !cmp.Equal(gotUpdate, test.wantUpdate, cmpopts.EquateEmpty(), cmp.Transformer("FilterConfig", func(fc httpfilter.FilterConfig) string { @@ -722,6 +724,95 @@ func (s) TestRDSGenerateRDSUpdateFromRouteConfiguration(t *testing.T) { } } +func (s) TestGenerateRDSUpdateFromRouteConfigurationWithAutoHostRewrite(t *testing.T) { + const ( + clusterName = "clusterName" + ldsTarget = "lds.target.good:1111" + ) + + buildRouteConfig := func() *v3routepb.RouteConfiguration { + return &v3routepb.RouteConfiguration{ + Name: "routeName", + VirtualHosts: []*v3routepb.VirtualHost{{ + Domains: []string{ldsTarget}, + Routes: []*v3routepb.Route{{ + Match: &v3routepb.RouteMatch{PathSpecifier: &v3routepb.RouteMatch_Prefix{Prefix: "/"}}, + Action: &v3routepb.Route_Route{ + Route: &v3routepb.RouteAction{ + ClusterSpecifier: &v3routepb.RouteAction_Cluster{Cluster: clusterName}, + HostRewriteSpecifier: &v3routepb.RouteAction_AutoHostRewrite{AutoHostRewrite: &wrapperspb.BoolValue{Value: true}}, + }, + }, + }}, + }}, + } + } + + tests := []struct { + name string + isTrusted bool // Corresponds to ServerConfig + envConfigRewrite bool // Corresponds to envconfig.XDSAuthorityRewrite + wantResult bool + }{ + { + name: "envConfigOn_Trusted", + isTrusted: true, + envConfigRewrite: true, + wantResult: true, + }, + { + name: "envConfigOff_Trusted", + isTrusted: true, + envConfigRewrite: false, + wantResult: false, + }, + { + name: "envConfigOn_Untrusted", + isTrusted: false, + envConfigRewrite: true, + wantResult: false, + }, + { + name: "envConfigOff_Untrusted", + isTrusted: false, + envConfigRewrite: false, + wantResult: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + testutils.SetEnvConfig(t, &envconfig.XDSAuthorityRewrite, test.envConfigRewrite) + + var serverFeature xdsclient.ServerFeature + if test.isTrusted { + serverFeature = xdsclient.ServerFeatureTrustedXDSServer + } + + opts := &xdsclient.DecodeOptions{ + ServerConfig: &xdsclient.ServerConfig{ + ServerFeature: serverFeature, + }, + } + + update, err := generateRDSUpdateFromRouteConfiguration(opts, buildRouteConfig()) + if err != nil { + t.Errorf("generateRDSUpdateFromRouteConfiguration() failed, got : %v, want: ", err) + } + + if len(update.VirtualHosts) == 0 || len(update.VirtualHosts[0].Routes) == 0 { + t.Errorf("Unexpected parsed routes from generateRDSUpdateFromRouteConfiguration(), got : 0, want: 1") + } + + got := update.VirtualHosts[0].Routes[0].AutoHostRewrite + + if got != test.wantResult { + t.Errorf("AutoHostRewrite = %v, want %v", got, test.wantResult) + } + }) + } +} + var configOfClusterSpecifierDoesntExist = &anypb.Any{ TypeUrl: "does.not.exist", Value: []byte{1, 2, 3}, @@ -874,7 +965,7 @@ func (s) TestUnmarshalRouteConfig(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - name, update, err := unmarshalRouteConfigResource(test.resource) + name, update, err := unmarshalRouteConfigResource(nil, test.resource) if (err != nil) != test.wantErr { t.Errorf("unmarshalRouteConfigResource(%s), got err: %v, wantErr: %v", pretty.ToJSON(test.resource), err, test.wantErr) } @@ -1505,7 +1596,7 @@ func (s) TestRoutesProtoToSlice(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, _, err := routesProtoToSlice(tt.routes, nil) + got, _, err := routesProtoToSlice(nil, tt.routes, nil) if (err != nil) != tt.wantErr { t.Fatalf("routesProtoToSlice() error = %v, wantErr %v", err, tt.wantErr) } From 8f184b4dcc234fbf2dc178f75669ef7e4b2740e6 Mon Sep 17 00:00:00 2001 From: Pranjali-2501 Date: Sat, 29 Nov 2025 21:33:05 +0000 Subject: [PATCH 2/3] resolving comments --- internal/envconfig/envconfig.go | 6 +- .../xds/xdsclient/xdsresource/filter_chain.go | 2 +- .../xdsresource/listener_resource_type.go | 4 +- .../xdsresource/route_config_resource_type.go | 2 +- .../xdsresource/unmarshal_eds_test.go | 156 ++++++++++++------ .../xdsclient/xdsresource/unmarshal_lds.go | 13 +- .../xdsresource/unmarshal_lds_test.go | 4 +- .../xdsclient/xdsresource/unmarshal_rds.go | 10 +- .../xdsresource/unmarshal_rds_test.go | 56 ++++--- 9 files changed, 154 insertions(+), 99 deletions(-) diff --git a/internal/envconfig/envconfig.go b/internal/envconfig/envconfig.go index 6874045a982c..6414ee4bbe27 100644 --- a/internal/envconfig/envconfig.go +++ b/internal/envconfig/envconfig.go @@ -78,9 +78,9 @@ var ( // - The DNS resolver is being used. EnableDefaultPortForProxyTarget = boolFromEnv("GRPC_EXPERIMENTAL_ENABLE_DEFAULT_PORT_FOR_PROXY_TARGET", true) - // XDSAuthorityRewrite is set if xDS authority rewriting is enabled, - // according to gRFC A81. It can be enabled by setting - // GRPC_EXPERIMENTAL_XDS_AUTHORITY_REWRITE to true. + // XDSAuthorityRewrite indicates whether xDS authority rewriting is enabled. + // This feature is defined in gRFC A81 and is enabled by setting the + // environment variable GRPC_EXPERIMENTAL_XDS_AUTHORITY_REWRITE to "true". XDSAuthorityRewrite = boolFromEnv("GRPC_EXPERIMENTAL_XDS_AUTHORITY_REWRITE", false) ) diff --git a/internal/xds/xdsclient/xdsresource/filter_chain.go b/internal/xds/xdsclient/xdsresource/filter_chain.go index fcb1b566a4a9..50b72e0de6b2 100644 --- a/internal/xds/xdsclient/xdsresource/filter_chain.go +++ b/internal/xds/xdsclient/xdsresource/filter_chain.go @@ -680,7 +680,7 @@ func processNetworkFilters(filters []*v3listenerpb.Filter) (*FilterChain, error) // server-side." - A36 // Can specify v3 here, as will never get to this function // if v2. - routeU, err := generateRDSUpdateFromRouteConfiguration(nil, hcm.GetRouteConfig()) + routeU, err := generateRDSUpdateFromRouteConfiguration(hcm.GetRouteConfig(), nil) if err != nil { return nil, fmt.Errorf("failed to parse inline RDS resp: %v", err) } diff --git a/internal/xds/xdsclient/xdsresource/listener_resource_type.go b/internal/xds/xdsclient/xdsresource/listener_resource_type.go index f4f69365abb5..2b9000fdf2b6 100644 --- a/internal/xds/xdsclient/xdsresource/listener_resource_type.go +++ b/internal/xds/xdsclient/xdsresource/listener_resource_type.go @@ -35,8 +35,8 @@ type listenerResourceDecoder struct { bootstrapConfig *bootstrap.Config } -func (d *listenerResourceDecoder) Decode(resource *xdsclient.AnyProto, _ xdsclient.DecodeOptions) (*xdsclient.DecodeResult, error) { - name, listener, err := unmarshalListenerResource(resource.ToAny()) +func (d *listenerResourceDecoder) Decode(resource *xdsclient.AnyProto, opts xdsclient.DecodeOptions) (*xdsclient.DecodeResult, error) { + name, listener, err := unmarshalListenerResource(resource.ToAny(), &opts) if name == "" { // Name is unset only when protobuf deserialization fails. return nil, err diff --git a/internal/xds/xdsclient/xdsresource/route_config_resource_type.go b/internal/xds/xdsclient/xdsresource/route_config_resource_type.go index 6e86829c8caa..1104fe9f2b4d 100644 --- a/internal/xds/xdsclient/xdsresource/route_config_resource_type.go +++ b/internal/xds/xdsclient/xdsresource/route_config_resource_type.go @@ -38,7 +38,7 @@ type routeConfigResourceDecoder struct { } func (d *routeConfigResourceDecoder) Decode(resource *xdsclient.AnyProto, opts xdsclient.DecodeOptions) (*xdsclient.DecodeResult, error) { - name, rc, err := unmarshalRouteConfigResource(&opts, resource.ToAny()) + name, rc, err := unmarshalRouteConfigResource(resource.ToAny(), &opts) if name == "" { // Name is unset only when protobuf deserialization fails. return nil, err diff --git a/internal/xds/xdsclient/xdsresource/unmarshal_eds_test.go b/internal/xds/xdsclient/xdsresource/unmarshal_eds_test.go index 421d270f1ec4..905cf8a20f26 100644 --- a/internal/xds/xdsclient/xdsresource/unmarshal_eds_test.go +++ b/internal/xds/xdsclient/xdsresource/unmarshal_eds_test.go @@ -93,12 +93,16 @@ func (s) TestEDSParseRespProto(t *testing.T) { name: "missing locality weight", m: func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 0, 1, []endpointOpts{{addrWithPort: "addr1:314"}}, &addLocalityOptions{ + endpoints1 := []endpointOpts{{addrWithPort: "addr1:314"}} + locOption1 := &addLocalityOptions{ Health: []v3corepb.HealthStatus{v3corepb.HealthStatus_HEALTHY}, - }) - clab0.addLocality("locality-2", 0, 0, []endpointOpts{{addrWithPort: "addr2:159"}}, &addLocalityOptions{ + } + clab0.addLocality("locality-1", 0, 1, endpoints1, locOption1) + endpoints2 := []endpointOpts{{addrWithPort: "addr2:159"}} + locOption2 := &addLocalityOptions{ Health: []v3corepb.HealthStatus{v3corepb.HealthStatus_HEALTHY}, - }) + } + clab0.addLocality("locality-2", 0, 0, endpoints2, locOption2) return clab0.Build() }(), want: EndpointsUpdate{}, @@ -130,14 +134,18 @@ func (s) TestEDSParseRespProto(t *testing.T) { name: "good", m: func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 1, []endpointOpts{{addrWithPort: "addr1:314", hostname: "addr1"}}, &addLocalityOptions{ + endpoints1 := []endpointOpts{{addrWithPort: "addr1:314", hostname: "addr1"}} + locOption1 := &addLocalityOptions{ Health: []v3corepb.HealthStatus{v3corepb.HealthStatus_UNHEALTHY}, Weight: []uint32{271}, - }) - clab0.addLocality("locality-2", 1, 0, []endpointOpts{{addrWithPort: "addr2:159", hostname: "addr2"}}, &addLocalityOptions{ + } + clab0.addLocality("locality-1", 1, 1, endpoints1, locOption1) + endpoints2 := []endpointOpts{{addrWithPort: "addr2:159", hostname: "addr2"}} + locOption2 := &addLocalityOptions{ Health: []v3corepb.HealthStatus{v3corepb.HealthStatus_DRAINING}, Weight: []uint32{828}, - }) + } + clab0.addLocality("locality-2", 1, 0, endpoints2, locOption2) return clab0.Build() }(), want: EndpointsUpdate{ @@ -173,15 +181,19 @@ func (s) TestEDSParseRespProto(t *testing.T) { name: "good duplicate locality with different priority", m: func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 1, []endpointOpts{{addrWithPort: "addr1:314", hostname: "addr1"}}, &addLocalityOptions{ + endpoints1 := []endpointOpts{{addrWithPort: "addr1:314", hostname: "addr1"}} + locOption1 := &addLocalityOptions{ Health: []v3corepb.HealthStatus{v3corepb.HealthStatus_UNHEALTHY}, Weight: []uint32{271}, - }) + } + clab0.addLocality("locality-1", 1, 1, endpoints1, locOption1) // Same locality name, but with different priority. - clab0.addLocality("locality-1", 1, 0, []endpointOpts{{addrWithPort: "addr2:159", hostname: "addr2"}}, &addLocalityOptions{ + endpoints2 := []endpointOpts{{addrWithPort: "addr2:159", hostname: "addr2"}} + locOption2 := &addLocalityOptions{ Health: []v3corepb.HealthStatus{v3corepb.HealthStatus_DRAINING}, Weight: []uint32{828}, - }) + } + clab0.addLocality("locality-1", 1, 0, endpoints2, locOption2) return clab0.Build() }(), want: EndpointsUpdate{ @@ -286,14 +298,18 @@ func (s) TestEDSParseRespProtoAdditionalAddrs(t *testing.T) { name: "multiple localities", m: func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 1, []endpointOpts{{addrWithPort: "addr1:997", additionalAddrWithPorts: []string{"addr1:1000"}}}, &addLocalityOptions{ + endpoints1 := []endpointOpts{{addrWithPort: "addr1:997", additionalAddrWithPorts: []string{"addr1:1000"}}} + locOption1 := &addLocalityOptions{ Health: []v3corepb.HealthStatus{v3corepb.HealthStatus_UNHEALTHY}, Weight: []uint32{271}, - }) - clab0.addLocality("locality-2", 1, 0, []endpointOpts{{addrWithPort: "addr2:998", additionalAddrWithPorts: []string{"addr2:1000"}}}, &addLocalityOptions{ + } + clab0.addLocality("locality-1", 1, 1, endpoints1, locOption1) + endpoints2 := []endpointOpts{{addrWithPort: "addr2:998", additionalAddrWithPorts: []string{"addr2:1000"}}} + locOption2 := &addLocalityOptions{ Health: []v3corepb.HealthStatus{v3corepb.HealthStatus_HEALTHY}, Weight: []uint32{828}, - }) + } + clab0.addLocality("locality-2", 1, 0, endpoints2, locOption2) return clab0.Build() }(), want: EndpointsUpdate{ @@ -470,14 +486,18 @@ func (s) TestUnmarshalEndpoints(t *testing.T) { testutils.SetEnvConfig(t, &envconfig.XDSHTTPConnectEnabled, true) var v3EndpointsAny = testutils.MarshalAny(t, func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 1, []endpointOpts{{addrWithPort: "addr1:314", hostname: "addr1"}}, &addLocalityOptions{ + endpoints1 := []endpointOpts{{addrWithPort: "addr1:314", hostname: "addr1"}} + locOption1 := &addLocalityOptions{ Health: []v3corepb.HealthStatus{v3corepb.HealthStatus_UNHEALTHY}, Weight: []uint32{271}, - }) - clab0.addLocality("locality-2", 1, 0, []endpointOpts{{addrWithPort: "addr2:159", hostname: "addr2"}}, &addLocalityOptions{ + } + clab0.addLocality("locality-1", 1, 1, endpoints1, locOption1) + endpoints2 := []endpointOpts{{addrWithPort: "addr2:159", hostname: "addr2"}} + locOption2 := &addLocalityOptions{ Health: []v3corepb.HealthStatus{v3corepb.HealthStatus_DRAINING}, Weight: []uint32{828}, - }) + } + clab0.addLocality("locality-2", 1, 0, endpoints2, locOption2) return clab0.Build() }()) @@ -608,7 +628,7 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOn(t *testing.T name: "typed_filter_metadata_in_endpoint", endpointProto: func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 0, []endpointOpts{{ + endpoints := []endpointOpts{{ addrWithPort: "addr1:314", metadata: &v3corepb.Metadata{ TypedFilterMetadata: map[string]*anypb.Any{ @@ -623,7 +643,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOn(t *testing.T }), }, }, - }}, nil) + }} + clab0.addLocality("locality-1", 1, 0, endpoints, nil) return clab0.Build() }(), wantEndpoint: EndpointsUpdate{ @@ -650,7 +671,7 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOn(t *testing.T name: "filter_metadata_in_endpoint", endpointProto: func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 0, []endpointOpts{{ + endpoints := []endpointOpts{{ addrWithPort: "addr1:314", metadata: &v3corepb.Metadata{ FilterMetadata: map[string]*structpb.Struct{ @@ -663,7 +684,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOn(t *testing.T }, }, }, - }}, nil) + }} + clab0.addLocality("locality-1", 1, 0, endpoints, nil) return clab0.Build() }(), wantEndpoint: EndpointsUpdate{ @@ -690,7 +712,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOn(t *testing.T name: "typed_filter_metadata_in_locality", endpointProto: func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 0, []endpointOpts{{addrWithPort: "addr1:314"}}, &addLocalityOptions{ + endpoints := []endpointOpts{{addrWithPort: "addr1:314"}} + locOption := &addLocalityOptions{ Metadata: &v3corepb.Metadata{ TypedFilterMetadata: map[string]*anypb.Any{ "test-key": testutils.MarshalAny(t, &v3corepb.Address{ @@ -704,7 +727,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOn(t *testing.T }), }, }, - }) + } + clab0.addLocality("locality-1", 1, 0, endpoints, locOption) return clab0.Build() }(), wantEndpoint: EndpointsUpdate{ @@ -731,7 +755,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOn(t *testing.T name: "filter_metadata_in_locality", endpointProto: func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 0, []endpointOpts{{addrWithPort: "addr1:314"}}, &addLocalityOptions{ + endpoints := []endpointOpts{{addrWithPort: "addr1:314"}} + locOption := &addLocalityOptions{ Metadata: &v3corepb.Metadata{ FilterMetadata: map[string]*structpb.Struct{ "test-key": { @@ -743,7 +768,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOn(t *testing.T }, }, }, - }) + } + clab0.addLocality("locality-1", 1, 0, endpoints, locOption) return clab0.Build() }(), wantEndpoint: EndpointsUpdate{ @@ -770,7 +796,7 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOn(t *testing.T name: "typed_filter_metadata_over_filter_metadata_in_endpoint", endpointProto: func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 0, []endpointOpts{{ + endpoints := []endpointOpts{{ addrWithPort: "addr1:314", metadata: &v3corepb.Metadata{ TypedFilterMetadata: map[string]*anypb.Any{ @@ -794,7 +820,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOn(t *testing.T }, }, }, - }}, nil) + }} + clab0.addLocality("locality-1", 1, 0, endpoints, nil) return clab0.Build() }(), wantEndpoint: EndpointsUpdate{ @@ -821,7 +848,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOn(t *testing.T name: "typed_filter_metadata_over_filter_metadata_in_locality", endpointProto: func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 0, []endpointOpts{{addrWithPort: "addr1:314"}}, &addLocalityOptions{ + endpoints := []endpointOpts{{addrWithPort: "addr1:314"}} + locOption := &addLocalityOptions{ Metadata: &v3corepb.Metadata{ TypedFilterMetadata: map[string]*anypb.Any{ "test-key": testutils.MarshalAny(t, &v3corepb.Address{ @@ -844,7 +872,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOn(t *testing.T }, }, }, - }) + } + clab0.addLocality("locality-1", 1, 0, endpoints, locOption) return clab0.Build() }(), wantEndpoint: EndpointsUpdate{ @@ -871,7 +900,7 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOn(t *testing.T name: "both_filter_and_typed_filter_metadata_in_endpoint", endpointProto: func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 0, []endpointOpts{{ + endpoints := []endpointOpts{{ addrWithPort: "addr1:314", metadata: &v3corepb.Metadata{ TypedFilterMetadata: map[string]*anypb.Any{ @@ -895,7 +924,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOn(t *testing.T }, }, }, - }}, nil) + }} + clab0.addLocality("locality-1", 1, 0, endpoints, nil) return clab0.Build() }(), wantEndpoint: EndpointsUpdate{ @@ -925,7 +955,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOn(t *testing.T name: "both_filter_and_typed_filter_metadata_in_locality", endpointProto: func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 0, []endpointOpts{{addrWithPort: "addr1:314"}}, &addLocalityOptions{ + endpoints := []endpointOpts{{addrWithPort: "addr1:314"}} + locOption := &addLocalityOptions{ Metadata: &v3corepb.Metadata{ TypedFilterMetadata: map[string]*anypb.Any{ "test-key": testutils.MarshalAny(t, &v3corepb.Address{ @@ -948,7 +979,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOn(t *testing.T }, }, }, - }) + } + clab0.addLocality("locality-1", 1, 0, endpoints, locOption) return clab0.Build() }(), wantEndpoint: EndpointsUpdate{ @@ -1001,7 +1033,7 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOff(t *testing. name: "typed_filter_metadata_in_endpoint", endpointProto: func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 0, []endpointOpts{{ + endpoints := []endpointOpts{{ addrWithPort: "addr1:314", metadata: &v3corepb.Metadata{ TypedFilterMetadata: map[string]*anypb.Any{ @@ -1016,7 +1048,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOff(t *testing. }), }, }, - }}, nil) + }} + clab0.addLocality("locality-1", 1, 0, endpoints, nil) return clab0.Build() }(), wantEndpoint: EndpointsUpdate{ @@ -1038,7 +1071,7 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOff(t *testing. name: "filter_metadata_in_endpoint", endpointProto: func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 0, []endpointOpts{{ + endpoints := []endpointOpts{{ addrWithPort: "addr1:314", metadata: &v3corepb.Metadata{ FilterMetadata: map[string]*structpb.Struct{ @@ -1051,7 +1084,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOff(t *testing. }, }, }, - }}, nil) + }} + clab0.addLocality("locality-1", 1, 0, endpoints, nil) return clab0.Build() }(), wantEndpoint: EndpointsUpdate{ @@ -1073,7 +1107,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOff(t *testing. name: "typed_filter_metadata_in_locality", endpointProto: func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 0, []endpointOpts{{addrWithPort: "addr1:314"}}, &addLocalityOptions{ + endpoints := []endpointOpts{{addrWithPort: "addr1:314"}} + locOption := &addLocalityOptions{ Metadata: &v3corepb.Metadata{ TypedFilterMetadata: map[string]*anypb.Any{ "test-key": testutils.MarshalAny(t, &v3corepb.Address{ @@ -1087,7 +1122,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOff(t *testing. }), }, }, - }) + } + clab0.addLocality("locality-1", 1, 0, endpoints, locOption) return clab0.Build() }(), wantEndpoint: EndpointsUpdate{ @@ -1109,7 +1145,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOff(t *testing. name: "filter_metadata_in_locality", endpointProto: func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 0, []endpointOpts{{addrWithPort: "addr1:314"}}, &addLocalityOptions{ + endpoints := []endpointOpts{{addrWithPort: "addr1:314"}} + locOption := &addLocalityOptions{ Metadata: &v3corepb.Metadata{ FilterMetadata: map[string]*structpb.Struct{ "test-key": { @@ -1121,7 +1158,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOff(t *testing. }, }, }, - }) + } + clab0.addLocality("locality-1", 1, 0, endpoints, locOption) return clab0.Build() }(), wantEndpoint: EndpointsUpdate{ @@ -1143,7 +1181,7 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOff(t *testing. name: "both_filter_and_typed_filter_metadata_in_endpoint", endpointProto: func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 0, []endpointOpts{{ + endpoints := []endpointOpts{{ addrWithPort: "addr1:314", metadata: &v3corepb.Metadata{ TypedFilterMetadata: map[string]*anypb.Any{ @@ -1167,7 +1205,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOff(t *testing. }, }, }, - }}, nil) + }} + clab0.addLocality("locality-1", 1, 0, endpoints, nil) return clab0.Build() }(), wantEndpoint: EndpointsUpdate{ @@ -1189,7 +1228,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOff(t *testing. name: "both_filter_and_typed_filter_metadata_in_locality", endpointProto: func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 0, []endpointOpts{{addrWithPort: "addr1:314"}}, &addLocalityOptions{ + endpoints := []endpointOpts{{addrWithPort: "addr1:314"}} + locOption := &addLocalityOptions{ Metadata: &v3corepb.Metadata{ TypedFilterMetadata: map[string]*anypb.Any{ "test-key": testutils.MarshalAny(t, &v3corepb.Address{ @@ -1212,7 +1252,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOff(t *testing. }, }, }, - }) + } + clab0.addLocality("locality-1", 1, 0, endpoints, locOption) return clab0.Build() }(), wantEndpoint: EndpointsUpdate{ @@ -1234,7 +1275,7 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOff(t *testing. name: "converter_failure_is_not_triggerred", endpointProto: func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 0, []endpointOpts{{ + endpoints := []endpointOpts{{ addrWithPort: "addr1:314", metadata: &v3corepb.Metadata{ TypedFilterMetadata: map[string]*anypb.Any{ @@ -1247,7 +1288,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOff(t *testing. }), }, }, - }}, &addLocalityOptions{ + }} + locOption := &addLocalityOptions{ Metadata: &v3corepb.Metadata{ TypedFilterMetadata: map[string]*anypb.Any{ "envoy.http11_proxy_transport_socket.proxy_address": testutils.MarshalAny(t, &v3corepb.Address{ @@ -1259,7 +1301,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_EnvVarOff(t *testing. }), }, }, - }) + } + clab0.addLocality("locality-1", 1, 0, endpoints, locOption) return clab0.Build() }(), wantEndpoint: EndpointsUpdate{ @@ -1303,7 +1346,7 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_ConverterFailure(t *t name: "converter_failure_in_endpoint", endpointProto: func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 0, []endpointOpts{{ + endpoints := []endpointOpts{{ addrWithPort: "addr1:314", metadata: &v3corepb.Metadata{ TypedFilterMetadata: map[string]*anypb.Any{ @@ -1316,7 +1359,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_ConverterFailure(t *t }), }, }, - }}, nil) + }} + clab0.addLocality("locality-1", 1, 0, endpoints, nil) return clab0.Build() }(), }, @@ -1324,7 +1368,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_ConverterFailure(t *t name: "converter_failure_in_locality", endpointProto: func() *v3endpointpb.ClusterLoadAssignment { clab0 := newClaBuilder("test", nil) - clab0.addLocality("locality-1", 1, 0, []endpointOpts{{addrWithPort: "addr1:314"}}, &addLocalityOptions{ + endpoints := []endpointOpts{{addrWithPort: "addr1:314"}} + locOption := &addLocalityOptions{ Metadata: &v3corepb.Metadata{ TypedFilterMetadata: map[string]*anypb.Any{ "envoy.http11_proxy_transport_socket.proxy_address": testutils.MarshalAny(t, &v3corepb.Address{ @@ -1336,7 +1381,8 @@ func (s) TestEDSParseRespProto_HTTP_Connect_CustomMetadata_ConverterFailure(t *t }), }, }, - }) + } + clab0.addLocality("locality-1", 1, 0, endpoints, locOption) return clab0.Build() }(), }, diff --git a/internal/xds/xdsclient/xdsresource/unmarshal_lds.go b/internal/xds/xdsclient/xdsresource/unmarshal_lds.go index 4c38894036f2..604c086ba428 100644 --- a/internal/xds/xdsclient/xdsresource/unmarshal_lds.go +++ b/internal/xds/xdsclient/xdsresource/unmarshal_lds.go @@ -27,12 +27,13 @@ import ( v3listenerpb "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" v3routepb "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" v3httppb "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" + "google.golang.org/grpc/internal/xds/clients/xdsclient" "google.golang.org/grpc/internal/xds/httpfilter" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" ) -func unmarshalListenerResource(r *anypb.Any) (string, ListenerUpdate, error) { +func unmarshalListenerResource(r *anypb.Any, opts *xdsclient.DecodeOptions) (string, ListenerUpdate, error) { r, err := UnwrapResource(r) if err != nil { return "", ListenerUpdate{}, fmt.Errorf("failed to unwrap resource: %v", err) @@ -46,7 +47,7 @@ func unmarshalListenerResource(r *anypb.Any) (string, ListenerUpdate, error) { return "", ListenerUpdate{}, fmt.Errorf("failed to unmarshal resource: %v", err) } - lu, err := processListener(lis) + lu, err := processListener(lis, opts) if err != nil { return lis.GetName(), ListenerUpdate{}, err } @@ -54,16 +55,16 @@ func unmarshalListenerResource(r *anypb.Any) (string, ListenerUpdate, error) { return lis.GetName(), *lu, nil } -func processListener(lis *v3listenerpb.Listener) (*ListenerUpdate, error) { +func processListener(lis *v3listenerpb.Listener, opts *xdsclient.DecodeOptions) (*ListenerUpdate, error) { if lis.GetApiListener() != nil { - return processClientSideListener(lis) + return processClientSideListener(lis, opts) } return processServerSideListener(lis) } // processClientSideListener checks if the provided Listener proto meets // the expected criteria. If so, it returns a non-empty routeConfigName. -func processClientSideListener(lis *v3listenerpb.Listener) (*ListenerUpdate, error) { +func processClientSideListener(lis *v3listenerpb.Listener, opts *xdsclient.DecodeOptions) (*ListenerUpdate, error) { update := &ListenerUpdate{} apiLisAny := lis.GetApiListener().GetApiListener() @@ -95,7 +96,7 @@ func processClientSideListener(lis *v3listenerpb.Listener) (*ListenerUpdate, err } update.RouteConfigName = name case *v3httppb.HttpConnectionManager_RouteConfig: - routeU, err := generateRDSUpdateFromRouteConfiguration(nil, apiLis.GetRouteConfig()) + routeU, err := generateRDSUpdateFromRouteConfiguration(apiLis.GetRouteConfig(), opts) if err != nil { return nil, fmt.Errorf("failed to parse inline RDS resp: %v", err) } diff --git a/internal/xds/xdsclient/xdsresource/unmarshal_lds_test.go b/internal/xds/xdsclient/xdsresource/unmarshal_lds_test.go index 2560365d09e2..24b0e7f0728b 100644 --- a/internal/xds/xdsclient/xdsresource/unmarshal_lds_test.go +++ b/internal/xds/xdsclient/xdsresource/unmarshal_lds_test.go @@ -580,7 +580,7 @@ func (s) TestUnmarshalListener_ClientSide(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - name, update, err := unmarshalListenerResource(test.resource) + name, update, err := unmarshalListenerResource(test.resource, nil) if (err != nil) != test.wantErr { t.Errorf("unmarshalListenerResource(%s), got err: %v, wantErr: %v", pretty.ToJSON(test.resource), err, test.wantErr) } @@ -1707,7 +1707,7 @@ func (s) TestUnmarshalListener_ServerSide(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - name, update, err := unmarshalListenerResource(test.resource) + name, update, err := unmarshalListenerResource(test.resource, nil) if err != nil && !strings.Contains(err.Error(), test.wantErr) { t.Errorf("unmarshalListenerResource(%s) = %v wantErr: %q", pretty.ToJSON(test.resource), err, test.wantErr) } diff --git a/internal/xds/xdsclient/xdsresource/unmarshal_rds.go b/internal/xds/xdsclient/xdsresource/unmarshal_rds.go index aaba42e80593..d988b4e77f9a 100644 --- a/internal/xds/xdsclient/xdsresource/unmarshal_rds.go +++ b/internal/xds/xdsclient/xdsresource/unmarshal_rds.go @@ -36,7 +36,7 @@ import ( v3typepb "github.com/envoyproxy/go-control-plane/envoy/type/v3" ) -func unmarshalRouteConfigResource(opts *xdsclient.DecodeOptions, r *anypb.Any) (string, RouteConfigUpdate, error) { +func unmarshalRouteConfigResource(r *anypb.Any, opts *xdsclient.DecodeOptions) (string, RouteConfigUpdate, error) { r, err := UnwrapResource(r) if err != nil { return "", RouteConfigUpdate{}, fmt.Errorf("failed to unwrap resource: %v", err) @@ -50,7 +50,7 @@ func unmarshalRouteConfigResource(opts *xdsclient.DecodeOptions, r *anypb.Any) ( return "", RouteConfigUpdate{}, fmt.Errorf("failed to unmarshal resource: %v", err) } - u, err := generateRDSUpdateFromRouteConfiguration(opts, rc) + u, err := generateRDSUpdateFromRouteConfiguration(rc, opts) if err != nil { return rc.GetName(), RouteConfigUpdate{}, err } @@ -74,7 +74,7 @@ func unmarshalRouteConfigResource(opts *xdsclient.DecodeOptions, r *anypb.Any) ( // field must be empty and whose route field must be set. Inside that route // message, the cluster field will contain the clusterName or weighted clusters // we are looking for. -func generateRDSUpdateFromRouteConfiguration(opts *xdsclient.DecodeOptions, rc *v3routepb.RouteConfiguration) (RouteConfigUpdate, error) { +func generateRDSUpdateFromRouteConfiguration(rc *v3routepb.RouteConfiguration, opts *xdsclient.DecodeOptions) (RouteConfigUpdate, error) { vhs := make([]*VirtualHost, 0, len(rc.GetVirtualHosts())) csps, err := processClusterSpecifierPlugins(rc.ClusterSpecifierPlugins) if err != nil { @@ -85,7 +85,7 @@ func generateRDSUpdateFromRouteConfiguration(opts *xdsclient.DecodeOptions, rc * // ignored and not emitted by the xdsclient. var cspNames = make(map[string]bool) for _, vh := range rc.GetVirtualHosts() { - routes, cspNs, err := routesProtoToSlice(opts, vh.Routes, csps) + routes, cspNs, err := routesProtoToSlice(vh.Routes, csps, opts) if err != nil { return RouteConfigUpdate{}, fmt.Errorf("received route is invalid: %v", err) } @@ -208,7 +208,7 @@ func generateRetryConfig(rp *v3routepb.RetryPolicy) (*RetryConfig, error) { return cfg, nil } -func routesProtoToSlice(opts *xdsclient.DecodeOptions, routes []*v3routepb.Route, csps map[string]clusterspecifier.BalancerConfig) ([]*Route, map[string]bool, error) { +func routesProtoToSlice(routes []*v3routepb.Route, csps map[string]clusterspecifier.BalancerConfig, opts *xdsclient.DecodeOptions) ([]*Route, map[string]bool, error) { var routesRet []*Route var cspNames = make(map[string]bool) for _, r := range routes { diff --git a/internal/xds/xdsclient/xdsresource/unmarshal_rds_test.go b/internal/xds/xdsclient/xdsresource/unmarshal_rds_test.go index a34b405ec245..c146f45f5c13 100644 --- a/internal/xds/xdsclient/xdsresource/unmarshal_rds_test.go +++ b/internal/xds/xdsclient/xdsresource/unmarshal_rds_test.go @@ -712,7 +712,7 @@ func (s) TestRDSGenerateRDSUpdateFromRouteConfiguration(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - gotUpdate, gotError := generateRDSUpdateFromRouteConfiguration(nil, test.rc) + gotUpdate, gotError := generateRDSUpdateFromRouteConfiguration(test.rc, nil) if (gotError != nil) != test.wantError || !cmp.Equal(gotUpdate, test.wantUpdate, cmpopts.EquateEmpty(), cmp.Transformer("FilterConfig", func(fc httpfilter.FilterConfig) string { @@ -730,52 +730,46 @@ func (s) TestGenerateRDSUpdateFromRouteConfigurationWithAutoHostRewrite(t *testi ldsTarget = "lds.target.good:1111" ) - buildRouteConfig := func() *v3routepb.RouteConfiguration { - return &v3routepb.RouteConfiguration{ - Name: "routeName", - VirtualHosts: []*v3routepb.VirtualHost{{ - Domains: []string{ldsTarget}, - Routes: []*v3routepb.Route{{ - Match: &v3routepb.RouteMatch{PathSpecifier: &v3routepb.RouteMatch_Prefix{Prefix: "/"}}, - Action: &v3routepb.Route_Route{ - Route: &v3routepb.RouteAction{ - ClusterSpecifier: &v3routepb.RouteAction_Cluster{Cluster: clusterName}, - HostRewriteSpecifier: &v3routepb.RouteAction_AutoHostRewrite{AutoHostRewrite: &wrapperspb.BoolValue{Value: true}}, - }, - }, - }}, - }}, - } - } - tests := []struct { name string isTrusted bool // Corresponds to ServerConfig envConfigRewrite bool // Corresponds to envconfig.XDSAuthorityRewrite + autoHostRewrite bool wantResult bool }{ { name: "envConfigOn_Trusted", isTrusted: true, envConfigRewrite: true, + autoHostRewrite: true, wantResult: true, }, + { + name: "envConfigOn_Trusted_AutoHostRewriteFalse", + isTrusted: true, + envConfigRewrite: true, + autoHostRewrite: false, + wantResult: false, + }, { name: "envConfigOff_Trusted", isTrusted: true, envConfigRewrite: false, + autoHostRewrite: true, wantResult: false, }, { name: "envConfigOn_Untrusted", isTrusted: false, envConfigRewrite: true, + autoHostRewrite: false, wantResult: false, }, { name: "envConfigOff_Untrusted", isTrusted: false, envConfigRewrite: false, + autoHostRewrite: true, wantResult: false, }, } @@ -795,17 +789,31 @@ func (s) TestGenerateRDSUpdateFromRouteConfigurationWithAutoHostRewrite(t *testi }, } - update, err := generateRDSUpdateFromRouteConfiguration(opts, buildRouteConfig()) + routeConfig := &v3routepb.RouteConfiguration{ + Name: "routeName", + VirtualHosts: []*v3routepb.VirtualHost{{ + Domains: []string{ldsTarget}, + Routes: []*v3routepb.Route{{ + Match: &v3routepb.RouteMatch{PathSpecifier: &v3routepb.RouteMatch_Prefix{Prefix: "/"}}, + Action: &v3routepb.Route_Route{ + Route: &v3routepb.RouteAction{ + ClusterSpecifier: &v3routepb.RouteAction_Cluster{Cluster: clusterName}, + HostRewriteSpecifier: &v3routepb.RouteAction_AutoHostRewrite{AutoHostRewrite: &wrapperspb.BoolValue{Value: test.autoHostRewrite}}, + }, + }, + }}, + }}, + } + + update, err := generateRDSUpdateFromRouteConfiguration(routeConfig, opts) if err != nil { t.Errorf("generateRDSUpdateFromRouteConfiguration() failed, got : %v, want: ", err) } - if len(update.VirtualHosts) == 0 || len(update.VirtualHosts[0].Routes) == 0 { t.Errorf("Unexpected parsed routes from generateRDSUpdateFromRouteConfiguration(), got : 0, want: 1") } got := update.VirtualHosts[0].Routes[0].AutoHostRewrite - if got != test.wantResult { t.Errorf("AutoHostRewrite = %v, want %v", got, test.wantResult) } @@ -965,7 +973,7 @@ func (s) TestUnmarshalRouteConfig(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - name, update, err := unmarshalRouteConfigResource(nil, test.resource) + name, update, err := unmarshalRouteConfigResource(test.resource, nil) if (err != nil) != test.wantErr { t.Errorf("unmarshalRouteConfigResource(%s), got err: %v, wantErr: %v", pretty.ToJSON(test.resource), err, test.wantErr) } @@ -1596,7 +1604,7 @@ func (s) TestRoutesProtoToSlice(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, _, err := routesProtoToSlice(nil, tt.routes, nil) + got, _, err := routesProtoToSlice(tt.routes, nil, nil) if (err != nil) != tt.wantErr { t.Fatalf("routesProtoToSlice() error = %v, wantErr %v", err, tt.wantErr) } From d8f997f58d698bbbd75a970402eb97ace91b9dba Mon Sep 17 00:00:00 2001 From: Pranjali-2501 Date: Mon, 1 Dec 2025 16:05:01 +0000 Subject: [PATCH 3/3] resolving nits --- .../xdsresource/unmarshal_rds_test.go | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/internal/xds/xdsclient/xdsresource/unmarshal_rds_test.go b/internal/xds/xdsclient/xdsresource/unmarshal_rds_test.go index c146f45f5c13..8c04dbb2b8ce 100644 --- a/internal/xds/xdsclient/xdsresource/unmarshal_rds_test.go +++ b/internal/xds/xdsclient/xdsresource/unmarshal_rds_test.go @@ -732,42 +732,40 @@ func (s) TestGenerateRDSUpdateFromRouteConfigurationWithAutoHostRewrite(t *testi tests := []struct { name string - isTrusted bool // Corresponds to ServerConfig - envConfigRewrite bool // Corresponds to envconfig.XDSAuthorityRewrite + isTrusted xdsclient.ServerFeature // Corresponds to ServerConfig + envConfigRewrite bool // Corresponds to envconfig.XDSAuthorityRewrite autoHostRewrite bool wantResult bool }{ { name: "envConfigOn_Trusted", - isTrusted: true, + isTrusted: xdsclient.ServerFeatureTrustedXDSServer, envConfigRewrite: true, autoHostRewrite: true, wantResult: true, }, { name: "envConfigOn_Trusted_AutoHostRewriteFalse", - isTrusted: true, + isTrusted: xdsclient.ServerFeatureTrustedXDSServer, envConfigRewrite: true, autoHostRewrite: false, wantResult: false, }, { name: "envConfigOff_Trusted", - isTrusted: true, + isTrusted: xdsclient.ServerFeatureTrustedXDSServer, envConfigRewrite: false, autoHostRewrite: true, wantResult: false, }, { name: "envConfigOn_Untrusted", - isTrusted: false, envConfigRewrite: true, autoHostRewrite: false, wantResult: false, }, { name: "envConfigOff_Untrusted", - isTrusted: false, envConfigRewrite: false, autoHostRewrite: true, wantResult: false, @@ -778,14 +776,9 @@ func (s) TestGenerateRDSUpdateFromRouteConfigurationWithAutoHostRewrite(t *testi t.Run(test.name, func(t *testing.T) { testutils.SetEnvConfig(t, &envconfig.XDSAuthorityRewrite, test.envConfigRewrite) - var serverFeature xdsclient.ServerFeature - if test.isTrusted { - serverFeature = xdsclient.ServerFeatureTrustedXDSServer - } - opts := &xdsclient.DecodeOptions{ ServerConfig: &xdsclient.ServerConfig{ - ServerFeature: serverFeature, + ServerFeature: test.isTrusted, }, } @@ -813,9 +806,8 @@ func (s) TestGenerateRDSUpdateFromRouteConfigurationWithAutoHostRewrite(t *testi t.Errorf("Unexpected parsed routes from generateRDSUpdateFromRouteConfiguration(), got : 0, want: 1") } - got := update.VirtualHosts[0].Routes[0].AutoHostRewrite - if got != test.wantResult { - t.Errorf("AutoHostRewrite = %v, want %v", got, test.wantResult) + if update.VirtualHosts[0].Routes[0].AutoHostRewrite != test.wantResult { + t.Errorf("AutoHostRewrite = %v, want %v", update.VirtualHosts[0].Routes[0].AutoHostRewrite, test.wantResult) } }) }