diff --git a/agent/xds/routes_test.go b/agent/xds/routes_test.go index e2f7d73b5e..782ec7a37f 100644 --- a/agent/xds/routes_test.go +++ b/agent/xds/routes_test.go @@ -262,6 +262,77 @@ func TestRoutesFromSnapshot(t *testing.T) { // TODO(proxystate): terminating gateway will come at a later time alsoRunTestForV2: false, }, + { + name: "api-gateway-with-multiple-hostnames", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotAPIGateway( + t, + "default", + nil, + func(entry *structs.APIGatewayConfigEntry, bound *structs.BoundAPIGatewayConfigEntry) { + entry.Listeners = []structs.APIGatewayListener{ + { + Name: "http", + Protocol: structs.ListenerProtocolHTTP, + Port: 8080, + Hostname: "*.example.com", + }, + } + bound.Listeners = []structs.BoundAPIGatewayListener{ + { + Name: "http", + Routes: []structs.ResourceReference{ + {Kind: structs.HTTPRoute, Name: "backend-route"}, + {Kind: structs.HTTPRoute, Name: "frontend-route"}, + {Kind: structs.HTTPRoute, Name: "generic-route"}, + }, + }, + } + }, + []structs.BoundRoute{ + &structs.HTTPRouteConfigEntry{ + Kind: structs.HTTPRoute, + Name: "backend-route", + Hostnames: []string{"backend.example.com"}, + Parents: []structs.ResourceReference{{Kind: structs.APIGateway, Name: "api-gateway"}}, + Rules: []structs.HTTPRouteRule{ + {Services: []structs.HTTPService{{Name: "backend"}}}, + }, + }, + &structs.HTTPRouteConfigEntry{ + Kind: structs.HTTPRoute, + Name: "frontend-route", + Hostnames: []string{"frontend.example.com"}, + Parents: []structs.ResourceReference{{Kind: structs.APIGateway, Name: "api-gateway"}}, + Rules: []structs.HTTPRouteRule{ + {Services: []structs.HTTPService{{Name: "frontend"}}}, + }, + }, + &structs.HTTPRouteConfigEntry{ + Kind: structs.HTTPRoute, + Name: "generic-route", + Parents: []structs.ResourceReference{{Kind: structs.APIGateway, Name: "api-gateway"}}, + Rules: []structs.HTTPRouteRule{ + { + Matches: []structs.HTTPMatch{ + {Path: structs.HTTPPathMatch{Match: structs.HTTPPathMatchPrefix, Value: "/frontend"}}, + }, + Services: []structs.HTTPService{{Name: "frontend"}}, + }, + { + Matches: []structs.HTTPMatch{ + {Path: structs.HTTPPathMatch{Match: structs.HTTPPathMatchPrefix, Value: "/backend"}}, + }, + Services: []structs.HTTPService{{Name: "backend"}}, + }, + }, + }, + }, + nil, + nil, + ) + }, + }, } tests = append(tests, makeRouteDiscoChainTests(false)...) diff --git a/agent/xds/testdata/routes/api-gateway-with-multiple-hostnames.envoy-1-24-x.golden b/agent/xds/testdata/routes/api-gateway-with-multiple-hostnames.envoy-1-24-x.golden new file mode 100644 index 0000000000..9e96457f3c --- /dev/null +++ b/agent/xds/testdata/routes/api-gateway-with-multiple-hostnames.envoy-1-24-x.golden @@ -0,0 +1,87 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "validateClusters": true, + "virtualHosts": [ + { + "domains": [ + "backend.example.com", + "backend.example.com:8080" + ], + "name": "api-gateway-http-5a84e719", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "backend.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "validateClusters": true, + "virtualHosts": [ + { + "domains": [ + "frontend.example.com", + "frontend.example.com:8080" + ], + "name": "api-gateway-http-54620b06", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "frontend.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "validateClusters": true, + "virtualHosts": [ + { + "domains": [ + "*.example.com", + "*.example.com:8080" + ], + "name": "api-gateway-http-aa289ce2", + "routes": [ + { + "match": { + "prefix": "/frontend" + }, + "route": { + "cluster": "frontend.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "prefix": "/backend" + }, + "route": { + "cluster": "backend.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/api-gateway-with-multiple-hostnames.envoy-1-25-x.golden b/agent/xds/testdata/routes/api-gateway-with-multiple-hostnames.envoy-1-25-x.golden new file mode 100644 index 0000000000..9e96457f3c --- /dev/null +++ b/agent/xds/testdata/routes/api-gateway-with-multiple-hostnames.envoy-1-25-x.golden @@ -0,0 +1,87 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "validateClusters": true, + "virtualHosts": [ + { + "domains": [ + "backend.example.com", + "backend.example.com:8080" + ], + "name": "api-gateway-http-5a84e719", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "backend.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "validateClusters": true, + "virtualHosts": [ + { + "domains": [ + "frontend.example.com", + "frontend.example.com:8080" + ], + "name": "api-gateway-http-54620b06", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "frontend.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "validateClusters": true, + "virtualHosts": [ + { + "domains": [ + "*.example.com", + "*.example.com:8080" + ], + "name": "api-gateway-http-aa289ce2", + "routes": [ + { + "match": { + "prefix": "/frontend" + }, + "route": { + "cluster": "frontend.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "prefix": "/backend" + }, + "route": { + "cluster": "backend.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/api-gateway-with-multiple-hostnames.envoy-1-26-x.golden b/agent/xds/testdata/routes/api-gateway-with-multiple-hostnames.envoy-1-26-x.golden new file mode 100644 index 0000000000..9e96457f3c --- /dev/null +++ b/agent/xds/testdata/routes/api-gateway-with-multiple-hostnames.envoy-1-26-x.golden @@ -0,0 +1,87 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "validateClusters": true, + "virtualHosts": [ + { + "domains": [ + "backend.example.com", + "backend.example.com:8080" + ], + "name": "api-gateway-http-5a84e719", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "backend.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "validateClusters": true, + "virtualHosts": [ + { + "domains": [ + "frontend.example.com", + "frontend.example.com:8080" + ], + "name": "api-gateway-http-54620b06", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "frontend.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "validateClusters": true, + "virtualHosts": [ + { + "domains": [ + "*.example.com", + "*.example.com:8080" + ], + "name": "api-gateway-http-aa289ce2", + "routes": [ + { + "match": { + "prefix": "/frontend" + }, + "route": { + "cluster": "frontend.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "prefix": "/backend" + }, + "route": { + "cluster": "backend.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/routes/api-gateway-with-multiple-hostnames.latest.golden b/agent/xds/testdata/routes/api-gateway-with-multiple-hostnames.latest.golden new file mode 100644 index 0000000000..7634114f54 --- /dev/null +++ b/agent/xds/testdata/routes/api-gateway-with-multiple-hostnames.latest.golden @@ -0,0 +1,87 @@ +{ + "nonce": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "validateClusters": true, + "virtualHosts": [ + { + "domains": [ + "frontend.example.com", + "frontend.example.com:8080" + ], + "name": "api-gateway-http-54620b06", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "frontend.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "validateClusters": true, + "virtualHosts": [ + { + "domains": [ + "*.example.com", + "*.example.com:8080" + ], + "name": "api-gateway-http-aa289ce2", + "routes": [ + { + "match": { + "prefix": "/frontend" + }, + "route": { + "cluster": "frontend.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + }, + { + "match": { + "prefix": "/backend" + }, + "route": { + "cluster": "backend.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "validateClusters": true, + "virtualHosts": [ + { + "domains": [ + "backend.example.com", + "backend.example.com:8080" + ], + "name": "api-gateway-http-5a84e719", + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "backend.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "versionInfo": "00000001" +} \ No newline at end of file