diff --git a/api/v1alpha1/ext_proc_types.go b/api/v1alpha1/ext_proc_types.go index 88da0123c0..95893d3c61 100644 --- a/api/v1alpha1/ext_proc_types.go +++ b/api/v1alpha1/ext_proc_types.go @@ -9,7 +9,7 @@ import ( gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" ) -// +kubebuilder:validation:Enum=Streamed;Buffered;BufferedPartial +// +kubebuilder:validation:Enum=Streamed;Buffered;BufferedPartial;FullDuplexStreamed type ExtProcBodyProcessingMode string const ( diff --git a/charts/gateway-addons-helm/dashboards/global-ratelimit.json b/charts/gateway-addons-helm/dashboards/global-ratelimit.json index 3242aa62b7..62c88ea163 100644 --- a/charts/gateway-addons-helm/dashboards/global-ratelimit.json +++ b/charts/gateway-addons-helm/dashboards/global-ratelimit.json @@ -38,7 +38,7 @@ { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "description": "The fraction of this program's available CPU time used by the GC since the program started.", "fieldConfig": { @@ -122,7 +122,7 @@ { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "disableTextWrap": false, "editorMode": "code", @@ -145,7 +145,7 @@ { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "description": "Resident memory size", "fieldConfig": { @@ -194,7 +194,7 @@ { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "disableTextWrap": false, "editorMode": "code", @@ -216,7 +216,7 @@ { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "description": "Virtual memory size", "fieldConfig": { @@ -266,7 +266,7 @@ { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "disableTextWrap": false, "editorMode": "code", @@ -288,7 +288,7 @@ { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "description": "Number of ratelimit rule hits in total", "fieldConfig": { @@ -341,7 +341,7 @@ { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "disableTextWrap": false, "editorMode": "builder", @@ -363,7 +363,7 @@ { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "description": "Number of rule hits over the NearLimit ratio threshold (currently 80%) but under the threshold rate.", "fieldConfig": { @@ -416,7 +416,7 @@ { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "disableTextWrap": false, "editorMode": "builder", @@ -438,7 +438,7 @@ { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "description": "Number of rule hits exceeding the threshold rate", "fieldConfig": { @@ -491,7 +491,7 @@ { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "disableTextWrap": false, "editorMode": "builder", @@ -522,7 +522,7 @@ "current": { "selected": false, "text": "Prometheus", - "value": "PBFA97CFB590B2093" + "value": "$datasource" }, "hide": 0, "includeAll": false, diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml index 01cb6663b1..7e8fa5d33c 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml @@ -1003,6 +1003,7 @@ spec: - Streamed - Buffered - BufferedPartial + - FullDuplexStreamed type: string type: object response: @@ -1026,6 +1027,7 @@ spec: - Streamed - Buffered - BufferedPartial + - FullDuplexStreamed type: string type: object type: object diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml index fb4f8bc752..d49a6046d2 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml @@ -1002,6 +1002,7 @@ spec: - Streamed - Buffered - BufferedPartial + - FullDuplexStreamed type: string type: object response: @@ -1025,6 +1026,7 @@ spec: - Streamed - Buffered - BufferedPartial + - FullDuplexStreamed type: string type: object type: object diff --git a/examples/envoy-ext-auth/Dockerfile b/examples/envoy-ext-auth/Dockerfile index 713f240f26..8cac13ffab 100644 --- a/examples/envoy-ext-auth/Dockerfile +++ b/examples/envoy-ext-auth/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.24.2 AS builder +FROM golang:1.24.3 AS builder ARG GO_LDFLAGS="" diff --git a/examples/envoy-ext-auth/go.mod b/examples/envoy-ext-auth/go.mod index 10d19daf3d..1b5a43afb1 100644 --- a/examples/envoy-ext-auth/go.mod +++ b/examples/envoy-ext-auth/go.mod @@ -1,6 +1,6 @@ module github.com/envoyproxy/gateway-grcp-ext-auth -go 1.24.2 +go 1.24.3 require ( github.com/envoyproxy/go-control-plane/envoy v1.32.4 diff --git a/examples/extension-server/go.mod b/examples/extension-server/go.mod index 8a396c325f..0fab86f3b7 100644 --- a/examples/extension-server/go.mod +++ b/examples/extension-server/go.mod @@ -1,6 +1,6 @@ module github.com/exampleorg/envoygateway-extension -go 1.24.2 +go 1.24.3 require ( github.com/envoyproxy/gateway v1.3.1 diff --git a/examples/grpc-ext-proc/Dockerfile b/examples/grpc-ext-proc/Dockerfile index 0b8988aeb3..ab262bf90a 100644 --- a/examples/grpc-ext-proc/Dockerfile +++ b/examples/grpc-ext-proc/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.24.2 AS builder +FROM golang:1.24.3 AS builder ARG GO_LDFLAGS="" diff --git a/examples/grpc-ext-proc/go.mod b/examples/grpc-ext-proc/go.mod index b94b3afa94..40cb9e2231 100644 --- a/examples/grpc-ext-proc/go.mod +++ b/examples/grpc-ext-proc/go.mod @@ -1,6 +1,6 @@ module github.com/envoyproxy/gateway-grpc-ext-proc -go 1.24.2 +go 1.24.3 require ( github.com/envoyproxy/go-control-plane/envoy v1.32.4 diff --git a/examples/preserve-case-backend/Dockerfile b/examples/preserve-case-backend/Dockerfile index ceef71bed1..8ee0fa63ff 100644 --- a/examples/preserve-case-backend/Dockerfile +++ b/examples/preserve-case-backend/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.24.2 AS builder +FROM golang:1.24.3 AS builder ARG GO_LDFLAGS="" diff --git a/examples/preserve-case-backend/go.mod b/examples/preserve-case-backend/go.mod index d383593957..edf81ecee2 100644 --- a/examples/preserve-case-backend/go.mod +++ b/examples/preserve-case-backend/go.mod @@ -1,6 +1,6 @@ module github.com/envoyproxy/gateway-preserve-case-backend -go 1.24.2 +go 1.24.3 require github.com/valyala/fasthttp v1.61.0 diff --git a/examples/simple-extension-server/Dockerfile b/examples/simple-extension-server/Dockerfile index f54ebbf7b9..6e7940c4dc 100644 --- a/examples/simple-extension-server/Dockerfile +++ b/examples/simple-extension-server/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.24.2 AS builder +FROM golang:1.24.3 AS builder ARG GO_LDFLAGS="" diff --git a/examples/simple-extension-server/go.mod b/examples/simple-extension-server/go.mod index 3939ecfaed..fafe30881f 100644 --- a/examples/simple-extension-server/go.mod +++ b/examples/simple-extension-server/go.mod @@ -1,6 +1,6 @@ module github.com/envoyproxy/gateway-simple-extension-server -go 1.24.2 +go 1.24.3 require ( github.com/envoyproxy/gateway v1.3.2 diff --git a/examples/static-file-server/Dockerfile b/examples/static-file-server/Dockerfile index 75e6d5eb71..911475923b 100644 --- a/examples/static-file-server/Dockerfile +++ b/examples/static-file-server/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.24.2 AS builder +FROM golang:1.24.3 AS builder ARG GO_LDFLAGS="" diff --git a/examples/static-file-server/go.mod b/examples/static-file-server/go.mod index 8c7a670ba2..b93cd5f3ce 100644 --- a/examples/static-file-server/go.mod +++ b/examples/static-file-server/go.mod @@ -1,3 +1,3 @@ module github.com/envoyproxy/static-file-server -go 1.24.2 +go 1.24.3 diff --git a/go.mod b/go.mod index b424f48065..e40b2a63ce 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/envoyproxy/gateway -go 1.24.2 +go 1.24.3 require ( fortio.org/fortio v1.69.4 @@ -198,7 +198,7 @@ require ( github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-metrics v0.0.1 // indirect github.com/docker/go-units v0.5.0 // indirect - github.com/ebitengine/purego v0.8.2 // indirect + github.com/ebitengine/purego v0.8.3 // indirect github.com/elastic/crd-ref-docs v0.1.0 // indirect github.com/elliotchance/orderedmap/v2 v2.2.0 // indirect github.com/emicklei/go-restful/v3 v3.12.0 // indirect diff --git a/go.sum b/go.sum index 315d567f9a..f125296c18 100644 --- a/go.sum +++ b/go.sum @@ -358,8 +358,8 @@ github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:Htrtb github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I= -github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/ebitengine/purego v0.8.3 h1:K+0AjQp63JEZTEMZiwsI9g0+hAMNohwUOtY0RPGexmc= +github.com/ebitengine/purego v0.8.3/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/elastic/crd-ref-docs v0.1.0 h1:Cr5kz89QB3Iuuj7dhAfLMApCrChEGAaIBTxGk/xuRKw= github.com/elastic/crd-ref-docs v0.1.0/go.mod h1:X83mMBdJt05heJUYiS3T0yJ/JkCuliuhSUNav5Gjo/U= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= diff --git a/internal/cmd/egctl/testdata/translate/out/backend-endpoint.all.yaml b/internal/cmd/egctl/testdata/translate/out/backend-endpoint.all.yaml index e9816d3458..1e913ac3da 100644 --- a/internal/cmd/egctl/testdata/translate/out/backend-endpoint.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/backend-endpoint.all.yaml @@ -77,9 +77,7 @@ envoyExtensionPolicies: namespace: envoy-gateway-system conditions: - lastTransitionTime: null - message: |- - Wasm: wasm cache is not initialized - ExtProc: service envoy-gateway-system/grpc-ext-proc not found. + message: 'ExtProc: service envoy-gateway-system/grpc-ext-proc not found.' reason: Invalid status: "False" type: Accepted diff --git a/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml b/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml index 0d0906fa80..fddc62d5c6 100644 --- a/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml @@ -23,7 +23,7 @@ envoyProxyForGatewayClass: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -108,7 +108,7 @@ envoyProxyForGatewayClass: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s diff --git a/internal/gatewayapi/backendtlspolicy.go b/internal/gatewayapi/backendtlspolicy.go index 143bc749fd..dc5c86b0f1 100644 --- a/internal/gatewayapi/backendtlspolicy.go +++ b/internal/gatewayapi/backendtlspolicy.go @@ -207,9 +207,25 @@ func getBackendTLSPolicy( } func getBackendTLSBundle(backendTLSPolicy *gwapiv1a3.BackendTLSPolicy, resources *resource.Resources) (*ir.TLSUpstreamConfig, error) { + // Translate SubjectAltNames from gwapiv1a3 to ir + var subjectAltNames []ir.SubjectAltName + for _, san := range backendTLSPolicy.Spec.Validation.SubjectAltNames { + var subjectAltName ir.SubjectAltName + switch san.Type { + case "DNS": + subjectAltName.Hostname = ptr.To(string(san.Hostname)) + case "URI": + subjectAltName.URI = ptr.To(string(san.URI)) + default: + continue // skip unknown types + } + subjectAltNames = append(subjectAltNames, subjectAltName) + } + tlsBundle := &ir.TLSUpstreamConfig{ SNI: ptr.To(string(backendTLSPolicy.Spec.Validation.Hostname)), UseSystemTrustStore: ptr.Deref(backendTLSPolicy.Spec.Validation.WellKnownCACertificates, "") == gwapiv1a3.WellKnownCACertificatesSystem, + SubjectAltNames: subjectAltNames, } if tlsBundle.UseSystemTrustStore { tlsBundle.CACertificate = &ir.TLSCACertificate{ diff --git a/internal/gatewayapi/backendtrafficpolicy.go b/internal/gatewayapi/backendtrafficpolicy.go index b670a2ea28..8998141bad 100644 --- a/internal/gatewayapi/backendtrafficpolicy.go +++ b/internal/gatewayapi/backendtrafficpolicy.go @@ -440,7 +440,13 @@ func (t *Translator) translateBackendTrafficPolicyForRouteWithMerge( // Since GlobalRateLimit merge relies on IR auto-generated key: (//rule/) // We can't simply merge the BTP's using utils.Merge() we need to specifically merge the GlobalRateLimit.Rules using IR fields. // Since ir.TrafficFeatures is not a built-in Kubernetes API object with defined merging strategies and it does not support a deep merge (for lists/maps). + + // Handle rate limit merging cases: + // 1. Both policies have rate limits - merge them + // 2. Only gateway policy has rate limits - preserve gateway policy's rule names + // 3. Only route policy has rate limits - use route policy's rule names (default behavior) if policy.Spec.RateLimit != nil && gwPolicy.Spec.RateLimit != nil { + // Case 1: Both policies have rate limits - merge them tfGW, _ := t.buildTrafficFeatures(gwPolicy, resources) tfRoute, _ := t.buildTrafficFeatures(policy, resources) @@ -454,7 +460,15 @@ func (t *Translator) translateBackendTrafficPolicyForRouteWithMerge( // Replace the rate limit in the merged features if successful tf.RateLimit = mergedRL } + } else if policy.Spec.RateLimit == nil && gwPolicy.Spec.RateLimit != nil { + // Case 2: Only gateway policy has rate limits - preserve gateway policy's rule names + tfGW, _ := t.buildTrafficFeatures(gwPolicy, resources) + if tfGW != nil && tfGW.RateLimit != nil { + // Use the gateway policy's rate limit with its original rule names + tf.RateLimit = tfGW.RateLimit + } } + // Case 3: Only route policy has rate limits or neither has rate limits - use default behavior (tf already built from merged policy) x, ok := xdsIR[t.IRKey(gatewayNN)] if !ok { diff --git a/internal/gatewayapi/envoyextensionpolicy.go b/internal/gatewayapi/envoyextensionpolicy.go index 7b27adbf06..079fdced28 100644 --- a/internal/gatewayapi/envoyextensionpolicy.go +++ b/internal/gatewayapi/envoyextensionpolicy.go @@ -614,12 +614,16 @@ func (t *Translator) buildWasms( policy *egv1a1.EnvoyExtensionPolicy, resources *resource.Resources, ) ([]ir.Wasm, error) { + var wasmIRList []ir.Wasm + + if len(policy.Spec.Wasm) == 0 { + return wasmIRList, nil + } + if t.WasmCache == nil { return nil, fmt.Errorf("wasm cache is not initialized") } - var wasmIRList []ir.Wasm - if policy == nil { return nil, nil } diff --git a/internal/gatewayapi/listener.go b/internal/gatewayapi/listener.go index 9f2fb5de26..7141d36ac7 100644 --- a/internal/gatewayapi/listener.go +++ b/internal/gatewayapi/listener.go @@ -176,30 +176,53 @@ func (t *Translator) ProcessListeners(gateways []*GatewayContext, xdsIR resource foundPorts[irKey] = append(foundPorts[irKey], servicePort) } } - - checkOverlappingTLSConfig(gateway) } + + t.checkOverlappingTLSConfig(gateways) } // checkOverlappingTLSConfig checks for overlapping hostnames and certificates between listeners and sets // the `OverlappingTLSConfig` condition if there are overlapping hostnames or certificates. -func checkOverlappingTLSConfig(gateway *GatewayContext) { - // Note: order of processing matters here. - // According to the Gateway API spec, If both hostname and certificate overlap, - // the controller SHOULD set the "OverlappingCertificates" Reason. - checkOverlappingHostnames(gateway) - checkOverlappingCertificates(gateway) -} - -func checkOverlappingHostnames(gateway *GatewayContext) { - httpsListeners := []*ListenerContext{} - for _, listener := range gateway.listeners { - if listener.Protocol == gwapiv1.HTTPSProtocolType { - httpsListeners = append(httpsListeners, listener) +func (t *Translator) checkOverlappingTLSConfig(gateways []*GatewayContext) { + // If merging gateways, check overlapping hostnames and certificates between listeners in all merged gateways. + if t.MergeGateways { + httpsListeners := []*ListenerContext{} + for _, gateway := range gateways { + for _, listener := range gateway.listeners { + if listener.Protocol == gwapiv1.HTTPSProtocolType { + httpsListeners = append(httpsListeners, listener) + } + } + } + // Note: order of processing matters here. + // According to the Gateway API spec, If both hostname and certificate overlap, + // the controller SHOULD set the "OverlappingCertificates" Reason. + checkOverlappingHostnames(httpsListeners) + checkOverlappingCertificates(httpsListeners) + } else { + // Check overlapping hostnames and certificates between listeners in each gateway. + for _, gateway := range gateways { + httpsListeners := []*ListenerContext{} + for _, listener := range gateway.listeners { + if listener.Protocol == gwapiv1.HTTPSProtocolType { + httpsListeners = append(httpsListeners, listener) + } + } + // Note: order of processing matters here. + // According to the Gateway API spec, If both hostname and certificate overlap, + // the controller SHOULD set the "OverlappingCertificates" Reason. + checkOverlappingHostnames(httpsListeners) + checkOverlappingCertificates(httpsListeners) } } +} +// checkOverlappingHostnames checks for overlapping hostnames between HTTPS listeners and sets +// the `OverlappingTLSConfig` condition if there are overlapping hostnames. +func checkOverlappingHostnames(httpsListeners []*ListenerContext) { type overlappingListener struct { + gateway1 *GatewayContext + gateway2 *GatewayContext listener1 string listener2 string hostname1 string @@ -220,12 +243,16 @@ func checkOverlappingHostnames(gateway *GatewayContext) { if isOverlappingHostname(httpsListeners[i].Hostname, httpsListeners[j].Hostname) { // Overlapping listeners can be more than two, we only report the first two for simplicity. overlappingListeners[i] = &overlappingListener{ + gateway1: httpsListeners[i].gateway, + gateway2: httpsListeners[j].gateway, listener1: string(httpsListeners[i].Name), listener2: string(httpsListeners[j].Name), hostname1: string(ptr.Deref(httpsListeners[i].Hostname, "")), hostname2: string(ptr.Deref(httpsListeners[j].Hostname, "")), } overlappingListeners[j] = &overlappingListener{ + gateway1: httpsListeners[j].gateway, + gateway2: httpsListeners[i].gateway, listener1: string(httpsListeners[j].Name), listener2: string(httpsListeners[i].Name), hostname1: string(ptr.Deref(httpsListeners[j].Hostname, "")), @@ -237,17 +264,33 @@ func checkOverlappingHostnames(gateway *GatewayContext) { for i, listener := range httpsListeners { if overlappingListeners[i] != nil { - status.SetGatewayListenerStatusCondition(gateway.Gateway, + var message string + gateway1 := overlappingListeners[i].gateway1 + gateway2 := overlappingListeners[i].gateway2 + if gateway1.Name == gateway2.Name && + gateway1.Namespace == gateway2.Namespace { + message = fmt.Sprintf( + "The hostname %s overlaps with the hostname %s in listener %s. ALPN will default to HTTP/1.1 to prevent HTTP/2 connection coalescing, unless explicitly configured via ClientTrafficPolicy", + overlappingListeners[i].hostname1, + overlappingListeners[i].hostname2, + overlappingListeners[i].listener2, + ) + } else { + message = fmt.Sprintf( + "The hostname %s overlaps with the hostname %s in listener %s of gateway %s. ALPN will default to HTTP/1.1 to prevent HTTP/2 connection coalescing, unless explicitly configured via ClientTrafficPolicy", + overlappingListeners[i].hostname1, + overlappingListeners[i].hostname2, + overlappingListeners[i].listener2, + gateway2.GetName(), + ) + } + + status.SetGatewayListenerStatusCondition(listener.gateway.Gateway, listener.listenerStatusIdx, gwapiv1.ListenerConditionOverlappingTLSConfig, metav1.ConditionTrue, gwapiv1.ListenerReasonOverlappingHostnames, - fmt.Sprintf( - "The hostname %s overlaps with the hostname %s in listener %s. ALPN is set to HTTP/1.1 to prevent HTTP/2 connection coalescing", - overlappingListeners[i].hostname1, - overlappingListeners[i].hostname2, - overlappingListeners[i].listener2, - ), + message, ) if listener.httpIR != nil { listener.httpIR.TLSOverlaps = true @@ -256,15 +299,12 @@ func checkOverlappingHostnames(gateway *GatewayContext) { } } -func checkOverlappingCertificates(gateway *GatewayContext) { - httpsListeners := []*ListenerContext{} - for _, listener := range gateway.listeners { - if listener.Protocol == gwapiv1.HTTPSProtocolType { - httpsListeners = append(httpsListeners, listener) - } - } - +// checkOverlappingCertificates checks for overlapping certificates SANs between HTTPSlisteners and sets +// the `OverlappingTLSConfig` condition if there are overlapping certificates. +func checkOverlappingCertificates(httpsListeners []*ListenerContext) { type overlappingListener struct { + gateway1 *GatewayContext + gateway2 *GatewayContext listener1 string listener2 string san1 string @@ -288,12 +328,16 @@ func checkOverlappingCertificates(gateway *GatewayContext) { if overlappingCertificate != nil { // Overlapping listeners can be more than two, we only report the first two for simplicity. overlappingListeners[i] = &overlappingListener{ + gateway1: httpsListeners[i].gateway, + gateway2: httpsListeners[j].gateway, listener1: string(httpsListeners[i].Name), listener2: string(httpsListeners[j].Name), san1: overlappingCertificate.san1, san2: overlappingCertificate.san2, } overlappingListeners[j] = &overlappingListener{ + gateway1: httpsListeners[j].gateway, + gateway2: httpsListeners[i].gateway, listener1: string(httpsListeners[j].Name), listener2: string(httpsListeners[i].Name), san1: overlappingCertificate.san2, @@ -305,17 +349,33 @@ func checkOverlappingCertificates(gateway *GatewayContext) { for i, listener := range httpsListeners { if overlappingListeners[i] != nil { - status.SetGatewayListenerStatusCondition(gateway.Gateway, + var message string + gateway1 := overlappingListeners[i].gateway1 + gateway2 := overlappingListeners[i].gateway2 + if gateway1.Name == gateway2.Name && + gateway1.Namespace == gateway2.Namespace { + message = fmt.Sprintf( + "The certificate SAN %s overlaps with the certificate SAN %s in listener %s. ALPN will default to HTTP/1.1 to prevent HTTP/2 connection coalescing, unless explicitly configured via ClientTrafficPolicy", + overlappingListeners[i].san1, + overlappingListeners[i].san2, + overlappingListeners[i].listener2, + ) + } else { + message = fmt.Sprintf( + "The certificate SAN %s overlaps with the certificate SAN %s in listener %s of gateway %s. ALPN will default to HTTP/1.1 to prevent HTTP/2 connection coalescing, unless explicitly configured via ClientTrafficPolicy", + overlappingListeners[i].san1, + overlappingListeners[i].san2, + overlappingListeners[i].listener2, + gateway2.GetName(), + ) + } + + status.SetGatewayListenerStatusCondition(listener.gateway.Gateway, listener.listenerStatusIdx, gwapiv1.ListenerConditionOverlappingTLSConfig, metav1.ConditionTrue, gwapiv1.ListenerReasonOverlappingCertificates, - fmt.Sprintf( - "The certificate san %s overlaps with the certificate san %s in listener %s. ALPN is set to HTTP/1.1 to prevent HTTP/2 connection coalescing", - overlappingListeners[i].san1, - overlappingListeners[i].san2, - overlappingListeners[i].listener2, - ), + message, ) if listener.httpIR != nil { listener.httpIR.TLSOverlaps = true diff --git a/internal/gatewayapi/listener_test.go b/internal/gatewayapi/listener_test.go index cfdae67f37..9c16fa6500 100644 --- a/internal/gatewayapi/listener_test.go +++ b/internal/gatewayapi/listener_test.go @@ -306,30 +306,6 @@ func TestCheckOverlappingHostnames(t *testing.T) { 2: "*.example.com", }, }, - { - name: "non-HTTPS listeners", - gateway: &GatewayContext{ - listeners: []*ListenerContext{ - { - Listener: &gwapiv1.Listener{ - Name: "listener-1", - Protocol: gwapiv1.HTTPProtocolType, - Port: 80, - Hostname: ptr.To(gwapiv1.Hostname("example.com")), - }, - }, - { - Listener: &gwapiv1.Listener{ - Name: "listener-2", - Protocol: gwapiv1.HTTPProtocolType, - Port: 80, - Hostname: ptr.To(gwapiv1.Hostname("example.com")), - }, - }, - }, - }, - expected: map[int]string{}, - }, { name: "nil hostnames", gateway: &GatewayContext{ @@ -369,13 +345,14 @@ func TestCheckOverlappingHostnames(t *testing.T) { } for i := range tt.gateway.listeners { tt.gateway.listeners[i].listenerStatusIdx = i + tt.gateway.listeners[i].gateway = tt.gateway tt.gateway.Status.Listeners[i] = gwapiv1.ListenerStatus{ Name: tt.gateway.listeners[i].Name, Conditions: []metav1.Condition{}, } } - checkOverlappingHostnames(tt.gateway) + checkOverlappingHostnames(tt.gateway.listeners) // Verify the status conditions for idx, expectedHostname := range tt.expected { @@ -476,14 +453,14 @@ func TestCheckOverlappingCertificates(t *testing.T) { condition: gwapiv1.ListenerConditionOverlappingTLSConfig, status: metav1.ConditionTrue, reason: gwapiv1.ListenerReasonOverlappingCertificates, - message: "The certificate san foo.example.com overlaps with the certificate san foo.example.com in listener listener-2. ALPN is set to HTTP/1.1 to prevent HTTP/2 connection coalescing", + message: "The certificate SAN foo.example.com overlaps with the certificate SAN foo.example.com in listener listener-2. ALPN will default to HTTP/1.1 to prevent HTTP/2 connection coalescing, unless explicitly configured via ClientTrafficPolicy", }, { listenerName: "listener-2", condition: gwapiv1.ListenerConditionOverlappingTLSConfig, status: metav1.ConditionTrue, reason: gwapiv1.ListenerReasonOverlappingCertificates, - message: "The certificate san foo.example.com overlaps with the certificate san foo.example.com in listener listener-1. ALPN is set to HTTP/1.1 to prevent HTTP/2 connection coalescing", + message: "The certificate SAN foo.example.com overlaps with the certificate SAN foo.example.com in listener listener-1. ALPN will default to HTTP/1.1 to prevent HTTP/2 connection coalescing, unless explicitly configured via ClientTrafficPolicy", }, }, }, @@ -539,14 +516,14 @@ func TestCheckOverlappingCertificates(t *testing.T) { condition: gwapiv1.ListenerConditionOverlappingTLSConfig, status: metav1.ConditionTrue, reason: gwapiv1.ListenerReasonOverlappingCertificates, - message: "The certificate san *.example.com overlaps with the certificate san foo.example.com in listener listener-2. ALPN is set to HTTP/1.1 to prevent HTTP/2 connection coalescing", + message: "The certificate SAN *.example.com overlaps with the certificate SAN foo.example.com in listener listener-2. ALPN will default to HTTP/1.1 to prevent HTTP/2 connection coalescing, unless explicitly configured via ClientTrafficPolicy", }, { listenerName: "listener-2", condition: gwapiv1.ListenerConditionOverlappingTLSConfig, status: metav1.ConditionTrue, reason: gwapiv1.ListenerReasonOverlappingCertificates, - message: "The certificate san foo.example.com overlaps with the certificate san *.example.com in listener listener-1. ALPN is set to HTTP/1.1 to prevent HTTP/2 connection coalescing", + message: "The certificate SAN foo.example.com overlaps with the certificate SAN *.example.com in listener listener-1. ALPN will default to HTTP/1.1 to prevent HTTP/2 connection coalescing, unless explicitly configured via ClientTrafficPolicy", }, }, }, @@ -578,14 +555,14 @@ func TestCheckOverlappingCertificates(t *testing.T) { condition: gwapiv1.ListenerConditionOverlappingTLSConfig, status: metav1.ConditionTrue, reason: gwapiv1.ListenerReasonOverlappingCertificates, - message: "The certificate san bar.example.org overlaps with the certificate san *.example.org in listener listener-2. ALPN is set to HTTP/1.1 to prevent HTTP/2 connection coalescing", + message: "The certificate SAN bar.example.org overlaps with the certificate SAN *.example.org in listener listener-2. ALPN will default to HTTP/1.1 to prevent HTTP/2 connection coalescing, unless explicitly configured via ClientTrafficPolicy", }, { listenerName: "listener-2", condition: gwapiv1.ListenerConditionOverlappingTLSConfig, status: metav1.ConditionTrue, reason: gwapiv1.ListenerReasonOverlappingCertificates, - message: "The certificate san *.example.org overlaps with the certificate san bar.example.org in listener listener-1. ALPN is set to HTTP/1.1 to prevent HTTP/2 connection coalescing", + message: "The certificate SAN *.example.org overlaps with the certificate SAN bar.example.org in listener listener-1. ALPN will default to HTTP/1.1 to prevent HTTP/2 connection coalescing, unless explicitly configured via ClientTrafficPolicy", }, }, }, @@ -603,16 +580,18 @@ func TestCheckOverlappingCertificates(t *testing.T) { listeners: tt.listeners, } - // Initialize listener status indices + // Initialize listener for i := range gateway.Status.Listeners { gateway.Status.Listeners[i] = gwapiv1.ListenerStatus{ Name: tt.listeners[i].Name, Conditions: []metav1.Condition{}, } + gateway.listeners[i].listenerStatusIdx = i + gateway.listeners[i].gateway = gateway } // Process overlapping certificates - checkOverlappingCertificates(gateway) + checkOverlappingCertificates(tt.listeners) // Verify the status conditions for _, expected := range tt.expectedStatus { diff --git a/internal/gatewayapi/status/gateway.go b/internal/gatewayapi/status/gateway.go index 5c0354c0be..af45012b67 100644 --- a/internal/gatewayapi/status/gateway.go +++ b/internal/gatewayapi/status/gateway.go @@ -58,7 +58,12 @@ func UpdateGatewayStatusProgrammedCondition(gw *gwapiv1.Gateway, svc *corev1.Ser if len(svc.Spec.ExternalIPs) > 0 { addresses = append(addresses, svc.Spec.ExternalIPs...) } else if len(svc.Spec.ClusterIPs) > 0 { - addresses = append(addresses, svc.Spec.ClusterIPs...) + // Filter out "None" values which represent headless services + for _, ip := range svc.Spec.ClusterIPs { + if ip != "" && ip != "None" { + addresses = append(addresses, ip) + } + } } } else { if svc.Spec.Type == corev1.ServiceTypeLoadBalancer { @@ -79,7 +84,8 @@ func UpdateGatewayStatusProgrammedCondition(gw *gwapiv1.Gateway, svc *corev1.Ser if svc.Spec.Type == corev1.ServiceTypeClusterIP { for i := range svc.Spec.ClusterIPs { - if svc.Spec.ClusterIPs[i] != "" { + // Filter out "None" values which represent headless services + if svc.Spec.ClusterIPs[i] != "" && svc.Spec.ClusterIPs[i] != "None" { addresses = append(addresses, svc.Spec.ClusterIPs[i]) } } diff --git a/internal/gatewayapi/status/gateway_test.go b/internal/gatewayapi/status/gateway_test.go index c2d18a7fc1..0dcb550a10 100644 --- a/internal/gatewayapi/status/gateway_test.go +++ b/internal/gatewayapi/status/gateway_test.go @@ -242,6 +242,45 @@ func TestUpdateGatewayStatusProgrammedCondition(t *testing.T) { }, }, }, + { + name: "Headless ClusterIP svc with None", + args: args{ + gw: &gwapiv1.Gateway{}, + svc: &corev1.Service{ + TypeMeta: metav1.TypeMeta{}, + ObjectMeta: metav1.ObjectMeta{}, + Spec: corev1.ServiceSpec{ + ClusterIPs: []string{"None"}, + Type: corev1.ServiceTypeClusterIP, + }, + }, + }, + wantAddresses: []gwapiv1.GatewayStatusAddress{}, + }, + { + name: "Headless ClusterIP svc with None and explicit Gateway addresses", + args: args{ + gw: &gwapiv1.Gateway{ + Spec: gwapiv1.GatewaySpec{ + Addresses: []gwapiv1.GatewaySpecAddress{ + { + Type: ptr.To(gwapiv1.IPAddressType), + Value: "10.0.0.1", + }, + }, + }, + }, + svc: &corev1.Service{ + TypeMeta: metav1.TypeMeta{}, + ObjectMeta: metav1.ObjectMeta{}, + Spec: corev1.ServiceSpec{ + ClusterIPs: []string{"None"}, + Type: corev1.ServiceTypeClusterIP, + }, + }, + }, + wantAddresses: []gwapiv1.GatewayStatusAddress{}, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/gatewayapi/testdata/backendtlspolicy-subjectaltnames.in.yaml b/internal/gatewayapi/testdata/backendtlspolicy-subjectaltnames.in.yaml new file mode 100644 index 0000000000..2b349c7783 --- /dev/null +++ b/internal/gatewayapi/testdata/backendtlspolicy-subjectaltnames.in.yaml @@ -0,0 +1,137 @@ +gateways: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + name: gateway-btls + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All +httpRoutes: + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + name: httproute-btls + namespace: envoy-gateway + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-btls + sectionName: http + rules: + - matches: + - path: + type: Exact + value: "/exact" + backendRefs: + - name: http-backend + namespace: backends + port: 8080 + +referenceGrants: + - apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: ReferenceGrant + metadata: + name: refg-route-svc + namespace: backends + spec: + from: + - group: gateway.networking.k8s.io + kind: HTTPRoute + namespace: envoy-gateway + - group: gateway.networking.k8s.io + kind: Gateway + namespace: envoy-gateway + to: + - group: "" + kind: Service + +services: + - apiVersion: v1 + kind: Service + metadata: + name: http-backend + namespace: backends + spec: + clusterIP: 10.11.12.13 + ports: + - port: 8080 + name: http + protocol: TCP + targetPort: 8080 + +endpointSlices: + - apiVersion: discovery.k8s.io/v1 + kind: EndpointSlice + metadata: + name: endpointslice-http-backend + namespace: backends + labels: + kubernetes.io/service-name: http-backend + addressType: IPv4 + ports: + - name: http + protocol: TCP + port: 8080 + endpoints: + - addresses: + - "10.244.0.11" + conditions: + ready: true + +configMaps: + - apiVersion: v1 + kind: ConfigMap + metadata: + name: ca-cmap + namespace: backends + data: + ca.crt: | + -----BEGIN CERTIFICATE----- + MIIDJzCCAg+gAwIBAgIUAl6UKIuKmzte81cllz5PfdN2IlIwDQYJKoZIhvcNAQEL + BQAwIzEQMA4GA1UEAwwHbXljaWVudDEPMA0GA1UECgwGa3ViZWRiMB4XDTIzMTAw + MjA1NDE1N1oXDTI0MTAwMTA1NDE1N1owIzEQMA4GA1UEAwwHbXljaWVudDEPMA0G + A1UECgwGa3ViZWRiMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwSTc + 1yj8HW62nynkFbXo4VXKv2jC0PM7dPVky87FweZcTKLoWQVPQE2p2kLDK6OEszmM + yyr+xxWtyiveremrWqnKkNTYhLfYPhgQkczib7eUalmFjUbhWdLvHakbEgCodn3b + kz57mInX2VpiDOKg4kyHfiuXWpiBqrCx0KNLpxo3DEQcFcsQTeTHzh4752GV04RU + Ti/GEWyzIsl4Rg7tGtAwmcIPgUNUfY2Q390FGqdH4ahn+mw/6aFbW31W63d9YJVq + ioyOVcaMIpM5B/c7Qc8SuhCI1YGhUyg4cRHLEw5VtikioyE3X04kna3jQAj54YbR + bpEhc35apKLB21HOUQIDAQABo1MwUTAdBgNVHQ4EFgQUyvl0VI5vJVSuYFXu7B48 + 6PbMEAowHwYDVR0jBBgwFoAUyvl0VI5vJVSuYFXu7B486PbMEAowDwYDVR0TAQH/ + BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAMLxrgFVMuNRq2wAwcBt7SnNR5Cfz + 2MvXq5EUmuawIUi9kaYjwdViDREGSjk7JW17vl576HjDkdfRwi4E28SydRInZf6J + i8HZcZ7caH6DxR335fgHVzLi5NiTce/OjNBQzQ2MJXVDd8DBmG5fyatJiOJQ4bWE + A7FlP0RdP3CO3GWE0M5iXOB2m1qWkE2eyO4UHvwTqNQLdrdAXgDQlbam9e4BG3Gg + d/6thAkWDbt/QNT+EJHDCvhDRKh1RuGHyg+Y+/nebTWWrFWsktRrbOoHCZiCpXI1 + 3eXE6nt0YkgtDxG22KqnhpAg9gUSs2hlhoxyvkzyF0mu6NhPlwAgnq7+/Q== + -----END CERTIFICATE----- +backendTLSPolicies: + - apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + name: policy-btls + namespace: backends + spec: + targetRefs: + - group: "" + kind: Service + name: http-backend + sectionName: http + validation: + caCertificateRefs: + - name: ca-cmap + group: "" + kind: ConfigMap + hostname: example.com + subjectAltNames: + - type: URI + uri: spiffe://cluster.local/ns/istio-demo/sa/echo-v1 + - type: DNS + hostname: subdomain.secondexample.com diff --git a/internal/gatewayapi/testdata/backendtlspolicy-subjectaltnames.out.yaml b/internal/gatewayapi/testdata/backendtlspolicy-subjectaltnames.out.yaml new file mode 100644 index 0000000000..215860c4ea --- /dev/null +++ b/internal/gatewayapi/testdata/backendtlspolicy-subjectaltnames.out.yaml @@ -0,0 +1,190 @@ +backendTLSPolicies: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + creationTimestamp: null + name: policy-btls + namespace: backends + spec: + targetRefs: + - group: "" + kind: Service + name: http-backend + sectionName: http + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + name: ca-cmap + hostname: example.com + subjectAltNames: + - type: URI + uri: spiffe://cluster.local/ns/istio-demo/sa/echo-v1 + - hostname: subdomain.secondexample.com + type: DNS + status: + ancestors: + - ancestorRef: + name: gateway-btls + namespace: envoy-gateway + sectionName: http + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-btls + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 1 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-btls + namespace: envoy-gateway + spec: + parentRefs: + - name: gateway-btls + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: http-backend + namespace: backends + port: 8080 + matches: + - path: + type: Exact + value: /exact + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-btls + namespace: envoy-gateway + sectionName: http +infraIR: + envoy-gateway/gateway-btls: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-btls/http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-btls + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-btls + namespace: envoy-gateway-system +xdsIR: + envoy-gateway/gateway-btls: + accessLog: + json: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-btls + namespace: envoy-gateway + sectionName: http + name: envoy-gateway/gateway-btls/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/envoy-gateway/httproute-btls/rule/0 + settings: + - addressType: IP + endpoints: + - host: 10.244.0.11 + port: 8080 + name: httproute/envoy-gateway/httproute-btls/rule/0/backend/0 + protocol: HTTP + tls: + alpnProtocols: null + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + name: policy-btls/backends-ca + sni: example.com + subjectAltNames: + - uri: spiffe://cluster.local/ns/istio-demo/sa/echo-v1 + - hostname: subdomain.secondexample.com + weight: 1 + hostname: '*' + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-btls + namespace: envoy-gateway + name: httproute/envoy-gateway/httproute-btls/rule/0/match/0/* + pathMatch: + distinct: false + exact: /exact + name: "" + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-strategic-merge-only-gw-rl.in.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-strategic-merge-only-gw-rl.in.yaml new file mode 100644 index 0000000000..d8a41472b3 --- /dev/null +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-strategic-merge-only-gw-rl.in.yaml @@ -0,0 +1,111 @@ +gateways: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-2 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All +httpRoutes: + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-1 + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + - namespace: envoy-gateway + name: gateway-2 + sectionName: http + rules: + - matches: + - path: + value: "/" + backendRefs: + - name: service-1 + port: 8080 +backendTrafficPolicies: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + namespace: envoy-gateway + name: policy-for-gateway1 + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + timeout: + tcp: + connectTimeout: 15s + http: + connectionIdleTimeout: 16s + maxConnectionDuration: 17s + httpUpgrade: + - type: websocket + rateLimit: + type: Global + global: + rules: + - clientSelectors: + - sourceCIDR: + type: Distinct + value: 0.0.0.0/0 + limit: + requests: 5 + unit: Hour + shared: true + - clientSelectors: + - headers: + - name: x-user-id + type: Exact + value: one + limit: + requests: 5 + unit: Hour + shared: true + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + namespace: default + name: policy-for-route + spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + mergeType: StrategicMerge + timeout: + tcp: + connectTimeout: 10s + connection: + bufferLimit: 100M + httpUpgrade: + - type: "spdy/3.1" + diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-strategic-merge-only-gw-rl.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-strategic-merge-only-gw-rl.out.yaml new file mode 100644 index 0000000000..06f9472447 --- /dev/null +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-strategic-merge-only-gw-rl.out.yaml @@ -0,0 +1,429 @@ +backendTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + creationTimestamp: null + name: policy-for-route + namespace: default + spec: + connection: + bufferLimit: 100M + httpUpgrade: + - type: spdy/3.1 + mergeType: StrategicMerge + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + timeout: + tcp: + connectTimeout: 10s + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: Merged with policy envoy-gateway/policy-for-gateway1 + reason: Merged + status: "True" + type: Merged + controllerName: gateway.envoyproxy.io/gatewayclass-controller + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-2 + namespace: envoy-gateway + sectionName: http + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + creationTimestamp: null + name: policy-for-gateway1 + namespace: envoy-gateway + spec: + httpUpgrade: + - type: websocket + rateLimit: + global: + rules: + - clientSelectors: + - sourceCIDR: + type: Distinct + value: 0.0.0.0/0 + limit: + requests: 5 + unit: Hour + shared: true + - clientSelectors: + - headers: + - name: x-user-id + type: Exact + value: one + limit: + requests: 5 + unit: Hour + shared: true + type: Global + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + timeout: + http: + connectionIdleTimeout: 16s + maxConnectionDuration: 17s + tcp: + connectTimeout: 15s + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: 'This policy is being merged by other backendTrafficPolicies for + these routes: [default/httproute-1]' + reason: Merged + status: "True" + type: Merged + controllerName: gateway.envoyproxy.io/gatewayclass-controller +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 1 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-2 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 1 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-1 + namespace: default + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + - name: gateway-2 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: / + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-2 + namespace: envoy-gateway + sectionName: http +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-1/http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-1 + namespace: envoy-gateway-system + envoy-gateway/gateway-2: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-2/http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-2 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-2 + namespace: envoy-gateway-system +xdsIR: + envoy-gateway/gateway-1: + accessLog: + json: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + name: httproute/default/httproute-1/rule/0/backend/0 + protocol: HTTP + weight: 1 + hostname: gateway.envoyproxy.io + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: / + traffic: + backendConnection: + bufferLimit: 100000000 + httpUpgrade: + - spdy/3.1 + - websocket + rateLimit: + global: + rules: + - cidrMatch: + cidr: 0.0.0.0/0 + distinct: true + ip: 0.0.0.0 + isIPv6: false + maskLen: 0 + headerMatches: [] + limit: + requests: 5 + unit: Hour + name: envoy-gateway/policy-for-gateway1/rule/0 + shared: true + - headerMatches: + - distinct: false + exact: one + name: x-user-id + limit: + requests: 5 + unit: Hour + name: envoy-gateway/policy-for-gateway1/rule/1 + shared: true + timeout: + http: + connectionIdleTimeout: 16s + maxConnectionDuration: 17s + tcp: + connectTimeout: 10s + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 + envoy-gateway/gateway-2: + accessLog: + json: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-2 + namespace: envoy-gateway + sectionName: http + name: envoy-gateway/gateway-2/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + name: httproute/default/httproute-1/rule/0/backend/0 + protocol: HTTP + weight: 1 + hostname: gateway.envoyproxy.io + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: / + traffic: + backendConnection: + bufferLimit: 100000000 + httpUpgrade: + - spdy/3.1 + timeout: + tcp: + connectTimeout: 10s + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-strategic-merge-only-httproute-rl.in.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-strategic-merge-only-httproute-rl.in.yaml new file mode 100644 index 0000000000..4c2142db8d --- /dev/null +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-strategic-merge-only-httproute-rl.in.yaml @@ -0,0 +1,110 @@ +gateways: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-2 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All +httpRoutes: + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-1 + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + - namespace: envoy-gateway + name: gateway-2 + sectionName: http + rules: + - matches: + - path: + value: "/" + backendRefs: + - name: service-1 + port: 8080 +backendTrafficPolicies: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + namespace: envoy-gateway + name: policy-for-gateway1 + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + timeout: + tcp: + connectTimeout: 15s + http: + connectionIdleTimeout: 16s + maxConnectionDuration: 17s + httpUpgrade: + - type: websocket + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + namespace: default + name: policy-for-route + spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + mergeType: StrategicMerge + timeout: + tcp: + connectTimeout: 10s + connection: + bufferLimit: 100M + httpUpgrade: + - type: "spdy/3.1" + rateLimit: + type: Global + global: + rules: + - clientSelectors: + - sourceCIDR: + type: Distinct + value: 0.0.0.0/0 + limit: + requests: 5 + unit: Hour + shared: true + - clientSelectors: + - headers: + - name: x-user-id + type: Exact + value: one + limit: + requests: 5 + unit: Hour + shared: true diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-strategic-merge-only-httproute-rl.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-strategic-merge-only-httproute-rl.out.yaml new file mode 100644 index 0000000000..92f5b76022 --- /dev/null +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-strategic-merge-only-httproute-rl.out.yaml @@ -0,0 +1,453 @@ +backendTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + creationTimestamp: null + name: policy-for-route + namespace: default + spec: + connection: + bufferLimit: 100M + httpUpgrade: + - type: spdy/3.1 + mergeType: StrategicMerge + rateLimit: + global: + rules: + - clientSelectors: + - sourceCIDR: + type: Distinct + value: 0.0.0.0/0 + limit: + requests: 5 + unit: Hour + shared: true + - clientSelectors: + - headers: + - name: x-user-id + type: Exact + value: one + limit: + requests: 5 + unit: Hour + shared: true + type: Global + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + timeout: + tcp: + connectTimeout: 10s + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: Merged with policy envoy-gateway/policy-for-gateway1 + reason: Merged + status: "True" + type: Merged + controllerName: gateway.envoyproxy.io/gatewayclass-controller + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-2 + namespace: envoy-gateway + sectionName: http + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + creationTimestamp: null + name: policy-for-gateway1 + namespace: envoy-gateway + spec: + httpUpgrade: + - type: websocket + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + timeout: + http: + connectionIdleTimeout: 16s + maxConnectionDuration: 17s + tcp: + connectTimeout: 15s + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: 'This policy is being merged by other backendTrafficPolicies for + these routes: [default/httproute-1]' + reason: Merged + status: "True" + type: Merged + controllerName: gateway.envoyproxy.io/gatewayclass-controller +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 1 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-2 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 1 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-1 + namespace: default + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + - name: gateway-2 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: / + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-2 + namespace: envoy-gateway + sectionName: http +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-1/http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-1 + namespace: envoy-gateway-system + envoy-gateway/gateway-2: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-2/http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-2 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-2 + namespace: envoy-gateway-system +xdsIR: + envoy-gateway/gateway-1: + accessLog: + json: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + name: httproute/default/httproute-1/rule/0/backend/0 + protocol: HTTP + weight: 1 + hostname: gateway.envoyproxy.io + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: / + traffic: + backendConnection: + bufferLimit: 100000000 + httpUpgrade: + - spdy/3.1 + - websocket + rateLimit: + global: + rules: + - cidrMatch: + cidr: 0.0.0.0/0 + distinct: true + ip: 0.0.0.0 + isIPv6: false + maskLen: 0 + headerMatches: [] + limit: + requests: 5 + unit: Hour + name: default/policy-for-route/rule/0 + shared: true + - headerMatches: + - distinct: false + exact: one + name: x-user-id + limit: + requests: 5 + unit: Hour + name: default/policy-for-route/rule/1 + shared: true + timeout: + http: + connectionIdleTimeout: 16s + maxConnectionDuration: 17s + tcp: + connectTimeout: 10s + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 + envoy-gateway/gateway-2: + accessLog: + json: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-2 + namespace: envoy-gateway + sectionName: http + name: envoy-gateway/gateway-2/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + name: httproute/default/httproute-1/rule/0/backend/0 + protocol: HTTP + weight: 1 + hostname: gateway.envoyproxy.io + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: / + traffic: + backendConnection: + bufferLimit: 100000000 + httpUpgrade: + - spdy/3.1 + rateLimit: + global: + rules: + - cidrMatch: + cidr: 0.0.0.0/0 + distinct: true + ip: 0.0.0.0 + isIPv6: false + maskLen: 0 + headerMatches: [] + limit: + requests: 5 + unit: Hour + name: default/policy-for-route/rule/0 + shared: true + - headerMatches: + - distinct: false + exact: one + name: x-user-id + limit: + requests: 5 + unit: Hour + name: default/policy-for-route/rule/1 + shared: true + timeout: + tcp: + connectTimeout: 10s + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 diff --git a/internal/gatewayapi/testdata/gateway-namespace-mode-infra-httproute.out.yaml b/internal/gatewayapi/testdata/gateway-namespace-mode-infra-httproute.out.yaml index 8d453faf57..98b3faf40b 100644 --- a/internal/gatewayapi/testdata/gateway-namespace-mode-infra-httproute.out.yaml +++ b/internal/gatewayapi/testdata/gateway-namespace-mode-infra-httproute.out.yaml @@ -240,6 +240,9 @@ infraIR: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 gateway.envoyproxy.io/owning-gateway-namespace: default + ownerReference: + kind: Gateway + name: gateway-1 name: default/gateway-1 namespace: default default/gateway-2: @@ -256,6 +259,9 @@ infraIR: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-2 gateway.envoyproxy.io/owning-gateway-namespace: default + ownerReference: + kind: Gateway + name: gateway-2 name: default/gateway-2 namespace: default test-ns/gateway-3: @@ -272,6 +278,9 @@ infraIR: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-3 gateway.envoyproxy.io/owning-gateway-namespace: test-ns + ownerReference: + kind: Gateway + name: gateway-3 name: test-ns/gateway-3 namespace: test-ns xdsIR: diff --git a/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-certs.out.yaml b/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-certs.out.yaml index 0b7bdfa2e4..99c22e426c 100644 --- a/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-certs.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-certs.out.yaml @@ -67,9 +67,9 @@ gateways: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: The certificate san *.example.com overlaps with the certificate san - bar.example.com in listener https-2. ALPN is set to HTTP/1.1 to prevent - HTTP/2 connection coalescing + message: The certificate SAN *.example.com overlaps with the certificate SAN + bar.example.com in listener https-2. ALPN will default to HTTP/1.1 to prevent + HTTP/2 connection coalescing, unless explicitly configured via ClientTrafficPolicy reason: OverlappingCertificates status: "True" type: OverlappingTLSConfig @@ -97,9 +97,9 @@ gateways: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: The certificate san bar.example.com overlaps with the certificate - san *.example.com in listener https-1. ALPN is set to HTTP/1.1 to prevent - HTTP/2 connection coalescing + message: The certificate SAN bar.example.com overlaps with the certificate + SAN *.example.com in listener https-1. ALPN will default to HTTP/1.1 to + prevent HTTP/2 connection coalescing, unless explicitly configured via ClientTrafficPolicy reason: OverlappingCertificates status: "True" type: OverlappingTLSConfig diff --git a/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames-and-certs-merged-gateways.in.yaml b/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames-and-certs-merged-gateways.in.yaml new file mode 100644 index 0000000000..7c204bac59 --- /dev/null +++ b/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames-and-certs-merged-gateways.in.yaml @@ -0,0 +1,123 @@ +envoyProxyForGatewayClass: + apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyProxy + metadata: + name: test + namespace: envoy-gateway-system + spec: + mergeGateways: true +gateways: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: https-1 + protocol: HTTPS + port: 443 + hostname: "*.example.com" # According to the Gateway API spec, If both hostname and certificate overlap, the controller SHOULD set the "OverlappingCertificates" Reason. + allowedRoutes: + namespaces: + from: All + tls: + mode: Terminate + certificateRefs: + - name: tls-secret-example-com + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-2 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: https-1 + protocol: HTTPS + port: 443 + hostname: "bar.example.com" + allowedRoutes: + namespaces: + from: All + tls: + mode: Terminate + certificateRefs: + - name: tls-secret-bar-example-com +secrets: + - apiVersion: v1 + kind: Secret + metadata: + namespace: envoy-gateway + name: tls-secret-example-com + type: kubernetes.io/tls + data: # foo.example.com *.example.com + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUR3RENDQXFpZ0F3SUJBZ0lVVDRyelIreStHd1VzMm9ydExIZ0k1MzBKeG9Fd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5UQTBNakl3TWpVNU1UQmFGdzB6TlRBME1qQXdNalU1TVRCYU1EVXhGREFTQmdOVkJBTU1DMlp2CmJ5NWlZWEl1WTI5dE1SMHdHd1lEVlFRS0RCUmxlR0Z0Y0d4bElHOXlaMkZ1YVhwaGRHbHZiakNDQVNJd0RRWUoKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTE4wbnJNR1NZNjBPT0JuTFVaSGpCRFkxazhqWHA2RwppeG1RaFNOK3lZUi9VQWVqSmhCOVI3S2RuT3d0eGljTnozdUFtL0p0UTFKRUU0dW5xQnhVTU8ydWpvVXl4ZisrCjRnb2tFYmVpTlhNN0ptaklPOGxEWlJjcEhFTlE3eUNJL3d1cEZBcHgwNnVrNUtBSlpRMUlmVXhZWS9RRkJsc3cKdUx0TWozVlB6eDBJYjRIV1lHdGhXcDIzUWduMUdGUWVTOGMwZHdqWWNBTGtrTFdwWWdUZTZGT0VhR3hvUzdwTQpGbitvZnRFUjlxZCtDcnRDSXM5TzFtOW5MUU9UWGJDNU5nSzR1ZFdhMFBuYjJ6TEk4WjZsVHFRSTNSODE2NkxKCkVDQi9ZSlYzVmtMb2cxUmx0d0FrM3hrWHFnbVhTZUxILzY3MHh6MEx5OGZHQVpmejFMQVpkSXNDQXdFQUFhT0IKenpDQnpEQWRCZ05WSFE0RUZnUVUzbVFodVB2dVl1K0lmN0ZaM010eU9jMWdjQ1V3YUFZRFZSMGpCR0V3WDRBVQpXWmxKWFQ1bXlEVnlsUjlSS2JQQTAxTkVlcytoTWFRdk1DMHhGVEFUQmdOVkJBb01ER1Y0WVcxd2JHVWdTVzVqCkxqRVVNQklHQTFVRUF3d0xaWGhoYlhCc1pTNWpiMjJDRkJuNktuTlBhbm1Db1daVStNYmtwKzJScmN4dU1Bc0cKQTFVZER3UUVBd0lDL0RBcEJnTlZIUkVFSWpBZ2dnOW1iMjh1WlhoaGJYQnNaUzVqYjIyQ0RTb3VaWGhoYlhCcwpaUzVqYjIwd0NRWURWUjBTQkFJd0FEQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFIa2xEbzkvNnRLcDNFd3JSCnJjVStKOUtmUkFGajc5YU1DREpVb0NyM2J6RFIycXQ4ZzlsbDdFSzZaeEtFa0xzWkFlYzBxU0Z1QjBvbzVqZFEKM3VvT2hNK1JKTkZoTldFd3dHWmpMb0FlK2oxaXByN1A5ajdmdFNzck8ra3M3TVNMeTE2RW9IV2Q0eG00Rk5QZQpmUVpRYWhpTTdMYVFCdW5wdXlhZWtLdG5tU241RzlkSHpGeTVNelRSbFJyVWxhVzdVbDRUeExlOEROZ2ZpR2ZCCnpjcmpVK2l3RUJXeS94b3B2aDEzNmlybmV3NTg3RWt3dzQ3QXFhc3gvZStMK2NhSlYySGVMd0dSaE5xR2pIcjkKQ2dSVHpud3F5QjdtTVNXYStWaXBNSHlUVmRCNjRvYjZxbkdqTldvWXdRbUUraU0vL0VrTURzd2JVcTc2R1pKMApsWlRkTlE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3pkSjZ6QmttT3REamcKWnkxR1I0d1EyTlpQSTE2ZWhvc1prSVVqZnNtRWYxQUhveVlRZlVleW5aenNMY1luRGM5N2dKdnliVU5TUkJPTApwNmdjVkREdHJvNkZNc1gvdnVJS0pCRzNvalZ6T3lab3lEdkpRMlVYS1J4RFVPOGdpUDhMcVJRS2NkT3JwT1NnCkNXVU5TSDFNV0dQMEJRWmJNTGk3VEk5MVQ4OGRDRytCMW1CcllWcWR0MElKOVJoVUhrdkhOSGNJMkhBQzVKQzEKcVdJRTN1aFRoR2hzYUV1NlRCWi9xSDdSRWZhbmZncTdRaUxQVHRadlp5MERrMTJ3dVRZQ3VMblZtdEQ1MjlzeQp5UEdlcFU2a0NOMGZOZXVpeVJBZ2YyQ1ZkMVpDNklOVVpiY0FKTjhaRjZvSmwwbml4Lyt1OU1jOUM4dkh4Z0dYCjg5U3dHWFNMQWdNQkFBRUNnZ0VBSmYrYW53UEV6WS9CdjFwNWpya1ZvbmVYb1hnMno5QmpZYzFsTTZma0djY3YKZGY2SXo5TUhQSDM5UFZGUDlQTUtyUGNGam1hdWE1djRtNGlyb3h2OHBFZGk3RGRkRDVNbW44a1ZhMUhRaVk3TAp5a0lqenJFVGxiemh2Q3RHQnhpYkVLZ0RrMWFZNEc1dzdxWXVuSXB0NVoyTnhKelB4TDFqVUYyY3Z0VmdZS0FPCjN2TWY1dENWbS9kL2JBT2xvWnVVc3ArSnc1ZTYvSFN3c3lEdjV2Y2dDQkRXRjFkTFFiYUxCelZDZGJBY0Fma1AKbFUzeGhZMVYyMGU2NmhBbU0veE53MzArSUhvTUlTUTFiQW9MOXVzN3NsTlYxT2ZNZk5hWC83WVdKWFVab1MzNwpyY1IvVXYwZlRtQkhPR3pwK25oaWpLRUlYU1ZESjNxK040amM4Ni9IeVFLQmdRRFhWbzNKSmlia0cvY1JBZ2pICkVqdWROMHJMSGJvVldPanN5ekZmaXg1MHJKTTYwMDJKZURicGdQeEt4ZUtFdGl4ZkVWQmU0eHdqNG9oK1ZubEIKT0dMU3BWcHRRVFRnRVprWXFvVU1iUDIyNHQ2cUZuSXZsTkkwZFJGWDUyS3I2L1FCS0EwWEk3K0I1bTV3Z2hLcgo4ZEQrMGRWNkZzMmxFT0NMWUJKck1weFNIUUtCZ1FEVlY0REVaUlFvVUo5UGRkb3IyK2IweFV2Y3JHeUJ1NlM2CjJZOFJuMzdWUVlBSThHUnlYRkcxTGxZaHpMOWNwd0tUR21SMVhPRTVkMC9mMStaU3h5TVc1d2FSaXU1b0dFK2cKUlNsMXBBdTNUdlEzM1BVNUJzNFhhcHBLOC9BZVk3cG1pd1JhYnRPSFlQa0FHMXNzL3k1d1NjVGUxQXZiWlpsTAo1TmgwdHZvZ3h3S0JnUUNtRkFJOFhlbG15czZ0Vm1WUXE1WkF0YkZBb0VleFNTWXo0cTdNb200MXpCZXRLZVRHCkhtb3pneUNSeHJiaVplSW8zQ0NoWGdXSkE2RUQxMHVqYW9xRkxiUmxTUUl2d2tMU1RFbGJBUUJZdWZiRE5aYVIKYmZVRk1qalRGQWo4MFhrYUh6cWhXeGZMWnQ1TWRYVlRHYWgzcjN3MnNqbWVranFzSThkdzE5TEtYUUtCZ0NoMQp3T0QrUG5WcTNOdklBUWxpV2dtL3hTUmp1dXhidHVFTTA1cEhBbG5WWXovT3YyNEUzaVliVkpCeWNUUlVKQ1BiCjFJT0JpdUZJSkdqU1hFY0VwejMzc0lJM3RBRWY0eklGQzlqWXRMUWVFQ2pzQ2NHMzdhdjVOcXZTV1k2WjRVY0QKUkY4V041MnNJVzBJd3lEa2dGMGhVR25tRXgyWHhodmptYjJBMmkwUEFvR0FUV1kzbXZRVWtZcmU5R0J0alVqYgpDWUx5Mm1VVElKbjVDcmhjTHMvMlh5MkNoVSt5MnhsT3pIcm1vanRIaHFFcnVCK0xyZkpBd3B3cGVRNmxyWnFQCjFGazVKT2c2bmV2U3lDcWF4SDZaenZRMXJ6VzAycm1IMUJrV1BiY0NwKy9VRTIrS3JselZtNHkvZ0ZoRGVGZlcKRUc5UzIzYndKME1JUmF0WVpFQm0wcWs9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + - apiVersion: v1 + kind: Secret + metadata: + namespace: envoy-gateway + name: tls-secret-bar-example-com + type: kubernetes.io/tls + data: # bar.example.com + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUR0VENDQXAyZ0F3SUJBZ0lVU3hoK2piWnYwVHZLV1FSQU1IYncxS1RQWWNzd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5UQTBNakl3TXpBek16bGFGdzB6TlRBME1qQXdNekF6TXpsYU1Ea3hHREFXQmdOVkJBTU1EMkpoCmNpNWxlR0Z0Y0d4bExtTnZiVEVkTUJzR0ExVUVDZ3dVWlhoaGJYQnNaU0J2Y21kaGJtbDZZWFJwYjI0d2dnRWkKTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFEU0FGMjhvSGxQNkYrcXoydXFXcGRXd1dpRApEakRSbUREcFVZWUc0NDlHY2VVMm9tVmxWS2F2dGtBUTM0dFdqendrYzRTbHMxL1lJZWF1U3RhcGVmSGk5OEdECjB4bi8wenVBa3ZGQjhaMTJqeFFvYm92a1doZHFDdUhNMmNoV09ub0tXZXpjNFVkdTBVZkhmalNjQ3MxR3hhOXIKNEdpMFJSajkwOFNUTU1rQW5oRjBaaDdHSEQvM0l1eEx4UW5UMkZYd0F1OTV6V3JqMzRPRUFBZ2FoTXZhdlJmOAozc2dNSVdBZlpVUEk1TitCN1E3L0RwdjJ5TzVQYUtzZ2hpK1dVZ1E1ckFxNUtweHY4TDJhWisxQUFVTUJiREZGCmtYRTd0MFowSTI2NTJKZkV5SmorUDRMaURZRDR5OW9CelpPbHJlQ0lJcGd0dE9VS1YwRnFrQ0JYKzRVWkFnTUIKQUFHamdjQXdnYjB3SFFZRFZSME9CQllFRklPZTliL3BHUWtPd0Y2aGRKYk1nYXNtV1ZMQk1HZ0dBMVVkSXdSaApNRitBRkZtWlNWMCtac2cxY3BVZlVTbXp3Tk5UUkhyUG9UR2tMekF0TVJVd0V3WURWUVFLREF4bGVHRnRjR3hsCklFbHVZeTR4RkRBU0JnTlZCQU1NQzJWNFlXMXdiR1V1WTI5dGdoUVoraXB6VDJwNWdxRm1WUGpHNUtmdGthM00KYmpBTEJnTlZIUThFQkFNQ0F2d3dHZ1lEVlIwUkJCTXdFWUlQWW1GeUxtVjRZVzF3YkdVdVkyOXRNQWtHQTFVZApFZ1FDTUFBd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFCcHIrMktZdXM2NHRsWUtiZHpoaGFMZU5UaHF1MzFhCldHMWFheDljdVdna2VIYUdsdFdkK082Q2IzQng5VTdlTmUvanVtZ3Q0RU9VRUhIaFJIa0NBem1MU21GLzMrM0gKNnVqUEM4eGdISkMvU3V6U3NPRENRTXRqMVg1bjBpT1JsWmU3Ni9KVy9zL1F2R0xzbkwyRXNHbnNVZE1Ca0dIdworOW9oSmp0RFI0Rzkxa0JwT1BGMXk4bXFsUnd5eUZkbkdGYlJvOGc1Vk1CajN3bnFQMTVja1JWam0vdmdlL2o3Ck9lOExwRHpFbVZkNy9ZWEFRWUxWNWU1cVJNSXlUcVlGV2FjcDN4Qm42NEZDNXFIZGlra0VyMlFpekNsZkRqSjQKSTc0L1hTTndabE4relhXdTRQME9wdldoVk0rZlhOUys1QlkxMGhDTXRtdFJtR2NDem9UVXVYaz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktnd2dnU2tBZ0VBQW9JQkFRRFNBRjI4b0hsUDZGK3EKejJ1cVdwZFd3V2lERGpEUm1ERHBVWVlHNDQ5R2NlVTJvbVZsVkthdnRrQVEzNHRXanp3a2M0U2xzMS9ZSWVhdQpTdGFwZWZIaTk4R0QweG4vMHp1QWt2RkI4WjEyanhRb2JvdmtXaGRxQ3VITTJjaFdPbm9LV2V6YzRVZHUwVWZICmZqU2NDczFHeGE5cjRHaTBSUmo5MDhTVE1Na0FuaEYwWmg3R0hELzNJdXhMeFFuVDJGWHdBdTk1eldyajM0T0UKQUFnYWhNdmF2UmY4M3NnTUlXQWZaVVBJNU4rQjdRNy9EcHYyeU81UGFLc2doaStXVWdRNXJBcTVLcHh2OEwyYQpaKzFBQVVNQmJERkZrWEU3dDBaMEkyNjUySmZFeUpqK1A0TGlEWUQ0eTlvQnpaT2xyZUNJSXBndHRPVUtWMEZxCmtDQlgrNFVaQWdNQkFBRUNnZ0VBRnU0YlRpRm5uYVlON0NUQjZOUURlbUdiKzlOczJUWDVBVUQ1bFg3N2dnR2wKdVpWNTVOcWRhTXBKckkzOE5QTm02Y1FEVStTR0xwOWxCTnIvSFhwSFF6VXlXQ2FRekRKUWFQV2lpa1RMb01wMgp0UU45R3U0TGFIVFB1d0o4c1kycERjQkw4TUpZZm0wem5VRFdsY05JTHRZZkZYUm5lbWVoRnZZc25MWFMvTklTCjNvQllUVHZSSjR6d3kvZzIxemN2ZC9uWDhndHFuZ2N2bUxwLzNWSXF2ckVhK05CU2QweFhmWjZCNTMvdVJaUk0KcktXUzFqdzVUVlptOUh2NkhvanN1Y2lBdnlPOVlkTGpGQWVOeDNtdWttbVNwOWp3WjFXMWdCVU0rZ1ROUEdqMAo2WkNYTDJ5YUx5OWlsTFoxNzYvUzB0YlpBa0hJWDlzZzlYbWRiRHdQVVFLQmdRRDc4cVFDSEFhYnY2STBFS2xKCko5MUhBeGZNS3F5MXVWb2kvczZUWlZLQ05FTFkrMkhrdFJaaENLWk5kMVJqMzVpME5kSVFxeG9td2N2RHFnekkKWGdnYVhzUWhpQmRiV3NaTFBmcXVMV0RvNkFqMWZCaVlzL1dvZ05OemFDYllLVjliNktwWmRsTWFyRVArN20rLwpwZmgyZCtDOGJ0dm5MTUM4UXZvUkdTdHlVd0tCZ1FEVllRUm9sNTd0eW9nQlVoeGVHVHZ0blNxcytOei96NWNRCkdsNDVWRDlPb01KT3JZUHM4T29ncFh3bkw1VzIwbllMZWdZSzhkb0M0ZWhPUHYyc3JNMjdaUmZtb1BXZFV2bFYKRUtKcDVMWXNLV2pHcnQ3ZFlzTUVvVG9NejJtbmhnTGdqYnJwbVdJeHlrR3MyaGN2eWtWSG9BSjQwMzh0QjJQVgpza3hDMWt5Vll3S0JnUURxL0lzMW9IZ1ZhZTNhUzdQb2xITFEyYlNuYXlIOHVDeTJ1UnRvNURiSlUvOEpLNlZKClVCRFlYZDNtSUtjb0k1TGtlZEk4VTZtbmZsY1RYcFpmaHp4ZGhBZkFFcE5lVkZMZ09LV0hNTEhUYVI5NS9zMWUKRjNMSFA2aDRXaXJvcitYTjdqcDhDRjFJWW1WazczUnd0bGIvLzUwdmd1STlRa05kRThieWpadzFHd0tCZ0VHVwpBSFRscGNRUmJKeDdVSnpieEwvVWZ6bUxoT0pjUEdLR3VFK0d4YTYxV3dRejhVanpCQVBrMmJSeHUrTGw3Y0s1ClR3SXVOSVNPUzRsQmMxZVFCZXlEdGtUOVZJRjI3NHhtQUlYcjl0SzhKNmhxTjdaMGxOem5jYUJlWUd0TmxiVFAKMjVQUndZenNUaU9ESlgxYS90QjFMazFWTk5IeVk0MWJzSFVheVk5aEFvR0JBTmE2RTR1RWFFSnZQbFR1c3lITQp5NjVSQktPU0t2ZDU1ekZUenN3dXVSRjVob29SaDcvY2JIam1mL3dQYW5UY1N0TndUanpUemZvdTZDSU1qVTVuCmZ1NVZ6bHZnVDQ3SVV5Z2FPcUlKby9iQm9SYXlFSXl4RXRPVzdybXBRUWtnTjBUckV2dnk3SlAwS1M1SWNlUWYKdkhZOVAvUDU2OEVadTJhYURod2tiaHBhCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + - apiVersion: v1 + kind: Secret + metadata: + namespace: envoy-gateway + name: tls-secret-foo-bar-com + type: kubernetes.io/tls + data: # foo.bar.com + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMxakNDQWI0Q0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5UQTBNakV3T1RFNU1qWmFGdzB6TlRBMApNVGt3T1RFNU1qWmFNRFV4RkRBU0JnTlZCQU1NQzJadmJ5NWlZWEl1WTI5dE1SMHdHd1lEVlFRS0RCUmxlR0Z0CmNHeGxJRzl5WjJGdWFYcGhkR2x2YmpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUIKQU5JZzRNWUMvVlV6ZVRMN3Z1ai9pSXNwYTVrd0dyZTFvVGVCd2JYTFk1dmlxRXlicjRraWRQbTVXaFdPdm9GTwpuK0t6QlIzdjRaT20vdzNzMllwTEJjdWtsa3FlQnYzN2kxZFpOOTBrRzR5YitDV01tT3Z3UXFPbkNDV1BvZHBTCitNL0JPbHk2VDRGQ09hT3MwRVFBeDIzb2hxU2h3U0hvVlNLVWdIWTBPTlpLaS8xTjZnVHExb252ajNSM1Z3WHoKb1N0VGl4ODFVUzN0RkZBcnUwaHlOSmJWV3dhMjhMczBLRDJUQlhDMWZTblV3U0VVUzBIQWlIRDFHeE9HT011Twp0SG96ZDkzUGlxNkFJQUIyZEZhdmI5Ujh3azdnU2ZrekV5SFlUT2NaVkFMdFd5Tmx6TnVDQ09uSDFkcWtISUpsClhMcTg5VVNDRDlLeFBoeVN2ODNFN0VrQ0F3RUFBVEFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBWGJ1Z29EenYKVWYwQS91bTNJd1dKUksxWHZFN01jaVUxU08xUHhnOXZ0SXJPclFqZVQ3dGZzajAzQnJObjQxbWVPQkhESzNrdwp0ZHB6SUxoNjJEL1JwM0tPM2UxNDRtZGw4V1BmelBtdmJOdCtlWThNdEo0UlZMT0R4ZVEvTVhGVUQ3aFlXMklWCnJOVnY5aFJrZCt6QmpjSlppRmV0NTlzU2VxR3NZNFdQSnlQVk5sMHBDSlBSM3AwVEZhTm4rclRSUjVhdmVzY3cKRlhqTUpYUHpYRU5ZYXM3TVJxSitVaTZ6Sm9UdVVaTHBPTEtlOFNkeGtoU3IrdkdqYnNPT25yb1I0bXYrRmdvcwo4T1d4RHA4UnpRRUZyeDhBa0tkMzJrRGJCMS9ZWDA0Z3Z0dklzemUwdWx1SEIvY0NSd1ZGZG45WHdOZXVpRmFvCmVUK3BZNVZ1S1Nubkx3PT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktnd2dnU2tBZ0VBQW9JQkFRRFNJT0RHQXYxVk0za3kKKzc3by80aUxLV3VaTUJxM3RhRTNnY0cxeTJPYjRxaE1tNitKSW5UNXVWb1ZqcjZCVHAvaXN3VWQ3K0dUcHY4Tgo3Tm1LU3dYTHBKWktuZ2I5KzR0WFdUZmRKQnVNbS9nbGpKanI4RUtqcHdnbGo2SGFVdmpQd1RwY3VrK0JRam1qCnJOQkVBTWR0Nklha29jRWg2RlVpbElCMk5EaldTb3Y5VGVvRTZ0YUo3NDkwZDFjRjg2RXJVNHNmTlZFdDdSUlEKSzd0SWNqU1cxVnNHdHZDN05DZzlrd1Z3dFgwcDFNRWhGRXRCd0lodzlSc1RoampManJSNk0zZmR6NHF1Z0NBQQpkblJXcjIvVWZNSk80RW41TXhNaDJFem5HVlFDN1ZzalpjemJnZ2pweDlYYXBCeUNaVnk2dlBWRWdnL1NzVDRjCmtyL054T3hKQWdNQkFBRUNnZ0VBSVZYZjh1bjBnTGpLeUlEUnQ2c2FZV0Z2MVh5aE1IWGJIckF5S0FJZFNsUzUKK0hWV2NyNEpxcmh5Qnl0L0k0cHlxUWRYajNsSDR5SENJdFpwYUp3Z1RqOU5MSWRIZXJHV1dJUXA3YVpWeklmTgo1VDhaMzR4ZE5oTkFvcHpYdzRnWU92VmZxZWhReHFQWCt4Um1jZk5oc0JrTWl6K3lJUXYzdmFXcmY1VW5VeTkwCnNvZGhGeVBRYzRVaDdHUGVxZkplU1BtN0xqZEdDQ21pbW9GaVpkV0N3cUdyR01PRzhaKytFZERjWkMyM0dtNVoKdUNEWU4rakkrdzZkTzRnejArUVFrYkhpdkVZSWVWb1d6ZDBwM3ExVjlHZFVTNW5XUFRDelREbU5BMFpIbTZBeQpiSTBCMjRJUC8zbzJuUVZ4M1Y5YjhwMURnTTJsYmxNbW5nWFBuUnFPeFFLQmdRRDFlU1pLeVNBNDZuT2dpeThSCk1USTU2dkNOajR6b2ZoaTR4UUozalJ3N1BtN1RnbDRrOTVuUXdpRDVrcExBYjBlc1JrVG1VMGdYWlVWd3NjVU0KTkZ2Y2tBTThrNlZ1WEpmd1dZOGRiamlTcUNoWkY1Nmp2cVh4MHdIbVlXU0dleitFWDFmT0ZZb1RHK050TkhPcwp0cXFZNzFWTWtjTzZ6K3ZZL3BNZHNCMFZmd0tCZ1FEYkk3VGovY3RkVFFKUDFrMndPcmRtb0tLMXFqQ1FzQWppCkU5RDRnVFJUTnNGeE9SWE9MR0VhRy9ZUktSdkpaOXVNdEloc2VObEkxMHl0RCtZVERnZUZhU2ZHaHFTZEhGYlYKOUJKRFZrelhxZ1ZCMGxOYldkOWh2ekdTV3NnMVVPeG5TQXVTZUk2MkVXYmhrSDdRR1U4N0JHem1rcWdkNkFxVgo2aWhlS08yeU53S0JnUUNlUHhpeGM1RmpQN21FME5WcDV1WXpNa01iYjJSdWFRUDA4WVNTbjVTSW1Nb0hibTdVCnRBNGo1MUlzc2hJTEhuSDlIRnZFaEFIZ216ZTEyOVJrOXNnVm0zMktxc0FtTW1qODJDK0wwSWVGL0FQdTAyeEEKc1dIM1VJbFVCSXN5cXZlYWxZQmNhY1JXWjA4cEVueFQ1bnA2RnloTk1WY1Y4bjVmcUZZYytIRDNid0tCZ1FDNgpmMjN3WnNzUGNYMlpNcHBWYy9NbnpXZ01VWFlaZlNkaU9Ga3RWTkNTVFZSZUpxWVBIQ2ZiajVaZ1Rtc09nbXdRCkdJak9RQjh6NWIra3ZaWWgrMXVkUjd3Sk1nZWdpa0RBdjRKWGVuZlZSeVpJT1ZhbHRSdnVWVWc3OVRUVVl6VisKUkl0TXNYdExLZzR6dzhTWkdDRWM2Z3hBUXVuKzRiODRqTnFrSUJNREN3S0JnQ295YkZIVUdzaUhUenFaOVIyZgpiaTlmT1JRNllUb25kaDRWZjUxUlFVOExtYWxFQkFydHNkYmh3Q01KdXlqR0Q1bTJWOUwyblUyd3hrak9kUkNQCk12dnRiVnBQRDFoWmI0dytlbjZuYzFITUtrZUxGSlljekRSZ0dlY2VwdHBWT3Q3czZUVGVKSWRsT1VPQU1ncTgKdk1mOEw4VzhDY1lLbXpNU3hrMkR0N3NuCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K +httpRoutes: + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: envoy-gateway + name: httproute-1 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + rules: + - matches: + - path: + value: "/" + backendRefs: + - name: service-1 + port: 8080 +services: + - apiVersion: v1 + kind: Service + metadata: + name: service-1 + namespace: envoy-gateway + spec: + clusterIP: 10.11.12.13 + ports: + - port: 8080 + name: http + protocol: TCP + targetPort: 8080 +endpointSlices: + - apiVersion: discovery.k8s.io/v1 + kind: EndpointSlice + metadata: + name: endpointslice-service-1 + namespace: envoy-gateway + labels: + kubernetes.io/service-name: service-1 + addressType: IPv4 + ports: + - name: http + protocol: TCP + port: 8080 + endpoints: + - addresses: + - "7.7.7.7" + conditions: + ready: true diff --git a/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames-and-certs-merged-gateways.out.yaml b/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames-and-certs-merged-gateways.out.yaml new file mode 100644 index 0000000000..5ee5701ec2 --- /dev/null +++ b/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames-and-certs-merged-gateways.out.yaml @@ -0,0 +1,248 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + hostname: '*.example.com' + name: https-1 + port: 443 + protocol: HTTPS + tls: + certificateRefs: + - group: null + kind: null + name: tls-secret-example-com + mode: Terminate + status: + listeners: + - attachedRoutes: 1 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + - lastTransitionTime: null + message: The certificate SAN *.example.com overlaps with the certificate SAN + bar.example.com in listener https-1 of gateway gateway-2. ALPN will default + to HTTP/1.1 to prevent HTTP/2 connection coalescing, unless explicitly configured + via ClientTrafficPolicy + reason: OverlappingCertificates + status: "True" + type: OverlappingTLSConfig + name: https-1 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-2 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + hostname: bar.example.com + name: https-1 + port: 443 + protocol: HTTPS + tls: + certificateRefs: + - group: null + kind: null + name: tls-secret-bar-example-com + mode: Terminate + status: + listeners: + - attachedRoutes: 0 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + - lastTransitionTime: null + message: The certificate SAN bar.example.com overlaps with the certificate + SAN *.example.com in listener https-1 of gateway gateway-1. ALPN will default + to HTTP/1.1 to prevent HTTP/2 connection coalescing, unless explicitly configured + via ClientTrafficPolicy + reason: OverlappingCertificates + status: "True" + type: OverlappingTLSConfig + name: https-1 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-1 + namespace: envoy-gateway + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: / + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway +infraIR: + envoy-gateway-class: + proxy: + config: + apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyProxy + metadata: + creationTimestamp: null + name: test + namespace: envoy-gateway-system + spec: + logging: {} + mergeGateways: true + status: {} + listeners: + - address: null + name: envoy-gateway/gateway-1/https-1 + ports: + - containerPort: 10443 + name: https-443 + protocol: HTTPS + servicePort: 443 + metadata: + labels: + gateway.envoyproxy.io/owning-gatewayclass: envoy-gateway-class + name: envoy-gateway-class + namespace: envoy-gateway-system +xdsIR: + envoy-gateway-class: + accessLog: + json: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*.example.com' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: https-1 + name: envoy-gateway/gateway-1/https-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10443 + routes: + - destination: + name: httproute/envoy-gateway/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + name: httproute/envoy-gateway/httproute-1/rule/0/backend/0 + protocol: HTTP + weight: 1 + hostname: '*.example.com' + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: envoy-gateway + name: httproute/envoy-gateway/httproute-1/rule/0/match/0/*_example_com + pathMatch: + distinct: false + name: "" + prefix: / + tls: + alpnProtocols: null + certificates: + - name: envoy-gateway/tls-secret-example-com + privateKey: '[redacted]' + serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUR3RENDQXFpZ0F3SUJBZ0lVVDRyelIreStHd1VzMm9ydExIZ0k1MzBKeG9Fd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5UQTBNakl3TWpVNU1UQmFGdzB6TlRBME1qQXdNalU1TVRCYU1EVXhGREFTQmdOVkJBTU1DMlp2CmJ5NWlZWEl1WTI5dE1SMHdHd1lEVlFRS0RCUmxlR0Z0Y0d4bElHOXlaMkZ1YVhwaGRHbHZiakNDQVNJd0RRWUoKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTE4wbnJNR1NZNjBPT0JuTFVaSGpCRFkxazhqWHA2RwppeG1RaFNOK3lZUi9VQWVqSmhCOVI3S2RuT3d0eGljTnozdUFtL0p0UTFKRUU0dW5xQnhVTU8ydWpvVXl4ZisrCjRnb2tFYmVpTlhNN0ptaklPOGxEWlJjcEhFTlE3eUNJL3d1cEZBcHgwNnVrNUtBSlpRMUlmVXhZWS9RRkJsc3cKdUx0TWozVlB6eDBJYjRIV1lHdGhXcDIzUWduMUdGUWVTOGMwZHdqWWNBTGtrTFdwWWdUZTZGT0VhR3hvUzdwTQpGbitvZnRFUjlxZCtDcnRDSXM5TzFtOW5MUU9UWGJDNU5nSzR1ZFdhMFBuYjJ6TEk4WjZsVHFRSTNSODE2NkxKCkVDQi9ZSlYzVmtMb2cxUmx0d0FrM3hrWHFnbVhTZUxILzY3MHh6MEx5OGZHQVpmejFMQVpkSXNDQXdFQUFhT0IKenpDQnpEQWRCZ05WSFE0RUZnUVUzbVFodVB2dVl1K0lmN0ZaM010eU9jMWdjQ1V3YUFZRFZSMGpCR0V3WDRBVQpXWmxKWFQ1bXlEVnlsUjlSS2JQQTAxTkVlcytoTWFRdk1DMHhGVEFUQmdOVkJBb01ER1Y0WVcxd2JHVWdTVzVqCkxqRVVNQklHQTFVRUF3d0xaWGhoYlhCc1pTNWpiMjJDRkJuNktuTlBhbm1Db1daVStNYmtwKzJScmN4dU1Bc0cKQTFVZER3UUVBd0lDL0RBcEJnTlZIUkVFSWpBZ2dnOW1iMjh1WlhoaGJYQnNaUzVqYjIyQ0RTb3VaWGhoYlhCcwpaUzVqYjIwd0NRWURWUjBTQkFJd0FEQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFIa2xEbzkvNnRLcDNFd3JSCnJjVStKOUtmUkFGajc5YU1DREpVb0NyM2J6RFIycXQ4ZzlsbDdFSzZaeEtFa0xzWkFlYzBxU0Z1QjBvbzVqZFEKM3VvT2hNK1JKTkZoTldFd3dHWmpMb0FlK2oxaXByN1A5ajdmdFNzck8ra3M3TVNMeTE2RW9IV2Q0eG00Rk5QZQpmUVpRYWhpTTdMYVFCdW5wdXlhZWtLdG5tU241RzlkSHpGeTVNelRSbFJyVWxhVzdVbDRUeExlOEROZ2ZpR2ZCCnpjcmpVK2l3RUJXeS94b3B2aDEzNmlybmV3NTg3RWt3dzQ3QXFhc3gvZStMK2NhSlYySGVMd0dSaE5xR2pIcjkKQ2dSVHpud3F5QjdtTVNXYStWaXBNSHlUVmRCNjRvYjZxbkdqTldvWXdRbUUraU0vL0VrTURzd2JVcTc2R1pKMApsWlRkTlE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + tlsOverlaps: true + - address: 0.0.0.0 + hostnames: + - bar.example.com + isHTTP2: false + metadata: + kind: Gateway + name: gateway-2 + namespace: envoy-gateway + sectionName: https-1 + name: envoy-gateway/gateway-2/https-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10443 + tls: + alpnProtocols: null + certificates: + - name: envoy-gateway/tls-secret-bar-example-com + privateKey: '[redacted]' + serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUR0VENDQXAyZ0F3SUJBZ0lVU3hoK2piWnYwVHZLV1FSQU1IYncxS1RQWWNzd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5UQTBNakl3TXpBek16bGFGdzB6TlRBME1qQXdNekF6TXpsYU1Ea3hHREFXQmdOVkJBTU1EMkpoCmNpNWxlR0Z0Y0d4bExtTnZiVEVkTUJzR0ExVUVDZ3dVWlhoaGJYQnNaU0J2Y21kaGJtbDZZWFJwYjI0d2dnRWkKTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFEU0FGMjhvSGxQNkYrcXoydXFXcGRXd1dpRApEakRSbUREcFVZWUc0NDlHY2VVMm9tVmxWS2F2dGtBUTM0dFdqendrYzRTbHMxL1lJZWF1U3RhcGVmSGk5OEdECjB4bi8wenVBa3ZGQjhaMTJqeFFvYm92a1doZHFDdUhNMmNoV09ub0tXZXpjNFVkdTBVZkhmalNjQ3MxR3hhOXIKNEdpMFJSajkwOFNUTU1rQW5oRjBaaDdHSEQvM0l1eEx4UW5UMkZYd0F1OTV6V3JqMzRPRUFBZ2FoTXZhdlJmOAozc2dNSVdBZlpVUEk1TitCN1E3L0RwdjJ5TzVQYUtzZ2hpK1dVZ1E1ckFxNUtweHY4TDJhWisxQUFVTUJiREZGCmtYRTd0MFowSTI2NTJKZkV5SmorUDRMaURZRDR5OW9CelpPbHJlQ0lJcGd0dE9VS1YwRnFrQ0JYKzRVWkFnTUIKQUFHamdjQXdnYjB3SFFZRFZSME9CQllFRklPZTliL3BHUWtPd0Y2aGRKYk1nYXNtV1ZMQk1HZ0dBMVVkSXdSaApNRitBRkZtWlNWMCtac2cxY3BVZlVTbXp3Tk5UUkhyUG9UR2tMekF0TVJVd0V3WURWUVFLREF4bGVHRnRjR3hsCklFbHVZeTR4RkRBU0JnTlZCQU1NQzJWNFlXMXdiR1V1WTI5dGdoUVoraXB6VDJwNWdxRm1WUGpHNUtmdGthM00KYmpBTEJnTlZIUThFQkFNQ0F2d3dHZ1lEVlIwUkJCTXdFWUlQWW1GeUxtVjRZVzF3YkdVdVkyOXRNQWtHQTFVZApFZ1FDTUFBd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFCcHIrMktZdXM2NHRsWUtiZHpoaGFMZU5UaHF1MzFhCldHMWFheDljdVdna2VIYUdsdFdkK082Q2IzQng5VTdlTmUvanVtZ3Q0RU9VRUhIaFJIa0NBem1MU21GLzMrM0gKNnVqUEM4eGdISkMvU3V6U3NPRENRTXRqMVg1bjBpT1JsWmU3Ni9KVy9zL1F2R0xzbkwyRXNHbnNVZE1Ca0dIdworOW9oSmp0RFI0Rzkxa0JwT1BGMXk4bXFsUnd5eUZkbkdGYlJvOGc1Vk1CajN3bnFQMTVja1JWam0vdmdlL2o3Ck9lOExwRHpFbVZkNy9ZWEFRWUxWNWU1cVJNSXlUcVlGV2FjcDN4Qm42NEZDNXFIZGlra0VyMlFpekNsZkRqSjQKSTc0L1hTTndabE4relhXdTRQME9wdldoVk0rZlhOUys1QlkxMGhDTXRtdFJtR2NDem9UVXVYaz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + tlsOverlaps: true + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 diff --git a/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames-and-certs.out.yaml b/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames-and-certs.out.yaml index d95a9413a8..d7215c2cdb 100644 --- a/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames-and-certs.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames-and-certs.out.yaml @@ -54,9 +54,9 @@ gateways: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: The certificate san *.example.com overlaps with the certificate san - bar.example.com in listener https-2. ALPN is set to HTTP/1.1 to prevent - HTTP/2 connection coalescing + message: The certificate SAN *.example.com overlaps with the certificate SAN + bar.example.com in listener https-2. ALPN will default to HTTP/1.1 to prevent + HTTP/2 connection coalescing, unless explicitly configured via ClientTrafficPolicy reason: OverlappingCertificates status: "True" type: OverlappingTLSConfig @@ -84,9 +84,9 @@ gateways: status: "True" type: ResolvedRefs - lastTransitionTime: null - message: The certificate san bar.example.com overlaps with the certificate - san *.example.com in listener https-1. ALPN is set to HTTP/1.1 to prevent - HTTP/2 connection coalescing + message: The certificate SAN bar.example.com overlaps with the certificate + SAN *.example.com in listener https-1. ALPN will default to HTTP/1.1 to + prevent HTTP/2 connection coalescing, unless explicitly configured via ClientTrafficPolicy reason: OverlappingCertificates status: "True" type: OverlappingTLSConfig diff --git a/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames-merged-gateways.in.yaml b/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames-merged-gateways.in.yaml new file mode 100644 index 0000000000..d6ebccb289 --- /dev/null +++ b/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames-merged-gateways.in.yaml @@ -0,0 +1,125 @@ +envoyProxyForGatewayClass: + apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyProxy + metadata: + name: test + namespace: envoy-gateway-system + spec: + mergeGateways: true +gateways: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: https-1 + protocol: HTTPS + port: 443 + hostname: foo.example.com + allowedRoutes: + namespaces: + from: All + tls: + mode: Terminate + certificateRefs: + - name: tls-secret-example-com + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-2 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: https-1 + protocol: HTTPS + port: 443 + hostname: "*.example.com" + allowedRoutes: + namespaces: + from: All + tls: + mode: Terminate + certificateRefs: + - name: tls-secret-example-com + - name: https-2 + protocol: HTTPS + port: 443 + hostname: "foo.bar.com" + allowedRoutes: + namespaces: + from: All + tls: + mode: Terminate + certificateRefs: + - name: tls-secret-foo-bar-com +secrets: + - apiVersion: v1 + kind: Secret + metadata: + namespace: envoy-gateway + name: tls-secret-example-com + type: kubernetes.io/tls + data: # *.example.com + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMyRENDQWNBQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5UQTBNakV3T1RFd05ETmFGdzB6TlRBMApNVGt3T1RFd05ETmFNRGN4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHhIVEFiQmdOVkJBb01GR1Y0CllXMXdiR1VnYjNKbllXNXBlbUYwYVc5dU1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0MKQVFFQXY0anl4TUh1YzQzMHdvWkk4M1JSMXVxU2gvbm9MVWVPdDZnMkNKaFVFYXNaeUNOMzN3bFRRRDE0SEhkSwpOb1k4SThWd1pOZFZCNGpjRzlnb3dDVmVQY3lqRzZPaGl1aUZNWnU2NzV6dWZEWnRlRTNEY3lTbFgrY2lSbVZZCkNuSmk3QkV3NlJMUUJ0bVV6WGxtYmRpVXE5djJwalVBL2R3ZnRLRHRZTHFrVytvTSt5MWg3cjRJV0JVK2RVcU0KcGtTem5VSCtKN1JoRkFsdytmRWlVSFRLemlCMkVtdjc3Mi91bS96NHdMWnJIeWNGbmc4L1FCM0JIUktXVTV4eQp3bWNTQ2xrVlMvWWNpMFVXcnR2eGhwck9wTUhQUGR2QkZ2M2NaWGNpUUJjb0ZNcGxsQzV0UURvdWJ0dEV1d3JpCi8rVktKWkUrSVl4ei9YeUd3Y3dJRnIzWG13SURBUUFCTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFBU3VLaE8KcGtwL1VSclphbEU0OUlnc0xkN3hSTlBhREVkQ1RWZ3Qvc3praUhnSDB1NDBVaVV6KzVzaDRpdlJOazRqTm1zRwprb3FwQlBVS3pvVmtrSTcxUWQ4bHh1VzF2dkxZMXVvM0RIS2svdDFpUWVZWWpERlk3YzUxVG1BT015WUdKTlhxCi9EbW84UWgzaFB1RnI3a29kUjBLSkJyc0RsMEhoWVBjUnpWOW1sQ2lrU1B4THJGTUNwZGx0QUw2UEprSVpucUgKc1g5dEtVZk1uYW5jMkpHZTZVTDE1ODBEV2xQTUcrMU1qRElCVXdxWWYzaWNKb0NYclAwbzNmckRKcTE2VnpidApkalRtVGswakx1bGkvQ2JCZzh4dWp4emo4bmRPcVNkd05kd091OWoxSmZ2Q0I1RjZ4S0VTenowOVo5TzlOZUM5CjMrd1pLTlRSOXVEdDRKNksKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktnd2dnU2tBZ0VBQW9JQkFRQy9pUExFd2U1empmVEMKaGtqemRGSFc2cEtIK2VndFI0NjNxRFlJbUZRUnF4bklJM2ZmQ1ZOQVBYZ2NkMG8yaGp3anhYQmsxMVVIaU53YgoyQ2pBSlY0OXpLTWJvNkdLNklVeG03cnZuTzU4Tm0xNFRjTnpKS1ZmNXlKR1pWZ0tjbUxzRVREcEV0QUcyWlROCmVXWnQySlNyMi9hbU5RRDkzQiswb08xZ3VxUmI2Z3o3TFdIdXZnaFlGVDUxU295bVJMT2RRZjRudEdFVUNYRDUKOFNKUWRNck9JSFlTYS92dmIrNmIvUGpBdG1zZkp3V2VEejlBSGNFZEVwWlRuSExDWnhJS1dSVkw5aHlMUlJhdQoyL0dHbXM2a3djODkyOEVXL2R4bGR5SkFGeWdVeW1XVUxtMUFPaTV1MjBTN0N1TC81VW9sa1Q0aGpIUDlmSWJCCnpBZ1d2ZGViQWdNQkFBRUNnZ0VBVW1UV3pvYUFqZXdjeFF1Z1dUNktNREpqaTZRWldWVWxrMk1FcjRqYjdXZlYKNU85QkUweS9KK3pwZlJGaDl2ZWk2bDUyZmFMV1BMSUd3ZUdva2hQaEtTT2RiUGZrdDgxVDh1WERzbTBuZUg2dgpjK2U3OHczcUtFblZTRVF6YmZjTUQvSkxRSkJydGU2bW9RZWU1UlVjeTV1SnpMRVRkcUZaY0Vva0k0N1d3b1M3CnBUUkM1ZDdMRVJEYlcrQStDaXdmZ2dXdS9Kb25nUXN6SjB1OEJKUSt1dXBXc0FVR213c0JPQWxPTk96ZGE3cTMKMVl6endRck9mRDI1U2psZlYxWkNpZ3VuTzVwL3ZvbllhVkF6NE45T0I4Vk9uRnJKMm91YWFGWkNPUjZKTzl2MApTWVdZU0ZrS3duUlVyTUpac25mTWVjdCtPM3NmZXN5VHlPSG9DRElvb1FLQmdRRGxNdFVDODRNNkM5aHAxYURuCm9EM2VpVG1GNE1NTlI4aWVGdXVOY1AyQkRTS1lUREVEWmJqNTNEd0E5VGJvQlRoYUQwOS8zZ3VpWlo4cFo3K1kKWDlsMDM5R2xZSmdqV2tJUU9HZVFnQld6ZFpROXM3elRHeVZmL2g5SE5OU2l5VDBaS2ZyZ3U5UFU1aFY1bitnTApkYkw5UDVYNmxSWVRKL1hkMVprdkZ1Y0ZPd0tCZ1FEVjdxTmlMbGQ2Vmo2MDA1SHRaQXRCNVpTVjF5U21JZ0x3CldTbnJKdjE0cVhNMURERndsdlVkSHNqb0ZXdlU2UnNIQ0FyMEZ5cHY1MytCdDB0c3c1NFZHUUNJQUw2dWJXbjkKR3BpUUVndS9SRmRuTTFnNGY5RURZQyt4UGt0R2lvNEhORHVmaURsbzQ2bVEwV0oyNFZ3TVZNUit1TFp3NkRzdQp2SnhqNkFQUklRS0JnUUNRa29iUXJML2F6bnY5RGpiSHhFa2laUmEydnZicUdweU9NOUR6VUJGbjVOd3NpdXJqCnhMZHdUQjVCVUd3STRMb1IvTlJkeUxjNEFiZnF5em1NcVBFbkNzTlgrTjBlZDZGeVQ5SHIwUTlmT3N4K096RGgKVEo4L3RMRVFIbC8rS3NmeVpvdU1WSTRqSGRydjlCRFBvYmQ4alM1U2VOWUswVXNDV2VpZFRtbjgzd0tCZ1FDVgpCWXJpVlkyeU5tbXY1TUQrTUhaM0RNbVlKeW5zWUR6VDJBaVBPYlhQVzVwWkZZbEsrSnorRC9lN1UxQ3VHME1zCmZybkNsbkNGU3lsUzNxKzNyL3hxamVRRTJSLzZ1VlRmYnF0ZmtIS0daY0RNcnNPQmQrZk5CaSt5czhZVCtXZysKTkhCa0RLeVJHQ1dDTDVqN1hyaVVEbWhpTGFGSXZUeWNyZDN5NmlmZWdRS0JnQzRmUTVxcWpMREEycDJ1MGpjeQpwUjlVcTRMd2Y2VXlJNnB3UCtTRmd6Rmw4UmNFM3VnOERFRDVmRVNJUEhIeUFOeWtrd1RGdm01L0d5VGZTZ0g0Cko3bU9YQzgxZ0E1V3I1TWdWN2JOME5GdXkwNFRJT0NGNG9QUHhwM1h0OVNTQmpGekNsS1FYSkFpV0RXL1UyWXIKYlV6U3VNU2J1NmZtTFRtc09LR0VHY1hlCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + - apiVersion: v1 + kind: Secret + metadata: + namespace: envoy-gateway + name: tls-secret-foo-bar-com + type: kubernetes.io/tls + data: # foo.bar.com + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMxakNDQWI0Q0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5UQTBNakV3T1RFNU1qWmFGdzB6TlRBMApNVGt3T1RFNU1qWmFNRFV4RkRBU0JnTlZCQU1NQzJadmJ5NWlZWEl1WTI5dE1SMHdHd1lEVlFRS0RCUmxlR0Z0CmNHeGxJRzl5WjJGdWFYcGhkR2x2YmpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUIKQU5JZzRNWUMvVlV6ZVRMN3Z1ai9pSXNwYTVrd0dyZTFvVGVCd2JYTFk1dmlxRXlicjRraWRQbTVXaFdPdm9GTwpuK0t6QlIzdjRaT20vdzNzMllwTEJjdWtsa3FlQnYzN2kxZFpOOTBrRzR5YitDV01tT3Z3UXFPbkNDV1BvZHBTCitNL0JPbHk2VDRGQ09hT3MwRVFBeDIzb2hxU2h3U0hvVlNLVWdIWTBPTlpLaS8xTjZnVHExb252ajNSM1Z3WHoKb1N0VGl4ODFVUzN0RkZBcnUwaHlOSmJWV3dhMjhMczBLRDJUQlhDMWZTblV3U0VVUzBIQWlIRDFHeE9HT011Twp0SG96ZDkzUGlxNkFJQUIyZEZhdmI5Ujh3azdnU2ZrekV5SFlUT2NaVkFMdFd5Tmx6TnVDQ09uSDFkcWtISUpsClhMcTg5VVNDRDlLeFBoeVN2ODNFN0VrQ0F3RUFBVEFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBWGJ1Z29EenYKVWYwQS91bTNJd1dKUksxWHZFN01jaVUxU08xUHhnOXZ0SXJPclFqZVQ3dGZzajAzQnJObjQxbWVPQkhESzNrdwp0ZHB6SUxoNjJEL1JwM0tPM2UxNDRtZGw4V1BmelBtdmJOdCtlWThNdEo0UlZMT0R4ZVEvTVhGVUQ3aFlXMklWCnJOVnY5aFJrZCt6QmpjSlppRmV0NTlzU2VxR3NZNFdQSnlQVk5sMHBDSlBSM3AwVEZhTm4rclRSUjVhdmVzY3cKRlhqTUpYUHpYRU5ZYXM3TVJxSitVaTZ6Sm9UdVVaTHBPTEtlOFNkeGtoU3IrdkdqYnNPT25yb1I0bXYrRmdvcwo4T1d4RHA4UnpRRUZyeDhBa0tkMzJrRGJCMS9ZWDA0Z3Z0dklzemUwdWx1SEIvY0NSd1ZGZG45WHdOZXVpRmFvCmVUK3BZNVZ1S1Nubkx3PT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktnd2dnU2tBZ0VBQW9JQkFRRFNJT0RHQXYxVk0za3kKKzc3by80aUxLV3VaTUJxM3RhRTNnY0cxeTJPYjRxaE1tNitKSW5UNXVWb1ZqcjZCVHAvaXN3VWQ3K0dUcHY4Tgo3Tm1LU3dYTHBKWktuZ2I5KzR0WFdUZmRKQnVNbS9nbGpKanI4RUtqcHdnbGo2SGFVdmpQd1RwY3VrK0JRam1qCnJOQkVBTWR0Nklha29jRWg2RlVpbElCMk5EaldTb3Y5VGVvRTZ0YUo3NDkwZDFjRjg2RXJVNHNmTlZFdDdSUlEKSzd0SWNqU1cxVnNHdHZDN05DZzlrd1Z3dFgwcDFNRWhGRXRCd0lodzlSc1RoampManJSNk0zZmR6NHF1Z0NBQQpkblJXcjIvVWZNSk80RW41TXhNaDJFem5HVlFDN1ZzalpjemJnZ2pweDlYYXBCeUNaVnk2dlBWRWdnL1NzVDRjCmtyL054T3hKQWdNQkFBRUNnZ0VBSVZYZjh1bjBnTGpLeUlEUnQ2c2FZV0Z2MVh5aE1IWGJIckF5S0FJZFNsUzUKK0hWV2NyNEpxcmh5Qnl0L0k0cHlxUWRYajNsSDR5SENJdFpwYUp3Z1RqOU5MSWRIZXJHV1dJUXA3YVpWeklmTgo1VDhaMzR4ZE5oTkFvcHpYdzRnWU92VmZxZWhReHFQWCt4Um1jZk5oc0JrTWl6K3lJUXYzdmFXcmY1VW5VeTkwCnNvZGhGeVBRYzRVaDdHUGVxZkplU1BtN0xqZEdDQ21pbW9GaVpkV0N3cUdyR01PRzhaKytFZERjWkMyM0dtNVoKdUNEWU4rakkrdzZkTzRnejArUVFrYkhpdkVZSWVWb1d6ZDBwM3ExVjlHZFVTNW5XUFRDelREbU5BMFpIbTZBeQpiSTBCMjRJUC8zbzJuUVZ4M1Y5YjhwMURnTTJsYmxNbW5nWFBuUnFPeFFLQmdRRDFlU1pLeVNBNDZuT2dpeThSCk1USTU2dkNOajR6b2ZoaTR4UUozalJ3N1BtN1RnbDRrOTVuUXdpRDVrcExBYjBlc1JrVG1VMGdYWlVWd3NjVU0KTkZ2Y2tBTThrNlZ1WEpmd1dZOGRiamlTcUNoWkY1Nmp2cVh4MHdIbVlXU0dleitFWDFmT0ZZb1RHK050TkhPcwp0cXFZNzFWTWtjTzZ6K3ZZL3BNZHNCMFZmd0tCZ1FEYkk3VGovY3RkVFFKUDFrMndPcmRtb0tLMXFqQ1FzQWppCkU5RDRnVFJUTnNGeE9SWE9MR0VhRy9ZUktSdkpaOXVNdEloc2VObEkxMHl0RCtZVERnZUZhU2ZHaHFTZEhGYlYKOUJKRFZrelhxZ1ZCMGxOYldkOWh2ekdTV3NnMVVPeG5TQXVTZUk2MkVXYmhrSDdRR1U4N0JHem1rcWdkNkFxVgo2aWhlS08yeU53S0JnUUNlUHhpeGM1RmpQN21FME5WcDV1WXpNa01iYjJSdWFRUDA4WVNTbjVTSW1Nb0hibTdVCnRBNGo1MUlzc2hJTEhuSDlIRnZFaEFIZ216ZTEyOVJrOXNnVm0zMktxc0FtTW1qODJDK0wwSWVGL0FQdTAyeEEKc1dIM1VJbFVCSXN5cXZlYWxZQmNhY1JXWjA4cEVueFQ1bnA2RnloTk1WY1Y4bjVmcUZZYytIRDNid0tCZ1FDNgpmMjN3WnNzUGNYMlpNcHBWYy9NbnpXZ01VWFlaZlNkaU9Ga3RWTkNTVFZSZUpxWVBIQ2ZiajVaZ1Rtc09nbXdRCkdJak9RQjh6NWIra3ZaWWgrMXVkUjd3Sk1nZWdpa0RBdjRKWGVuZlZSeVpJT1ZhbHRSdnVWVWc3OVRUVVl6VisKUkl0TXNYdExLZzR6dzhTWkdDRWM2Z3hBUXVuKzRiODRqTnFrSUJNREN3S0JnQ295YkZIVUdzaUhUenFaOVIyZgpiaTlmT1JRNllUb25kaDRWZjUxUlFVOExtYWxFQkFydHNkYmh3Q01KdXlqR0Q1bTJWOUwyblUyd3hrak9kUkNQCk12dnRiVnBQRDFoWmI0dytlbjZuYzFITUtrZUxGSlljekRSZ0dlY2VwdHBWT3Q3czZUVGVKSWRsT1VPQU1ncTgKdk1mOEw4VzhDY1lLbXpNU3hrMkR0N3NuCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K +httpRoutes: + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: envoy-gateway + name: httproute-1 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + rules: + - matches: + - path: + value: "/" + backendRefs: + - name: service-1 + port: 8080 +services: + - apiVersion: v1 + kind: Service + metadata: + name: service-1 + namespace: envoy-gateway + spec: + clusterIP: 10.11.12.13 + ports: + - port: 8080 + name: http + protocol: TCP + targetPort: 8080 +endpointSlices: + - apiVersion: discovery.k8s.io/v1 + kind: EndpointSlice + metadata: + name: endpointslice-service-1 + namespace: envoy-gateway + labels: + kubernetes.io/service-name: service-1 + addressType: IPv4 + ports: + - name: http + protocol: TCP + port: 8080 + endpoints: + - addresses: + - "7.7.7.7" + conditions: + ready: true diff --git a/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames-merged-gateways.out.yaml b/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames-merged-gateways.out.yaml new file mode 100644 index 0000000000..31a1f29565 --- /dev/null +++ b/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames-merged-gateways.out.yaml @@ -0,0 +1,304 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + hostname: foo.example.com + name: https-1 + port: 443 + protocol: HTTPS + tls: + certificateRefs: + - group: null + kind: null + name: tls-secret-example-com + mode: Terminate + status: + listeners: + - attachedRoutes: 1 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + - lastTransitionTime: null + message: The hostname foo.example.com overlaps with the hostname *.example.com + in listener https-1 of gateway gateway-2. ALPN will default to HTTP/1.1 + to prevent HTTP/2 connection coalescing, unless explicitly configured via + ClientTrafficPolicy + reason: OverlappingHostnames + status: "True" + type: OverlappingTLSConfig + name: https-1 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-2 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + hostname: '*.example.com' + name: https-1 + port: 443 + protocol: HTTPS + tls: + certificateRefs: + - group: null + kind: null + name: tls-secret-example-com + mode: Terminate + - allowedRoutes: + namespaces: + from: All + hostname: foo.bar.com + name: https-2 + port: 443 + protocol: HTTPS + tls: + certificateRefs: + - group: null + kind: null + name: tls-secret-foo-bar-com + mode: Terminate + status: + listeners: + - attachedRoutes: 0 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + - lastTransitionTime: null + message: The hostname *.example.com overlaps with the hostname foo.example.com + in listener https-1 of gateway gateway-1. ALPN will default to HTTP/1.1 + to prevent HTTP/2 connection coalescing, unless explicitly configured via + ClientTrafficPolicy + reason: OverlappingHostnames + status: "True" + type: OverlappingTLSConfig + name: https-1 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute + - attachedRoutes: 0 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: https-2 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-1 + namespace: envoy-gateway + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: / + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway +infraIR: + envoy-gateway-class: + proxy: + config: + apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyProxy + metadata: + creationTimestamp: null + name: test + namespace: envoy-gateway-system + spec: + logging: {} + mergeGateways: true + status: {} + listeners: + - address: null + name: envoy-gateway/gateway-1/https-1 + ports: + - containerPort: 10443 + name: https-443 + protocol: HTTPS + servicePort: 443 + metadata: + labels: + gateway.envoyproxy.io/owning-gatewayclass: envoy-gateway-class + name: envoy-gateway-class + namespace: envoy-gateway-system +xdsIR: + envoy-gateway-class: + accessLog: + json: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - foo.example.com + isHTTP2: false + metadata: + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: https-1 + name: envoy-gateway/gateway-1/https-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10443 + routes: + - destination: + name: httproute/envoy-gateway/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + name: httproute/envoy-gateway/httproute-1/rule/0/backend/0 + protocol: HTTP + weight: 1 + hostname: foo.example.com + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: envoy-gateway + name: httproute/envoy-gateway/httproute-1/rule/0/match/0/foo_example_com + pathMatch: + distinct: false + name: "" + prefix: / + tls: + alpnProtocols: null + certificates: + - name: envoy-gateway/tls-secret-example-com + privateKey: '[redacted]' + serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMyRENDQWNBQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5UQTBNakV3T1RFd05ETmFGdzB6TlRBMApNVGt3T1RFd05ETmFNRGN4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHhIVEFiQmdOVkJBb01GR1Y0CllXMXdiR1VnYjNKbllXNXBlbUYwYVc5dU1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0MKQVFFQXY0anl4TUh1YzQzMHdvWkk4M1JSMXVxU2gvbm9MVWVPdDZnMkNKaFVFYXNaeUNOMzN3bFRRRDE0SEhkSwpOb1k4SThWd1pOZFZCNGpjRzlnb3dDVmVQY3lqRzZPaGl1aUZNWnU2NzV6dWZEWnRlRTNEY3lTbFgrY2lSbVZZCkNuSmk3QkV3NlJMUUJ0bVV6WGxtYmRpVXE5djJwalVBL2R3ZnRLRHRZTHFrVytvTSt5MWg3cjRJV0JVK2RVcU0KcGtTem5VSCtKN1JoRkFsdytmRWlVSFRLemlCMkVtdjc3Mi91bS96NHdMWnJIeWNGbmc4L1FCM0JIUktXVTV4eQp3bWNTQ2xrVlMvWWNpMFVXcnR2eGhwck9wTUhQUGR2QkZ2M2NaWGNpUUJjb0ZNcGxsQzV0UURvdWJ0dEV1d3JpCi8rVktKWkUrSVl4ei9YeUd3Y3dJRnIzWG13SURBUUFCTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFBU3VLaE8KcGtwL1VSclphbEU0OUlnc0xkN3hSTlBhREVkQ1RWZ3Qvc3praUhnSDB1NDBVaVV6KzVzaDRpdlJOazRqTm1zRwprb3FwQlBVS3pvVmtrSTcxUWQ4bHh1VzF2dkxZMXVvM0RIS2svdDFpUWVZWWpERlk3YzUxVG1BT015WUdKTlhxCi9EbW84UWgzaFB1RnI3a29kUjBLSkJyc0RsMEhoWVBjUnpWOW1sQ2lrU1B4THJGTUNwZGx0QUw2UEprSVpucUgKc1g5dEtVZk1uYW5jMkpHZTZVTDE1ODBEV2xQTUcrMU1qRElCVXdxWWYzaWNKb0NYclAwbzNmckRKcTE2VnpidApkalRtVGswakx1bGkvQ2JCZzh4dWp4emo4bmRPcVNkd05kd091OWoxSmZ2Q0I1RjZ4S0VTenowOVo5TzlOZUM5CjMrd1pLTlRSOXVEdDRKNksKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + tlsOverlaps: true + - address: 0.0.0.0 + hostnames: + - '*.example.com' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-2 + namespace: envoy-gateway + sectionName: https-1 + name: envoy-gateway/gateway-2/https-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10443 + tls: + alpnProtocols: null + certificates: + - name: envoy-gateway/tls-secret-example-com + privateKey: '[redacted]' + serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMyRENDQWNBQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5UQTBNakV3T1RFd05ETmFGdzB6TlRBMApNVGt3T1RFd05ETmFNRGN4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHhIVEFiQmdOVkJBb01GR1Y0CllXMXdiR1VnYjNKbllXNXBlbUYwYVc5dU1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0MKQVFFQXY0anl4TUh1YzQzMHdvWkk4M1JSMXVxU2gvbm9MVWVPdDZnMkNKaFVFYXNaeUNOMzN3bFRRRDE0SEhkSwpOb1k4SThWd1pOZFZCNGpjRzlnb3dDVmVQY3lqRzZPaGl1aUZNWnU2NzV6dWZEWnRlRTNEY3lTbFgrY2lSbVZZCkNuSmk3QkV3NlJMUUJ0bVV6WGxtYmRpVXE5djJwalVBL2R3ZnRLRHRZTHFrVytvTSt5MWg3cjRJV0JVK2RVcU0KcGtTem5VSCtKN1JoRkFsdytmRWlVSFRLemlCMkVtdjc3Mi91bS96NHdMWnJIeWNGbmc4L1FCM0JIUktXVTV4eQp3bWNTQ2xrVlMvWWNpMFVXcnR2eGhwck9wTUhQUGR2QkZ2M2NaWGNpUUJjb0ZNcGxsQzV0UURvdWJ0dEV1d3JpCi8rVktKWkUrSVl4ei9YeUd3Y3dJRnIzWG13SURBUUFCTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFBU3VLaE8KcGtwL1VSclphbEU0OUlnc0xkN3hSTlBhREVkQ1RWZ3Qvc3praUhnSDB1NDBVaVV6KzVzaDRpdlJOazRqTm1zRwprb3FwQlBVS3pvVmtrSTcxUWQ4bHh1VzF2dkxZMXVvM0RIS2svdDFpUWVZWWpERlk3YzUxVG1BT015WUdKTlhxCi9EbW84UWgzaFB1RnI3a29kUjBLSkJyc0RsMEhoWVBjUnpWOW1sQ2lrU1B4THJGTUNwZGx0QUw2UEprSVpucUgKc1g5dEtVZk1uYW5jMkpHZTZVTDE1ODBEV2xQTUcrMU1qRElCVXdxWWYzaWNKb0NYclAwbzNmckRKcTE2VnpidApkalRtVGswakx1bGkvQ2JCZzh4dWp4emo4bmRPcVNkd05kd091OWoxSmZ2Q0I1RjZ4S0VTenowOVo5TzlOZUM5CjMrd1pLTlRSOXVEdDRKNksKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + tlsOverlaps: true + - address: 0.0.0.0 + hostnames: + - foo.bar.com + isHTTP2: false + metadata: + kind: Gateway + name: gateway-2 + namespace: envoy-gateway + sectionName: https-2 + name: envoy-gateway/gateway-2/https-2 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10443 + tls: + alpnProtocols: null + certificates: + - name: envoy-gateway/tls-secret-foo-bar-com + privateKey: '[redacted]' + serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMxakNDQWI0Q0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5UQTBNakV3T1RFNU1qWmFGdzB6TlRBMApNVGt3T1RFNU1qWmFNRFV4RkRBU0JnTlZCQU1NQzJadmJ5NWlZWEl1WTI5dE1SMHdHd1lEVlFRS0RCUmxlR0Z0CmNHeGxJRzl5WjJGdWFYcGhkR2x2YmpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUIKQU5JZzRNWUMvVlV6ZVRMN3Z1ai9pSXNwYTVrd0dyZTFvVGVCd2JYTFk1dmlxRXlicjRraWRQbTVXaFdPdm9GTwpuK0t6QlIzdjRaT20vdzNzMllwTEJjdWtsa3FlQnYzN2kxZFpOOTBrRzR5YitDV01tT3Z3UXFPbkNDV1BvZHBTCitNL0JPbHk2VDRGQ09hT3MwRVFBeDIzb2hxU2h3U0hvVlNLVWdIWTBPTlpLaS8xTjZnVHExb252ajNSM1Z3WHoKb1N0VGl4ODFVUzN0RkZBcnUwaHlOSmJWV3dhMjhMczBLRDJUQlhDMWZTblV3U0VVUzBIQWlIRDFHeE9HT011Twp0SG96ZDkzUGlxNkFJQUIyZEZhdmI5Ujh3azdnU2ZrekV5SFlUT2NaVkFMdFd5Tmx6TnVDQ09uSDFkcWtISUpsClhMcTg5VVNDRDlLeFBoeVN2ODNFN0VrQ0F3RUFBVEFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBWGJ1Z29EenYKVWYwQS91bTNJd1dKUksxWHZFN01jaVUxU08xUHhnOXZ0SXJPclFqZVQ3dGZzajAzQnJObjQxbWVPQkhESzNrdwp0ZHB6SUxoNjJEL1JwM0tPM2UxNDRtZGw4V1BmelBtdmJOdCtlWThNdEo0UlZMT0R4ZVEvTVhGVUQ3aFlXMklWCnJOVnY5aFJrZCt6QmpjSlppRmV0NTlzU2VxR3NZNFdQSnlQVk5sMHBDSlBSM3AwVEZhTm4rclRSUjVhdmVzY3cKRlhqTUpYUHpYRU5ZYXM3TVJxSitVaTZ6Sm9UdVVaTHBPTEtlOFNkeGtoU3IrdkdqYnNPT25yb1I0bXYrRmdvcwo4T1d4RHA4UnpRRUZyeDhBa0tkMzJrRGJCMS9ZWDA0Z3Z0dklzemUwdWx1SEIvY0NSd1ZGZG45WHdOZXVpRmFvCmVUK3BZNVZ1S1Nubkx3PT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 diff --git a/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames.out.yaml b/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames.out.yaml index 4f60b08c32..aaa48f964c 100644 --- a/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames.out.yaml @@ -68,8 +68,8 @@ gateways: type: ResolvedRefs - lastTransitionTime: null message: The hostname foo.example.com overlaps with the hostname *.example.com - in listener https-2. ALPN is set to HTTP/1.1 to prevent HTTP/2 connection - coalescing + in listener https-2. ALPN will default to HTTP/1.1 to prevent HTTP/2 connection + coalescing, unless explicitly configured via ClientTrafficPolicy reason: OverlappingHostnames status: "True" type: OverlappingTLSConfig @@ -98,8 +98,8 @@ gateways: type: ResolvedRefs - lastTransitionTime: null message: The hostname *.example.com overlaps with the hostname foo.example.com - in listener https-1. ALPN is set to HTTP/1.1 to prevent HTTP/2 connection - coalescing + in listener https-1. ALPN will default to HTTP/1.1 to prevent HTTP/2 connection + coalescing, unless explicitly configured via ClientTrafficPolicy reason: OverlappingHostnames status: "True" type: OverlappingTLSConfig diff --git a/internal/gatewayapi/translator.go b/internal/gatewayapi/translator.go index 7666322d76..228c02362d 100644 --- a/internal/gatewayapi/translator.go +++ b/internal/gatewayapi/translator.go @@ -308,6 +308,10 @@ func (t *Translator) InitIRs(gateways []*GatewayContext) (map[string]*ir.Xds, ma gwInfraIR.Proxy.Namespace = t.ControllerNamespace if t.GatewayNamespaceMode { gwInfraIR.Proxy.Namespace = gateway.Namespace + gwInfraIR.Proxy.GetProxyMetadata().OwnerReference = &ir.ResourceMetadata{ + Kind: resource.KindGateway, + Name: gateway.Name, + } } // save the IR references in the map before the translation starts xdsIR[irKey] = gwXdsIR diff --git a/internal/gatewayapi/translator_test.go b/internal/gatewayapi/translator_test.go index 5193944295..717f292e71 100644 --- a/internal/gatewayapi/translator_test.go +++ b/internal/gatewayapi/translator_test.go @@ -41,7 +41,7 @@ import ( "github.com/envoyproxy/gateway/internal/wasm" ) -func mustUnmarshal(t *testing.T, val []byte, out interface{}) { +func mustUnmarshal(t *testing.T, val []byte, out any) { require.NoError(t, yaml.UnmarshalStrict(val, out, yaml.DisallowUnknownFields)) } diff --git a/internal/infrastructure/kubernetes/proxy/resource.go b/internal/infrastructure/kubernetes/proxy/resource.go index 481427ec00..66999bbe70 100644 --- a/internal/infrastructure/kubernetes/proxy/resource.go +++ b/internal/infrastructure/kubernetes/proxy/resource.go @@ -26,8 +26,8 @@ import ( const ( // envoyContainerName is the name of the Envoy container. envoyContainerName = "envoy" - // envoyNsEnvVar is the name of the Envoy Gateway namespace environment variable. - envoyNsEnvVar = "ENVOY_GATEWAY_NAMESPACE" + // envoyNsEnvVar is the name of the Envoy pod namespace environment variable. + envoyNsEnvVar = "ENVOY_POD_NAMESPACE" // envoyPodEnvVar is the name of the Envoy pod name environment variable. envoyPodEnvVar = "ENVOY_POD_NAME" // envoyZoneEnvVar is the Envoy pod locality zone name @@ -131,7 +131,7 @@ func expectedProxyContainers(infra *ir.ProxyInfra, ImagePullPolicy: corev1.PullIfNotPresent, Command: []string{"envoy"}, Args: args, - Env: expectedContainerEnv(containerSpec, controllerNamespace), + Env: expectedContainerEnv(containerSpec), Resources: *containerSpec.Resources, SecurityContext: expectedEnvoySecurityContext(containerSpec), Ports: ports, @@ -193,7 +193,7 @@ func expectedProxyContainers(infra *ir.ProxyInfra, ImagePullPolicy: corev1.PullIfNotPresent, Command: []string{"envoy-gateway"}, Args: expectedShutdownManagerArgs(shutdownConfig), - Env: expectedContainerEnv(nil, controllerNamespace), + Env: expectedContainerEnv(nil), Resources: *egv1a1.DefaultShutdownManagerContainerResourceRequirements(), TerminationMessagePolicy: corev1.TerminationMessageReadFile, TerminationMessagePath: "/dev/termination-log", @@ -409,11 +409,25 @@ func expectedVolumes(name string, gatewayNamespacedMode bool, pod *egv1a1.Kubern } // expectedContainerEnv returns expected proxy container envs. -func expectedContainerEnv(containerSpec *egv1a1.KubernetesContainerSpec, controllerNamespace string) []corev1.EnvVar { +func expectedContainerEnv(containerSpec *egv1a1.KubernetesContainerSpec) []corev1.EnvVar { env := []corev1.EnvVar{ { - Name: envoyNsEnvVar, - Value: controllerNamespace, + Name: envoyNsEnvVar, + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + APIVersion: "v1", + FieldPath: "metadata.namespace", + }, + }, + }, + { + Name: envoyPodEnvVar, + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + APIVersion: "v1", + FieldPath: "metadata.name", + }, + }, }, { Name: envoyZoneEnvVar, @@ -426,16 +440,6 @@ func expectedContainerEnv(containerSpec *egv1a1.KubernetesContainerSpec, control }, } - env = append(env, corev1.EnvVar{ - Name: envoyPodEnvVar, - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - APIVersion: "v1", - FieldPath: "metadata.name", - }, - }, - }) - if containerSpec != nil { return resource.ExpectedContainerEnv(containerSpec, env) } else { diff --git a/internal/infrastructure/kubernetes/proxy/resource_provider.go b/internal/infrastructure/kubernetes/proxy/resource_provider.go index 17c2ee647f..b83b9002b7 100644 --- a/internal/infrastructure/kubernetes/proxy/resource_provider.go +++ b/internal/infrastructure/kubernetes/proxy/resource_provider.go @@ -6,6 +6,7 @@ package proxy import ( + "context" "fmt" "strconv" @@ -16,11 +17,14 @@ import ( policyv1 "k8s.io/api/policy/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/utils/ptr" + gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/gatewayapi" + gwapiresource "github.com/envoyproxy/gateway/internal/gatewayapi/resource" "github.com/envoyproxy/gateway/internal/infrastructure/common" "github.com/envoyproxy/gateway/internal/infrastructure/kubernetes/resource" "github.com/envoyproxy/gateway/internal/ir" @@ -58,17 +62,37 @@ type ResourceRender struct { ShutdownManager *egv1a1.ShutdownManager GatewayNamespaceMode bool + + // ownerReferenceUID store the uid of its owner reference. Key is the kind of owner resource. + // - Gateway when enabled GatewayNamespaceMode + // - TODO: GatewayClass when enabled merged gateways + ownerReferenceUID map[string]types.UID } -func NewResourceRender(envoyNamespace, controllerNamespace, dnsDomain string, infra *ir.ProxyInfra, gateway *egv1a1.EnvoyGateway) *ResourceRender { - return &ResourceRender{ - envoyNamespace: envoyNamespace, - controllerNamespace: controllerNamespace, - DNSDomain: dnsDomain, - infra: infra, - ShutdownManager: gateway.GetEnvoyGatewayProvider().GetEnvoyGatewayKubeProvider().ShutdownManager, - GatewayNamespaceMode: gateway.GatewayNamespaceMode(), +// KubernetesInfraProvider provide information for initializing the proxy resource render. +type KubernetesInfraProvider interface { + GetControllerNamespace() string + GetDNSDomain() string + GetEnvoyGateway() *egv1a1.EnvoyGateway + GetOwnerReferenceUID(ctx context.Context, infra *ir.Infra) (map[string]types.UID, error) + GetResourceNamespace(ir *ir.Infra) string +} + +func NewResourceRender(ctx context.Context, kubernetesInfra KubernetesInfraProvider, infra *ir.Infra) (*ResourceRender, error) { + ownerReference, err := kubernetesInfra.GetOwnerReferenceUID(ctx, infra) + if err != nil { + return nil, err } + + return &ResourceRender{ + envoyNamespace: kubernetesInfra.GetResourceNamespace(infra), + controllerNamespace: kubernetesInfra.GetControllerNamespace(), + DNSDomain: kubernetesInfra.GetDNSDomain(), + infra: infra.GetProxyInfra(), + ShutdownManager: kubernetesInfra.GetEnvoyGateway().GetEnvoyGatewayProvider().GetEnvoyGatewayKubeProvider().ShutdownManager, + GatewayNamespaceMode: kubernetesInfra.GetEnvoyGateway().GatewayNamespaceMode(), + ownerReferenceUID: ownerReference, + }, nil } func (r *ResourceRender) Name() string { @@ -87,6 +111,21 @@ func (r *ResourceRender) LabelSelector() labels.Selector { return labels.SelectorFromSet(r.stableSelector().MatchLabels) } +func (r *ResourceRender) OwnerReferences() []metav1.OwnerReference { + var ownerReferences []metav1.OwnerReference + if r.ownerReferenceUID != nil && r.GatewayNamespaceMode { + if uid, ok := r.ownerReferenceUID[gwapiresource.KindGateway]; ok { + ownerReferences = append(ownerReferences, metav1.OwnerReference{ + APIVersion: gwapiv1.GroupVersion.String(), + Kind: r.infra.GetProxyMetadata().OwnerReference.Kind, + Name: r.infra.GetProxyMetadata().OwnerReference.Name, + UID: uid, + }) + } + } + return ownerReferences +} + // ServiceAccount returns the expected proxy serviceAccount. func (r *ResourceRender) ServiceAccount() (*corev1.ServiceAccount, error) { // Set the labels based on the owning gateway name. @@ -101,10 +140,11 @@ func (r *ResourceRender) ServiceAccount() (*corev1.ServiceAccount, error) { APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ - Namespace: r.Namespace(), - Name: r.Name(), - Labels: labels, - Annotations: r.infra.GetProxyMetadata().Annotations, + Namespace: r.Namespace(), + Name: r.Name(), + Labels: labels, + Annotations: r.infra.GetProxyMetadata().Annotations, + OwnerReferences: r.OwnerReferences(), }, }, nil } @@ -208,9 +248,10 @@ func (r *ResourceRender) Service() (*corev1.Service, error) { Kind: "Service", }, ObjectMeta: metav1.ObjectMeta{ - Namespace: r.Namespace(), - Labels: svcLabels, - Annotations: annotations, + Namespace: r.Namespace(), + Labels: svcLabels, + Annotations: annotations, + OwnerReferences: r.OwnerReferences(), }, Spec: serviceSpec, } @@ -253,10 +294,11 @@ func (r *ResourceRender) ConfigMap(cert string) (*corev1.ConfigMap, error) { APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ - Namespace: r.Namespace(), - Name: r.Name(), - Labels: labels, - Annotations: r.infra.GetProxyMetadata().Annotations, + Namespace: r.Namespace(), + Name: r.Name(), + Labels: labels, + Annotations: r.infra.GetProxyMetadata().Annotations, + OwnerReferences: r.OwnerReferences(), }, Data: data, }, nil @@ -312,9 +354,10 @@ func (r *ResourceRender) Deployment() (*appsv1.Deployment, error) { APIVersion: "apps/v1", }, ObjectMeta: metav1.ObjectMeta{ - Namespace: r.Namespace(), - Labels: dpLabels, - Annotations: dpAnnotations, + Namespace: r.Namespace(), + Labels: dpLabels, + Annotations: dpAnnotations, + OwnerReferences: r.OwnerReferences(), }, Spec: appsv1.DeploymentSpec{ Replicas: deploymentConfig.Replicas, @@ -400,9 +443,10 @@ func (r *ResourceRender) DaemonSet() (*appsv1.DaemonSet, error) { APIVersion: "apps/v1", }, ObjectMeta: metav1.ObjectMeta{ - Namespace: r.Namespace(), - Labels: dsLabels, - Annotations: dsAnnotations, + Namespace: r.Namespace(), + Labels: dsLabels, + Annotations: dsAnnotations, + OwnerReferences: r.OwnerReferences(), }, Spec: appsv1.DaemonSetSpec{ // Daemonset's selector is immutable. @@ -468,8 +512,9 @@ func (r *ResourceRender) PodDisruptionBudget() (*policyv1.PodDisruptionBudget, e podDisruptionBudget := &policyv1.PodDisruptionBudget{ ObjectMeta: metav1.ObjectMeta{ - Name: r.Name(), - Namespace: r.Namespace(), + Name: r.Name(), + Namespace: r.Namespace(), + OwnerReferences: r.OwnerReferences(), }, TypeMeta: metav1.TypeMeta{ APIVersion: "policy/v1", @@ -503,10 +548,11 @@ func (r *ResourceRender) HorizontalPodAutoscaler() (*autoscalingv2.HorizontalPod Kind: "HorizontalPodAutoscaler", }, ObjectMeta: metav1.ObjectMeta{ - Namespace: r.Namespace(), - Name: r.Name(), - Annotations: r.infra.GetProxyMetadata().Annotations, - Labels: r.infra.GetProxyMetadata().Labels, + Namespace: r.Namespace(), + Name: r.Name(), + Annotations: r.infra.GetProxyMetadata().Annotations, + Labels: r.infra.GetProxyMetadata().Labels, + OwnerReferences: r.OwnerReferences(), }, Spec: autoscalingv2.HorizontalPodAutoscalerSpec{ ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{ diff --git a/internal/infrastructure/kubernetes/proxy/resource_provider_test.go b/internal/infrastructure/kubernetes/proxy/resource_provider_test.go index f8165efacb..d99fd82be4 100644 --- a/internal/infrastructure/kubernetes/proxy/resource_provider_test.go +++ b/internal/infrastructure/kubernetes/proxy/resource_provider_test.go @@ -6,6 +6,7 @@ package proxy import ( + "context" "fmt" "os" "sort" @@ -21,6 +22,7 @@ import ( apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/utils/ptr" "sigs.k8s.io/yaml" @@ -28,6 +30,7 @@ import ( egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/envoygateway/config" "github.com/envoyproxy/gateway/internal/gatewayapi" + gwapiresource "github.com/envoyproxy/gateway/internal/gatewayapi/resource" "github.com/envoyproxy/gateway/internal/ir" "github.com/envoyproxy/gateway/internal/utils/test" ) @@ -39,15 +42,59 @@ const ( envoyHTTPSPort = int32(8443) ) +type fakeKubernetesInfraProvider struct { + ControllerNamespace string + DNSDomain string + EnvoyGateway *egv1a1.EnvoyGateway +} + +func newFakeKubernetesInfraProvider(cfg *config.Server) KubernetesInfraProvider { + return &fakeKubernetesInfraProvider{ + ControllerNamespace: cfg.ControllerNamespace, + DNSDomain: cfg.DNSDomain, + EnvoyGateway: cfg.EnvoyGateway, + } +} + +func (f *fakeKubernetesInfraProvider) GetControllerNamespace() string { + return f.ControllerNamespace +} + +func (f *fakeKubernetesInfraProvider) GetDNSDomain() string { + return f.DNSDomain +} + +func (f *fakeKubernetesInfraProvider) GetEnvoyGateway() *egv1a1.EnvoyGateway { + return f.EnvoyGateway +} + +func (f *fakeKubernetesInfraProvider) GetOwnerReferenceUID(ctx context.Context, infra *ir.Infra) (map[string]types.UID, error) { + return map[string]types.UID{ + gwapiresource.KindGateway: "test-owner-reference-uid-for-gateway", + }, nil +} + +func (f *fakeKubernetesInfraProvider) GetResourceNamespace(infra *ir.Infra) string { + if f.EnvoyGateway.GatewayNamespaceMode() { + return infra.Proxy.Namespace + } + return f.ControllerNamespace +} + func newTestInfra() *ir.Infra { return newTestInfraWithAnnotations(nil) } -func newTestInfraWithNamespace(namespace string) *ir.Infra { - i := ir.NewInfra() +func newTestInfraWithNamespaceName(namespace, name, proxyName string) *ir.Infra { + i := newTestInfraWithAnnotations(nil) + i.Proxy.Name = proxyName i.Proxy.Namespace = namespace i.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNamespaceLabel] = namespace - i.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNameLabel] = i.Proxy.Name + i.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNameLabel] = name + i.Proxy.GetProxyMetadata().OwnerReference = &ir.ResourceMetadata{ + Kind: "Gateway", + Name: name, + } return i } @@ -568,6 +615,12 @@ func TestDeployment(t *testing.T) { Name: ptr.To("custom-deployment-name"), }, }, + { + caseName: "gateway-namespace-mode", + infra: newTestInfraWithNamespaceName("ns1", "gateway-1", "ns1/gateway-1"), + deploy: nil, + gatewayNamespaceMode: true, + }, } for _, tc := range cases { t.Run(tc.caseName, func(t *testing.T) { @@ -612,8 +665,20 @@ func TestDeployment(t *testing.T) { if len(tc.extraArgs) > 0 { tc.infra.Proxy.Config.Spec.ExtraArgs = tc.extraArgs } - infraNamespace := cfg.ControllerNamespace - r := NewResourceRender(infraNamespace, cfg.ControllerNamespace, cfg.DNSDomain, tc.infra.GetProxyInfra(), cfg.EnvoyGateway) + if tc.gatewayNamespaceMode { + deployType := egv1a1.KubernetesDeployModeType(egv1a1.KubernetesDeployModeTypeGatewayNamespace) + cfg.EnvoyGateway.Provider = &egv1a1.EnvoyGatewayProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyGatewayKubernetesProvider{ + Deploy: &egv1a1.KubernetesDeployMode{ + Type: &deployType, + }, + }, + } + } + + r, err := NewResourceRender(context.Background(), newFakeKubernetesInfraProvider(cfg), tc.infra) + require.NoError(t, err) dp, err := r.Deployment() require.NoError(t, err) @@ -657,15 +722,16 @@ func TestDaemonSet(t *testing.T) { require.NoError(t, err) cases := []struct { - caseName string - infra *ir.Infra - daemonset *egv1a1.KubernetesDaemonSetSpec - shutdown *egv1a1.ShutdownConfig - proxyLogging map[egv1a1.ProxyLogComponent]egv1a1.LogLevel - bootstrap string - telemetry *egv1a1.ProxyTelemetry - concurrency *int32 - extraArgs []string + caseName string + infra *ir.Infra + daemonset *egv1a1.KubernetesDaemonSetSpec + shutdown *egv1a1.ShutdownConfig + proxyLogging map[egv1a1.ProxyLogComponent]egv1a1.LogLevel + bootstrap string + telemetry *egv1a1.ProxyTelemetry + concurrency *int32 + extraArgs []string + gatewayNamespaceMode bool }{ { caseName: "default", @@ -998,9 +1064,27 @@ func TestDaemonSet(t *testing.T) { Name: ptr.To("custom-daemonset-name"), }, }, + { + caseName: "gateway-namespace-mode", + infra: newTestInfraWithNamespaceName("ns1", "gateway-1", "ns1/gateway-1"), + daemonset: nil, + gatewayNamespaceMode: true, + }, } for _, tc := range cases { t.Run(tc.caseName, func(t *testing.T) { + if tc.gatewayNamespaceMode { + deployType := egv1a1.KubernetesDeployModeType(egv1a1.KubernetesDeployModeTypeGatewayNamespace) + cfg.EnvoyGateway.Provider = &egv1a1.EnvoyGatewayProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyGatewayKubernetesProvider{ + Deploy: &egv1a1.KubernetesDeployMode{ + Type: &deployType, + }, + }, + } + } + kube := tc.infra.GetProxyInfra().GetProxyConfig().GetEnvoyProxyProvider().GetEnvoyProxyKubeProvider() // fill deploument, use daemonset @@ -1042,7 +1126,8 @@ func TestDaemonSet(t *testing.T) { tc.infra.Proxy.Config.Spec.ExtraArgs = tc.extraArgs } - r := NewResourceRender(cfg.ControllerNamespace, cfg.ControllerNamespace, cfg.DNSDomain, tc.infra.GetProxyInfra(), cfg.EnvoyGateway) + r, err := NewResourceRender(context.Background(), newFakeKubernetesInfraProvider(cfg), tc.infra) + require.NoError(t, err) ds, err := r.DaemonSet() require.NoError(t, err) @@ -1087,9 +1172,10 @@ func TestService(t *testing.T) { svcType := egv1a1.ServiceTypeClusterIP cases := []struct { - caseName string - infra *ir.Infra - service *egv1a1.KubernetesServiceSpec + caseName string + infra *ir.Infra + service *egv1a1.KubernetesServiceSpec + gatewayNamespaceMode bool }{ { caseName: "default", @@ -1199,15 +1285,34 @@ func TestService(t *testing.T) { infra: newTestInfraWithIPFamily(ptr.To(egv1a1.IPv6)), service: nil, }, + { + caseName: "gateway-namespace-mode", + infra: newTestInfraWithNamespaceName("ns1", "gateway-1", "ns1/gateway-1"), + service: nil, + gatewayNamespaceMode: true, + }, } for _, tc := range cases { t.Run(tc.caseName, func(t *testing.T) { + if tc.gatewayNamespaceMode { + deployType := egv1a1.KubernetesDeployModeType(egv1a1.KubernetesDeployModeTypeGatewayNamespace) + cfg.EnvoyGateway.Provider = &egv1a1.EnvoyGatewayProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyGatewayKubernetesProvider{ + Deploy: &egv1a1.KubernetesDeployMode{ + Type: &deployType, + }, + }, + } + } + provider := tc.infra.GetProxyInfra().GetProxyConfig().GetEnvoyProxyProvider().GetEnvoyProxyKubeProvider() if tc.service != nil { provider.EnvoyService = tc.service } - r := NewResourceRender(cfg.ControllerNamespace, cfg.ControllerNamespace, cfg.DNSDomain, tc.infra.GetProxyInfra(), cfg.EnvoyGateway) + r, err := NewResourceRender(context.Background(), newFakeKubernetesInfraProvider(cfg), tc.infra) + require.NoError(t, err) svc, err := r.Service() require.NoError(t, err) @@ -1233,24 +1338,43 @@ func TestConfigMap(t *testing.T) { cfg, err := config.New(os.Stdout) require.NoError(t, err) cases := []struct { - name string - infra *ir.Infra + name string + infra *ir.Infra + gatewayNamespaceMode bool }{ { name: "default", infra: newTestInfra(), - }, { + }, + { name: "with-annotations", infra: newTestInfraWithAnnotations(map[string]string{ "anno1": "value1", "anno2": "value2", }), }, + { + name: "gateway-namespace-mode", + infra: newTestInfraWithNamespaceName("ns1", "gateway-1", "ns1/gateway-1"), + gatewayNamespaceMode: true, + }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - r := NewResourceRender(cfg.ControllerNamespace, cfg.ControllerNamespace, cfg.DNSDomain, tc.infra.GetProxyInfra(), cfg.EnvoyGateway) + if tc.gatewayNamespaceMode { + deployType := egv1a1.KubernetesDeployModeType(egv1a1.KubernetesDeployModeTypeGatewayNamespace) + cfg.EnvoyGateway.Provider = &egv1a1.EnvoyGatewayProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyGatewayKubernetesProvider{ + Deploy: &egv1a1.KubernetesDeployMode{ + Type: &deployType, + }, + }, + } + } + r, err := NewResourceRender(context.Background(), newFakeKubernetesInfraProvider(cfg), tc.infra) + require.NoError(t, err) cm, err := r.ConfigMap("") require.NoError(t, err) @@ -1293,14 +1417,13 @@ func TestServiceAccount(t *testing.T) { }, { name: "gateway-namespace-mode", - infra: newTestInfraWithNamespace("ns1"), + infra: newTestInfraWithNamespaceName("ns1", "gateway-1", "ns1/gateway-1"), gatewayNamespaceMode: true, }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - ns := cfg.ControllerNamespace if tc.gatewayNamespaceMode { deployType := egv1a1.KubernetesDeployModeType(egv1a1.KubernetesDeployModeTypeGatewayNamespace) cfg.EnvoyGateway.Provider = &egv1a1.EnvoyGatewayProvider{ @@ -1311,9 +1434,9 @@ func TestServiceAccount(t *testing.T) { }, }, } - ns = tc.infra.GetProxyInfra().Namespace } - r := NewResourceRender(ns, cfg.ControllerNamespace, cfg.DNSDomain, tc.infra.GetProxyInfra(), cfg.EnvoyGateway) + r, err := NewResourceRender(context.Background(), newFakeKubernetesInfraProvider(cfg), tc.infra) + require.NoError(t, err) sa, err := r.ServiceAccount() require.NoError(t, err) @@ -1349,10 +1472,11 @@ func TestPDB(t *testing.T) { require.NoError(t, err) cases := []struct { - caseName string - infra *ir.Infra - pdb *egv1a1.KubernetesPodDisruptionBudgetSpec - deploy *egv1a1.KubernetesDeploymentSpec + caseName string + infra *ir.Infra + pdb *egv1a1.KubernetesPodDisruptionBudgetSpec + deploy *egv1a1.KubernetesDeploymentSpec + gatewayNamespaceMode bool }{ { caseName: "default", @@ -1420,10 +1544,30 @@ func TestPDB(t *testing.T) { }, }, }, + { + caseName: "gateway-namespace-mode", + infra: newTestInfraWithNamespaceName("ns1", "gateway-1", "ns1/gateway-1"), + pdb: &egv1a1.KubernetesPodDisruptionBudgetSpec{ + MinAvailable: ptr.To(intstr.IntOrString{Type: intstr.Int, IntVal: 1}), + }, + gatewayNamespaceMode: true, + }, } for _, tc := range cases { t.Run(tc.caseName, func(t *testing.T) { + if tc.gatewayNamespaceMode { + deployType := egv1a1.KubernetesDeployModeType(egv1a1.KubernetesDeployModeTypeGatewayNamespace) + cfg.EnvoyGateway.Provider = &egv1a1.EnvoyGatewayProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyGatewayKubernetesProvider{ + Deploy: &egv1a1.KubernetesDeployMode{ + Type: &deployType, + }, + }, + } + } + provider := tc.infra.GetProxyInfra().GetProxyConfig().GetEnvoyProxyProvider() provider.Kubernetes = egv1a1.DefaultEnvoyProxyKubeProvider() @@ -1437,7 +1581,8 @@ func TestPDB(t *testing.T) { provider.GetEnvoyProxyKubeProvider() - r := NewResourceRender(cfg.ControllerNamespace, cfg.ControllerNamespace, cfg.DNSDomain, tc.infra.GetProxyInfra(), cfg.EnvoyGateway) + r, err := NewResourceRender(context.Background(), newFakeKubernetesInfraProvider(cfg), tc.infra) + require.NoError(t, err) pdb, err := r.PodDisruptionBudget() require.NoError(t, err) @@ -1455,10 +1600,11 @@ func TestHorizontalPodAutoscaler(t *testing.T) { require.NoError(t, err) cases := []struct { - caseName string - infra *ir.Infra - hpa *egv1a1.KubernetesHorizontalPodAutoscalerSpec - deploy *egv1a1.KubernetesDeploymentSpec + caseName string + infra *ir.Infra + hpa *egv1a1.KubernetesHorizontalPodAutoscalerSpec + deploy *egv1a1.KubernetesDeploymentSpec + gatewayNamespaceMode bool }{ { caseName: "default", @@ -1534,10 +1680,30 @@ func TestHorizontalPodAutoscaler(t *testing.T) { Name: ptr.To("custom-deployment-name"), }, }, + { + caseName: "gateway-namespace-mode", + infra: newTestInfraWithNamespaceName("ns1", "gateway-1", "ns1/gateway-1"), + hpa: &egv1a1.KubernetesHorizontalPodAutoscalerSpec{ + MaxReplicas: ptr.To[int32](1), + }, + gatewayNamespaceMode: true, + }, } for _, tc := range cases { t.Run(tc.caseName, func(t *testing.T) { + if tc.gatewayNamespaceMode { + deployType := egv1a1.KubernetesDeployModeType(egv1a1.KubernetesDeployModeTypeGatewayNamespace) + cfg.EnvoyGateway.Provider = &egv1a1.EnvoyGatewayProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyGatewayKubernetesProvider{ + Deploy: &egv1a1.KubernetesDeployMode{ + Type: &deployType, + }, + }, + } + } + provider := tc.infra.GetProxyInfra().GetProxyConfig().GetEnvoyProxyProvider() provider.Kubernetes = egv1a1.DefaultEnvoyProxyKubeProvider() @@ -1549,7 +1715,8 @@ func TestHorizontalPodAutoscaler(t *testing.T) { } provider.GetEnvoyProxyKubeProvider() - r := NewResourceRender(cfg.ControllerNamespace, cfg.ControllerNamespace, cfg.DNSDomain, tc.infra.GetProxyInfra(), cfg.EnvoyGateway) + r, err := NewResourceRender(context.Background(), newFakeKubernetesInfraProvider(cfg), tc.infra) + require.NoError(t, err) hpa, err := r.HorizontalPodAutoscaler() require.NoError(t, err) @@ -1695,9 +1862,7 @@ func TestGatewayNamespaceModeMultipleResources(t *testing.T) { // Create test infra with multiple namespaces var infraList []*ir.Infra - infra1 := newTestInfraWithNamespace("namespace-1") - infra1.Proxy.Name = "namespace-1/gateway-1" - infra1.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNameLabel] = "gateway-1" + infra1 := newTestInfraWithNamespaceName("namespace-1", "gateway-1", "namespace-1/gateway-1") // Add HPA config to first infra if infra1.Proxy.Config == nil { infra1.Proxy.Config = &egv1a1.EnvoyProxy{Spec: egv1a1.EnvoyProxySpec{}} @@ -1714,9 +1879,7 @@ func TestGatewayNamespaceModeMultipleResources(t *testing.T) { MaxReplicas: ptr.To[int32](3), } - infra2 := newTestInfraWithNamespace("namespace-2") - infra2.Proxy.Name = "namespace-2/gateway-2" - infra2.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNameLabel] = "gateway-2" + infra2 := newTestInfraWithNamespaceName("namespace-2", "gateway-2", "namespace-2/gateway-2") // Add HPA config to second infra if infra2.Proxy.Config == nil { infra2.Proxy.Config = &egv1a1.EnvoyProxy{Spec: egv1a1.EnvoyProxySpec{}} @@ -1741,9 +1904,8 @@ func TestGatewayNamespaceModeMultipleResources(t *testing.T) { hpas := make([]*autoscalingv2.HorizontalPodAutoscaler, 0, len(infraList)) for _, infra := range infraList { - namespace := infra.GetProxyInfra().Namespace - r := NewResourceRender(namespace, cfg.ControllerNamespace, cfg.DNSDomain, - infra.GetProxyInfra(), cfg.EnvoyGateway) + r, err := NewResourceRender(context.Background(), newFakeKubernetesInfraProvider(cfg), infra) + require.NoError(t, err) dp, err := r.Deployment() require.NoError(t, err) diff --git a/internal/infrastructure/kubernetes/proxy/testdata/configmap/gateway-namespace-mode.yaml b/internal/infrastructure/kubernetes/proxy/testdata/configmap/gateway-namespace-mode.yaml new file mode 100644 index 0000000000..69cf6c2adb --- /dev/null +++ b/internal/infrastructure/kubernetes/proxy/testdata/configmap/gateway-namespace-mode.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/name: envoy + app.kubernetes.io/component: proxy + app.kubernetes.io/managed-by: envoy-gateway + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: ns1 + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + name: gateway-1 + uid: test-owner-reference-uid-for-gateway + name: envoy-ns1-gateway-1-02ae0474 + namespace: ns1 +data: + xds-certificate.json: '{"resources":[{"@type":"type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret","name":"xds_certificate","tls_certificate":{"certificate_chain":{"filename":"/certs/tls.crt"},"private_key":{"filename":"/certs/tls.key"}}}]}' + xds-trusted-ca.json: '{"resources":[{"@type":"type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret","name":"xds_trusted_ca","validation_context":{"trusted_ca":{"filename":"/certs/ca.crt"},"match_typed_subject_alt_names":[{"san_type":"DNS","matcher":{"exact":"envoy-gateway"}}]}}]}' diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/component-level.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/component-level.yaml index 2585b1a843..6e500f7b39 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/component-level.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/component-level.yaml @@ -45,18 +45,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -129,18 +132,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/custom.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/custom.yaml index 10e0d530a3..a90cada680 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/custom.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/custom.yaml @@ -52,7 +52,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -137,7 +137,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -248,18 +248,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: envoyproxy/envoy:v1.2.3 imagePullPolicy: IfNotPresent lifecycle: @@ -326,18 +329,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default-env.yaml index c128b84b22..d74ed2faf1 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default-env.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default-env.yaml @@ -51,7 +51,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -136,7 +136,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -247,18 +247,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: envoyproxy/envoy:v1.2.3 imagePullPolicy: IfNotPresent lifecycle: @@ -325,18 +328,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml index 691d4e9c22..8f08280887 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml @@ -51,7 +51,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -136,7 +136,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -232,18 +232,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -316,18 +319,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml index 30c1103a57..be43f0d003 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml @@ -47,7 +47,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -85,7 +85,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -181,18 +181,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -262,18 +265,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/extension-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/extension-env.yaml index 4b82730649..1f4853b41a 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/extension-env.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/extension-env.yaml @@ -51,7 +51,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -136,7 +136,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -247,18 +247,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] - name: env_a value: env_a_value - name: env_b @@ -329,18 +332,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/gateway-namespace-mode.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/gateway-namespace-mode.yaml new file mode 100644 index 0000000000..ae8b78e904 --- /dev/null +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/gateway-namespace-mode.yaml @@ -0,0 +1,456 @@ +apiVersion: apps/v1 +kind: DaemonSet +metadata: + creationTimestamp: null + labels: + app.kubernetes.io/component: proxy + app.kubernetes.io/managed-by: envoy-gateway + app.kubernetes.io/name: envoy + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: ns1 + name: envoy-ns1-gateway-1-02ae0474 + namespace: ns1 + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + name: gateway-1 + uid: test-owner-reference-uid-for-gateway +spec: + selector: + matchLabels: + app.kubernetes.io/component: proxy + app.kubernetes.io/managed-by: envoy-gateway + app.kubernetes.io/name: envoy + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: ns1 + template: + metadata: + annotations: + prometheus.io/path: /stats/prometheus + prometheus.io/port: "19001" + prometheus.io/scrape: "true" + creationTimestamp: null + labels: + app.kubernetes.io/component: proxy + app.kubernetes.io/managed-by: envoy-gateway + app.kubernetes.io/name: envoy + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: ns1 + spec: + containers: + - args: + - --service-cluster ns1/gateway-1 + - --service-node $(ENVOY_POD_NAME) + - | + --config-yaml admin: + access_log: + - name: envoy.access_loggers.file + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog + path: /dev/null + address: + socket_address: + address: 127.0.0.1 + port_value: 19000 + cluster_manager: + local_cluster_name: local_cluster + node: + locality: + zone: $(ENVOY_SERVICE_ZONE) + layered_runtime: + layers: + - name: global_config + static_layer: + envoy.restart_features.use_eds_cache_for_ads: true + re2.max_program_size.error_level: 4294967295 + re2.max_program_size.warn_level: 1000 + dynamic_resources: + ads_config: + api_type: DELTA_GRPC + transport_api_version: V3 + grpc_services: + - envoy_grpc: + cluster_name: xds_cluster + set_node_on_first_message_only: true + lds_config: + ads: {} + resource_api_version: V3 + cds_config: + ads: {} + resource_api_version: V3 + static_resources: + listeners: + - name: envoy-gateway-proxy-stats-0.0.0.0-19001 + address: + socket_address: + address: '0.0.0.0' + port_value: 19001 + protocol: TCP + bypass_overload_manager: true + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + stat_prefix: eg-stats-http + normalize_path: true + route_config: + name: local_route + virtual_hosts: + - name: prometheus_stats + domains: + - "*" + routes: + - match: + path: /stats/prometheus + headers: + - name: ":method" + string_match: + exact: GET + route: + cluster: prometheus_stats + http_filters: + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + clusters: + - name: prometheus_stats + connect_timeout: 0.250s + type: STATIC + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: prometheus_stats + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 19000 + - connect_timeout: 10s + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: local_cluster + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 10080 + load_balancing_weight: 1 + load_balancing_weight: 1 + locality: + zone: $(ENVOY_SERVICE_ZONE) + name: local_cluster + type: STATIC + - connect_timeout: 10s + load_assignment: + cluster_name: xds_cluster + endpoints: + - load_balancing_weight: 1 + lb_endpoints: + - load_balancing_weight: 1 + endpoint: + address: + socket_address: + address: envoy-gateway.envoy-gateway-system.svc.cluster.local + port_value: 18000 + typed_extension_protocol_options: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions" + explicit_http_config: + http2_protocol_options: + connection_keepalive: + interval: 30s + timeout: 5s + http_filters: + - name: envoy.filters.http.credential_injector + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.credential_injector.v3.CredentialInjector + credential: + name: envoy.http.injected_credentials.generic + typed_config: + "@type": type.googleapis.com/envoy.extensions.http.injected_credentials.generic.v3.Generic + credential: + name: jwt-sa-bearer + overwrite: true + - name: envoy.extensions.filters.http.upstream_codec.v3.UpstreamCodec + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.upstream_codec.v3.UpstreamCodec + name: xds_cluster + type: STRICT_DNS + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + tls_params: + tls_maximum_protocol_version: TLSv1_3 + validation_context_sds_secret_config: + name: xds_trusted_ca + sds_config: + path_config_source: + path: /sds/xds-trusted-ca.json + resource_api_version: V3 + - name: wasm_cluster + type: STRICT_DNS + connect_timeout: 10s + load_assignment: + cluster_name: wasm_cluster + endpoints: + - load_balancing_weight: 1 + lb_endpoints: + - load_balancing_weight: 1 + endpoint: + address: + socket_address: + address: envoy-gateway + port_value: 18002 + typed_extension_protocol_options: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions" + explicit_http_config: + http2_protocol_options: {} + http_filters: + - name: envoy.filters.http.credential_injector + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.credential_injector.v3.CredentialInjector + credential: + name: envoy.http.injected_credentials.generic + typed_config: + "@type": type.googleapis.com/envoy.extensions.http.injected_credentials.generic.v3.Generic + credential: + name: jwt-sa-bearer + overwrite: true + - name: envoy.extensions.filters.http.upstream_codec.v3.UpstreamCodec + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.upstream_codec.v3.UpstreamCodec + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + tls_params: + tls_maximum_protocol_version: TLSv1_3 + validation_context_sds_secret_config: + name: xds_trusted_ca + sds_config: + path_config_source: + path: /sds/xds-trusted-ca.json + resource_api_version: V3 + secrets: + - name: jwt-sa-bearer + generic_secret: + secret: + filename: "/var/run/secrets/token/sa-token" + overload_manager: + refresh_interval: 0.25s + resource_monitors: + - name: "envoy.resource_monitors.global_downstream_max_connections" + typed_config: + "@type": type.googleapis.com/envoy.extensions.resource_monitors.downstream_connections.v3.DownstreamConnectionsConfig + max_active_downstream_connections: 50000 + - --log-level warn + - --cpuset-threads + - --drain-strategy immediate + - --drain-time-s 60 + command: + - envoy + env: + - name: ENVOY_POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + image: docker.io/envoyproxy/envoy:distroless-v1.34.1 + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + httpGet: + path: /shutdown/ready + port: 19002 + scheme: HTTP + livenessProbe: + failureThreshold: 3 + httpGet: + path: /ready + port: 19003 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + name: envoy + ports: + - containerPort: 19001 + name: metrics + protocol: TCP + - containerPort: 19003 + name: readiness + protocol: TCP + readinessProbe: + failureThreshold: 1 + httpGet: + path: /ready + port: 19003 + scheme: HTTP + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + resources: + requests: + cpu: 100m + memory: 512Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + runAsGroup: 65532 + runAsNonRoot: true + runAsUser: 65532 + seccompProfile: + type: RuntimeDefault + startupProbe: + failureThreshold: 30 + httpGet: + path: /ready + port: 19003 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /certs + name: certs + readOnly: true + - mountPath: /sds + name: sds + - mountPath: /var/run/secrets/token + name: sa-token + readOnly: true + - args: + - envoy + - shutdown-manager + command: + - envoy-gateway + env: + - name: ENVOY_POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + image: docker.io/envoyproxy/gateway-dev:latest + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - envoy-gateway + - envoy + - shutdown + livenessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + name: shutdown-manager + readinessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + resources: + requests: + cpu: 10m + memory: 32Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + runAsGroup: 65532 + runAsNonRoot: true + runAsUser: 65532 + seccompProfile: + type: RuntimeDefault + startupProbe: + failureThreshold: 30 + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + serviceAccountName: envoy-ns1-gateway-1-02ae0474 + terminationGracePeriodSeconds: 360 + volumes: + - name: sa-token + projected: + defaultMode: 420 + sources: + - serviceAccountToken: + audience: envoy-gateway.envoy-gateway-system.svc.cluster.local + expirationSeconds: 3600 + path: sa-token + - configMap: + defaultMode: 420 + items: + - key: ca.crt + path: ca.crt + name: envoy-ns1-gateway-1-02ae0474 + optional: false + name: certs + - configMap: + defaultMode: 420 + items: + - key: xds-trusted-ca.json + path: xds-trusted-ca.json + name: envoy-ns1-gateway-1-02ae0474 + optional: false + name: sds + updateStrategy: + type: RollingUpdate +status: + currentNumberScheduled: 0 + desiredNumberScheduled: 0 + numberMisscheduled: 0 + numberReady: 0 diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml index 700996c9d5..1aa26a1c6d 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml @@ -60,7 +60,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -145,7 +145,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -241,18 +241,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -325,18 +328,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml index 45e1c043ef..2d38eaba84 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml @@ -51,7 +51,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -136,7 +136,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -232,18 +232,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -316,18 +319,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/shutdown-manager.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/shutdown-manager.yaml index bdd79ecff8..716cb61c94 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/shutdown-manager.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/shutdown-manager.yaml @@ -51,7 +51,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -136,7 +136,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -232,18 +232,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -321,18 +324,21 @@ spec: value: env_a_value - name: env_b value: env_b_value - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: envoyproxy/gateway-dev:v1.2.3 imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/volumes.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/volumes.yaml index 00237afd96..2009045573 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/volumes.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/volumes.yaml @@ -51,7 +51,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -136,7 +136,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -247,18 +247,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] - name: env_a value: env_a_value - name: env_b @@ -329,18 +332,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml index 39b0003532..2e8a3f85ff 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml @@ -56,7 +56,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -141,7 +141,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -237,18 +237,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -321,18 +324,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-concurrency.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-concurrency.yaml index 0637e2fb12..faae3da331 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-concurrency.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-concurrency.yaml @@ -45,18 +45,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -129,18 +132,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml index a6dee04718..708bc655bb 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml @@ -51,7 +51,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -136,7 +136,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -234,18 +234,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -318,18 +321,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml index 89d67cf98e..07a2eac965 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml @@ -51,7 +51,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -136,7 +136,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -232,18 +232,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -316,18 +319,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml index 448b82a91b..f078b2f83b 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml @@ -51,7 +51,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -136,7 +136,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -232,18 +232,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -316,18 +319,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml index bd86b03c92..0c061fc053 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml @@ -51,7 +51,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -136,7 +136,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -232,18 +232,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -316,18 +319,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml index 89ee2d4f05..85739bdb6b 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml @@ -51,7 +51,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -136,7 +136,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -232,18 +232,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -316,18 +319,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml index 1bc4e047c6..53d6c883cc 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml @@ -48,18 +48,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -132,18 +135,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml index edd6b45aac..4e530e1ab8 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml @@ -49,18 +49,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -133,18 +136,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml index 2e6f822133..eb0cb4a055 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml @@ -57,7 +57,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -142,7 +142,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -253,18 +253,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: envoyproxy/envoy:v1.2.3 imagePullPolicy: IfNotPresent lifecycle: @@ -331,18 +334,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml index 77014daeda..aa3d4ef914 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml @@ -57,7 +57,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -142,7 +142,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -253,18 +253,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: envoyproxy/envoy:v1.2.3 imagePullPolicy: IfNotPresent lifecycle: @@ -333,18 +336,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml index 6a1da9c6cf..deb7fc0d3d 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml @@ -56,7 +56,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -141,7 +141,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -252,18 +252,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: envoyproxy/envoy:v1.2.3 imagePullPolicy: IfNotPresent lifecycle: @@ -330,18 +333,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml index 84d5c6e333..7b010c5f15 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml @@ -55,7 +55,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -140,7 +140,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -236,18 +236,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -320,18 +323,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml index 6fc515f2d6..ce2417f6d9 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml @@ -51,7 +51,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -89,7 +89,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -185,18 +185,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -266,18 +269,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/dual-stack.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/dual-stack.yaml index ec5638e752..72775a58c8 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/dual-stack.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/dual-stack.yaml @@ -55,7 +55,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -141,7 +141,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -237,18 +237,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -321,18 +324,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml index 1aff8bf165..cd36c6cf44 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml @@ -56,7 +56,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -141,7 +141,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -252,18 +252,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] - name: env_a value: env_a_value - name: env_b @@ -334,18 +337,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/gateway-namespace-mode.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/gateway-namespace-mode.yaml new file mode 100644 index 0000000000..2c84b757e9 --- /dev/null +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/gateway-namespace-mode.yaml @@ -0,0 +1,454 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + creationTimestamp: null + labels: + app.kubernetes.io/component: proxy + app.kubernetes.io/managed-by: envoy-gateway + app.kubernetes.io/name: envoy + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: ns1 + name: envoy-ns1-gateway-1-02ae0474 + namespace: ns1 + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + name: gateway-1 + uid: test-owner-reference-uid-for-gateway +spec: + progressDeadlineSeconds: 600 + revisionHistoryLimit: 10 + selector: + matchLabels: + app.kubernetes.io/component: proxy + app.kubernetes.io/managed-by: envoy-gateway + app.kubernetes.io/name: envoy + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: ns1 + strategy: + type: RollingUpdate + template: + metadata: + annotations: + prometheus.io/path: /stats/prometheus + prometheus.io/port: "19001" + prometheus.io/scrape: "true" + creationTimestamp: null + labels: + app.kubernetes.io/component: proxy + app.kubernetes.io/managed-by: envoy-gateway + app.kubernetes.io/name: envoy + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: ns1 + spec: + containers: + - args: + - --service-cluster ns1/gateway-1 + - --service-node $(ENVOY_POD_NAME) + - | + --config-yaml admin: + access_log: + - name: envoy.access_loggers.file + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog + path: /dev/null + address: + socket_address: + address: 127.0.0.1 + port_value: 19000 + cluster_manager: + local_cluster_name: local_cluster + node: + locality: + zone: $(ENVOY_SERVICE_ZONE) + layered_runtime: + layers: + - name: global_config + static_layer: + envoy.restart_features.use_eds_cache_for_ads: true + re2.max_program_size.error_level: 4294967295 + re2.max_program_size.warn_level: 1000 + dynamic_resources: + ads_config: + api_type: DELTA_GRPC + transport_api_version: V3 + grpc_services: + - envoy_grpc: + cluster_name: xds_cluster + set_node_on_first_message_only: true + lds_config: + ads: {} + resource_api_version: V3 + cds_config: + ads: {} + resource_api_version: V3 + static_resources: + listeners: + - name: envoy-gateway-proxy-stats-0.0.0.0-19001 + address: + socket_address: + address: '0.0.0.0' + port_value: 19001 + protocol: TCP + bypass_overload_manager: true + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + stat_prefix: eg-stats-http + normalize_path: true + route_config: + name: local_route + virtual_hosts: + - name: prometheus_stats + domains: + - "*" + routes: + - match: + path: /stats/prometheus + headers: + - name: ":method" + string_match: + exact: GET + route: + cluster: prometheus_stats + http_filters: + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + clusters: + - name: prometheus_stats + connect_timeout: 0.250s + type: STATIC + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: prometheus_stats + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 19000 + - connect_timeout: 10s + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: local_cluster + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 10080 + load_balancing_weight: 1 + load_balancing_weight: 1 + locality: + zone: $(ENVOY_SERVICE_ZONE) + name: local_cluster + type: STATIC + - connect_timeout: 10s + load_assignment: + cluster_name: xds_cluster + endpoints: + - load_balancing_weight: 1 + lb_endpoints: + - load_balancing_weight: 1 + endpoint: + address: + socket_address: + address: envoy-gateway.envoy-gateway-system.svc.cluster.local + port_value: 18000 + typed_extension_protocol_options: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions" + explicit_http_config: + http2_protocol_options: + connection_keepalive: + interval: 30s + timeout: 5s + http_filters: + - name: envoy.filters.http.credential_injector + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.credential_injector.v3.CredentialInjector + credential: + name: envoy.http.injected_credentials.generic + typed_config: + "@type": type.googleapis.com/envoy.extensions.http.injected_credentials.generic.v3.Generic + credential: + name: jwt-sa-bearer + overwrite: true + - name: envoy.extensions.filters.http.upstream_codec.v3.UpstreamCodec + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.upstream_codec.v3.UpstreamCodec + name: xds_cluster + type: STRICT_DNS + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + tls_params: + tls_maximum_protocol_version: TLSv1_3 + validation_context_sds_secret_config: + name: xds_trusted_ca + sds_config: + path_config_source: + path: /sds/xds-trusted-ca.json + resource_api_version: V3 + - name: wasm_cluster + type: STRICT_DNS + connect_timeout: 10s + load_assignment: + cluster_name: wasm_cluster + endpoints: + - load_balancing_weight: 1 + lb_endpoints: + - load_balancing_weight: 1 + endpoint: + address: + socket_address: + address: envoy-gateway + port_value: 18002 + typed_extension_protocol_options: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions" + explicit_http_config: + http2_protocol_options: {} + http_filters: + - name: envoy.filters.http.credential_injector + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.credential_injector.v3.CredentialInjector + credential: + name: envoy.http.injected_credentials.generic + typed_config: + "@type": type.googleapis.com/envoy.extensions.http.injected_credentials.generic.v3.Generic + credential: + name: jwt-sa-bearer + overwrite: true + - name: envoy.extensions.filters.http.upstream_codec.v3.UpstreamCodec + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.upstream_codec.v3.UpstreamCodec + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + tls_params: + tls_maximum_protocol_version: TLSv1_3 + validation_context_sds_secret_config: + name: xds_trusted_ca + sds_config: + path_config_source: + path: /sds/xds-trusted-ca.json + resource_api_version: V3 + secrets: + - name: jwt-sa-bearer + generic_secret: + secret: + filename: "/var/run/secrets/token/sa-token" + overload_manager: + refresh_interval: 0.25s + resource_monitors: + - name: "envoy.resource_monitors.global_downstream_max_connections" + typed_config: + "@type": type.googleapis.com/envoy.extensions.resource_monitors.downstream_connections.v3.DownstreamConnectionsConfig + max_active_downstream_connections: 50000 + - --log-level warn + - --cpuset-threads + - --drain-strategy immediate + - --drain-time-s 60 + command: + - envoy + env: + - name: ENVOY_POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + image: docker.io/envoyproxy/envoy:distroless-v1.34.1 + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + httpGet: + path: /shutdown/ready + port: 19002 + scheme: HTTP + livenessProbe: + failureThreshold: 3 + httpGet: + path: /ready + port: 19003 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + name: envoy + ports: + - containerPort: 19001 + name: metrics + protocol: TCP + - containerPort: 19003 + name: readiness + protocol: TCP + readinessProbe: + failureThreshold: 1 + httpGet: + path: /ready + port: 19003 + scheme: HTTP + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + resources: + requests: + cpu: 100m + memory: 512Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + runAsGroup: 65532 + runAsNonRoot: true + runAsUser: 65532 + seccompProfile: + type: RuntimeDefault + startupProbe: + failureThreshold: 30 + httpGet: + path: /ready + port: 19003 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /certs + name: certs + readOnly: true + - mountPath: /sds + name: sds + - mountPath: /var/run/secrets/token + name: sa-token + readOnly: true + - args: + - envoy + - shutdown-manager + command: + - envoy-gateway + env: + - name: ENVOY_POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + image: docker.io/envoyproxy/gateway-dev:latest + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - envoy-gateway + - envoy + - shutdown + livenessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + name: shutdown-manager + readinessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + resources: + requests: + cpu: 10m + memory: 32Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + runAsGroup: 65532 + runAsNonRoot: true + runAsUser: 65532 + seccompProfile: + type: RuntimeDefault + startupProbe: + failureThreshold: 30 + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + serviceAccountName: envoy-ns1-gateway-1-02ae0474 + terminationGracePeriodSeconds: 360 + volumes: + - name: sa-token + projected: + defaultMode: 420 + sources: + - serviceAccountToken: + audience: envoy-gateway.envoy-gateway-system.svc.cluster.local + expirationSeconds: 3600 + path: sa-token + - configMap: + defaultMode: 420 + items: + - key: ca.crt + path: ca.crt + name: envoy-ns1-gateway-1-02ae0474 + optional: false + name: certs + - configMap: + defaultMode: 420 + items: + - key: xds-trusted-ca.json + path: xds-trusted-ca.json + name: envoy-ns1-gateway-1-02ae0474 + optional: false + name: sds +status: {} diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/ipv6.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/ipv6.yaml index bf7a0aed62..0cf8f99a5f 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/ipv6.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/ipv6.yaml @@ -55,7 +55,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -141,7 +141,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -237,18 +237,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -321,18 +324,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/override-labels-and-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/override-labels-and-annotations.yaml index cac336b42e..003093b283 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/override-labels-and-annotations.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/override-labels-and-annotations.yaml @@ -64,7 +64,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -149,7 +149,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -245,18 +245,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -329,18 +332,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml index 4e3f5f816e..438ca1f446 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml @@ -55,7 +55,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -140,7 +140,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -236,18 +236,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -320,18 +323,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/shutdown-manager.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/shutdown-manager.yaml index fe9025222a..51cff26904 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/shutdown-manager.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/shutdown-manager.yaml @@ -55,7 +55,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -140,7 +140,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -236,18 +236,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -325,18 +328,21 @@ spec: value: env_a_value - name: env_b value: env_b_value - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: privaterepo/envoyproxy/gateway-dev:v1.2.3 imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml index 065c9b05d1..26951afe48 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml @@ -56,7 +56,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -141,7 +141,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -252,18 +252,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] - name: env_a value: env_a_value - name: env_b @@ -334,18 +337,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml index 9593c49828..f8068f45cc 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml @@ -60,7 +60,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -145,7 +145,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -241,18 +241,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -325,18 +328,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml index cccbba1135..b4eb9d5d1b 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml @@ -49,18 +49,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -133,18 +136,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml index 221e786d64..e2273aca97 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml @@ -55,7 +55,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -140,7 +140,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -236,18 +236,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -319,18 +322,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml index e3dacccdb6..f4f8f7030d 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml @@ -55,7 +55,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -140,7 +140,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -238,18 +238,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -322,18 +325,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-image-pull-secrets.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-image-pull-secrets.yaml index e0384be35a..ec1f1157f2 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-image-pull-secrets.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-image-pull-secrets.yaml @@ -55,7 +55,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -140,7 +140,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -236,18 +236,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -320,18 +323,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml index 8da72bf90e..b8ac9b251e 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml @@ -55,7 +55,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -140,7 +140,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -236,18 +236,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -320,18 +323,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml index f4f841b7fc..30dcd66b26 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml @@ -55,7 +55,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -140,7 +140,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -236,18 +236,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -320,18 +323,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-topology-spread-constraints.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-topology-spread-constraints.yaml index 475de1d089..08028a30c5 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-topology-spread-constraints.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-topology-spread-constraints.yaml @@ -55,7 +55,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -140,7 +140,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -236,18 +236,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -320,18 +323,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/gateway-namespace-mode/deployment.yaml b/internal/infrastructure/kubernetes/proxy/testdata/gateway-namespace-mode/deployment.yaml index 0a672f1fbf..37d149d9cb 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/gateway-namespace-mode/deployment.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/gateway-namespace-mode/deployment.yaml @@ -10,6 +10,11 @@ metadata: gateway.envoyproxy.io/owning-gateway-namespace: namespace-1 name: envoy-namespace-1-gateway-1-e2117e41 namespace: namespace-1 + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + name: gateway-1 + uid: test-owner-reference-uid-for-gateway spec: progressDeadlineSeconds: 600 revisionHistoryLimit: 10 @@ -55,7 +60,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -140,7 +145,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -257,18 +262,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -344,18 +352,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: @@ -454,6 +465,11 @@ metadata: gateway.envoyproxy.io/owning-gateway-namespace: namespace-2 name: envoy-namespace-2-gateway-2-107e8cb2 namespace: namespace-2 + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + name: gateway-2 + uid: test-owner-reference-uid-for-gateway spec: progressDeadlineSeconds: 600 revisionHistoryLimit: 10 @@ -499,7 +515,7 @@ spec: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -584,7 +600,7 @@ spec: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s @@ -701,18 +717,21 @@ spec: command: - envoy env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/envoy:distroless-v1.34.1 imagePullPolicy: IfNotPresent lifecycle: @@ -788,18 +807,21 @@ spec: command: - envoy-gateway env: - - name: ENVOY_GATEWAY_NAMESPACE - value: envoy-gateway-system - - name: ENVOY_SERVICE_ZONE + - name: ENVOY_POD_NAMESPACE valueFrom: fieldRef: apiVersion: v1 - fieldPath: metadata.annotations['topology.kubernetes.io/zone'] + fieldPath: metadata.namespace - name: ENVOY_POD_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.name + - name: ENVOY_SERVICE_ZONE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations['topology.kubernetes.io/zone'] image: docker.io/envoyproxy/gateway-dev:latest imagePullPolicy: IfNotPresent lifecycle: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/gateway-namespace-mode/hpa.yaml b/internal/infrastructure/kubernetes/proxy/testdata/gateway-namespace-mode/hpa.yaml index 0724e0c089..2c1be83e01 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/gateway-namespace-mode/hpa.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/gateway-namespace-mode/hpa.yaml @@ -7,6 +7,11 @@ metadata: gateway.envoyproxy.io/owning-gateway-namespace: namespace-1 name: envoy-namespace-1-gateway-1-e2117e41 namespace: namespace-1 + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + name: gateway-1 + uid: test-owner-reference-uid-for-gateway spec: maxReplicas: 3 metrics: @@ -34,6 +39,11 @@ metadata: gateway.envoyproxy.io/owning-gateway-namespace: namespace-2 name: envoy-namespace-2-gateway-2-107e8cb2 namespace: namespace-2 + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + name: gateway-2 + uid: test-owner-reference-uid-for-gateway spec: maxReplicas: 3 metrics: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/gateway-namespace-mode/service.yaml b/internal/infrastructure/kubernetes/proxy/testdata/gateway-namespace-mode/service.yaml index 50e94c01d2..db0d815079 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/gateway-namespace-mode/service.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/gateway-namespace-mode/service.yaml @@ -10,8 +10,22 @@ metadata: gateway.envoyproxy.io/owning-gateway-namespace: namespace-1 name: envoy-namespace-1-gateway-1-e2117e41 namespace: namespace-1 + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + name: gateway-1 + uid: test-owner-reference-uid-for-gateway spec: externalTrafficPolicy: Local + ports: + - name: EnvoyHTTPPort + port: 0 + protocol: TCP + targetPort: 8080 + - name: EnvoyHTTPSPort + port: 0 + protocol: TCP + targetPort: 8443 selector: app.kubernetes.io/component: proxy app.kubernetes.io/managed-by: envoy-gateway @@ -35,8 +49,22 @@ metadata: gateway.envoyproxy.io/owning-gateway-namespace: namespace-2 name: envoy-namespace-2-gateway-2-107e8cb2 namespace: namespace-2 + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + name: gateway-2 + uid: test-owner-reference-uid-for-gateway spec: externalTrafficPolicy: Local + ports: + - name: EnvoyHTTPPort + port: 0 + protocol: TCP + targetPort: 8080 + - name: EnvoyHTTPSPort + port: 0 + protocol: TCP + targetPort: 8443 selector: app.kubernetes.io/component: proxy app.kubernetes.io/managed-by: envoy-gateway diff --git a/internal/infrastructure/kubernetes/proxy/testdata/gateway-namespace-mode/serviceaccount.yaml b/internal/infrastructure/kubernetes/proxy/testdata/gateway-namespace-mode/serviceaccount.yaml index 8c8b81a6b4..13d5c8e03e 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/gateway-namespace-mode/serviceaccount.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/gateway-namespace-mode/serviceaccount.yaml @@ -10,6 +10,11 @@ metadata: gateway.envoyproxy.io/owning-gateway-namespace: namespace-1 name: envoy-namespace-1-gateway-1-e2117e41 namespace: namespace-1 + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + name: gateway-1 + uid: test-owner-reference-uid-for-gateway --- apiVersion: v1 kind: ServiceAccount @@ -23,3 +28,8 @@ metadata: gateway.envoyproxy.io/owning-gateway-namespace: namespace-2 name: envoy-namespace-2-gateway-2-107e8cb2 namespace: namespace-2 + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + name: gateway-2 + uid: test-owner-reference-uid-for-gateway diff --git a/internal/infrastructure/kubernetes/proxy/testdata/hpa/gateway-namespace-mode.yaml b/internal/infrastructure/kubernetes/proxy/testdata/hpa/gateway-namespace-mode.yaml new file mode 100644 index 0000000000..b449c891a7 --- /dev/null +++ b/internal/infrastructure/kubernetes/proxy/testdata/hpa/gateway-namespace-mode.yaml @@ -0,0 +1,26 @@ +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: ns1 + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + name: gateway-1 + uid: test-owner-reference-uid-for-gateway + name: envoy-ns1-gateway-1-02ae0474 + namespace: ns1 +spec: + metrics: + - resource: + name: cpu + target: + averageUtilization: 80 + type: Utilization + type: Resource + maxReplicas: 1 + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: envoy-ns1-gateway-1-02ae0474 diff --git a/internal/infrastructure/kubernetes/proxy/testdata/pdb/gateway-namespace-mode.yaml b/internal/infrastructure/kubernetes/proxy/testdata/pdb/gateway-namespace-mode.yaml new file mode 100644 index 0000000000..9689d80f74 --- /dev/null +++ b/internal/infrastructure/kubernetes/proxy/testdata/pdb/gateway-namespace-mode.yaml @@ -0,0 +1,19 @@ +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: envoy-ns1-gateway-1-02ae0474 + namespace: ns1 + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + name: gateway-1 + uid: test-owner-reference-uid-for-gateway +spec: + minAvailable: 1 + selector: + matchLabels: + app.kubernetes.io/component: proxy + app.kubernetes.io/managed-by: envoy-gateway + app.kubernetes.io/name: envoy + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: ns1 diff --git a/internal/infrastructure/kubernetes/proxy/testdata/serviceaccount/gateway-namespace-mode.yaml b/internal/infrastructure/kubernetes/proxy/testdata/serviceaccount/gateway-namespace-mode.yaml index 393ada177c..484e1f7068 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/serviceaccount/gateway-namespace-mode.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/serviceaccount/gateway-namespace-mode.yaml @@ -6,7 +6,12 @@ metadata: app.kubernetes.io/component: proxy app.kubernetes.io/managed-by: envoy-gateway app.kubernetes.io/name: envoy - gateway.envoyproxy.io/owning-gateway-name: default + gateway.envoyproxy.io/owning-gateway-name: gateway-1 gateway.envoyproxy.io/owning-gateway-namespace: ns1 - name: envoy-default-37a8eec1 + name: envoy-ns1-gateway-1-02ae0474 namespace: ns1 + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + name: gateway-1 + uid: test-owner-reference-uid-for-gateway diff --git a/internal/infrastructure/kubernetes/proxy/testdata/services/gateway-namespace-mode.yaml b/internal/infrastructure/kubernetes/proxy/testdata/services/gateway-namespace-mode.yaml new file mode 100644 index 0000000000..e063df2a05 --- /dev/null +++ b/internal/infrastructure/kubernetes/proxy/testdata/services/gateway-namespace-mode.yaml @@ -0,0 +1,35 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name: envoy + app.kubernetes.io/component: proxy + app.kubernetes.io/managed-by: envoy-gateway + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: ns1 + ownerReferences: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + name: gateway-1 + uid: test-owner-reference-uid-for-gateway + name: envoy-ns1-gateway-1-02ae0474 + namespace: ns1 +spec: + externalTrafficPolicy: Local + ports: + - name: EnvoyHTTPPort + port: 0 + protocol: TCP + targetPort: 8080 + - name: EnvoyHTTPSPort + port: 0 + protocol: TCP + targetPort: 8443 + selector: + app.kubernetes.io/name: envoy + app.kubernetes.io/component: proxy + app.kubernetes.io/managed-by: envoy-gateway + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: ns1 + sessionAffinity: None + type: LoadBalancer diff --git a/internal/infrastructure/kubernetes/proxy_configmap_test.go b/internal/infrastructure/kubernetes/proxy_configmap_test.go index ed7343dbe7..660a3cfc6d 100644 --- a/internal/infrastructure/kubernetes/proxy_configmap_test.go +++ b/internal/infrastructure/kubernetes/proxy_configmap_test.go @@ -10,14 +10,17 @@ import ( "os" "testing" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" - apiequality "k8s.io/apimachinery/pkg/api/equality" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake" + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/envoygateway" "github.com/envoyproxy/gateway/internal/envoygateway/config" "github.com/envoyproxy/gateway/internal/gatewayapi" @@ -27,24 +30,35 @@ import ( ) func TestCreateOrUpdateProxyConfigMap(t *testing.T) { - cfg, err := config.New(os.Stdout) - require.NoError(t, err) - - infra := ir.NewInfra() - infra.Proxy.Name = "test" - infra.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNamespaceLabel] = "default" - infra.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNameLabel] = infra.Proxy.Name - testCases := []struct { - name string - current *corev1.ConfigMap - expect *corev1.ConfigMap + name string + ns string + in *ir.Infra + gatewayNamespaceMode bool + current *corev1.ConfigMap + expect *corev1.ConfigMap }{ { name: "create configmap", + ns: "test", + in: &ir.Infra{ + Proxy: &ir.ProxyInfra{ + Name: "test", + Metadata: &ir.InfraMetadata{ + Labels: map[string]string{ + gatewayapi.OwningGatewayNamespaceLabel: "default", + gatewayapi.OwningGatewayNameLabel: "test", + }, + }, + }, + }, expect: &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + Kind: "ConfigMap", + APIVersion: "v1", + }, ObjectMeta: metav1.ObjectMeta{ - Namespace: cfg.ControllerNamespace, + Namespace: "test", Name: "envoy-test-9f86d081", Labels: map[string]string{ "app.kubernetes.io/name": "envoy", @@ -62,9 +76,21 @@ func TestCreateOrUpdateProxyConfigMap(t *testing.T) { }, { name: "update configmap", + ns: "test", + in: &ir.Infra{ + Proxy: &ir.ProxyInfra{ + Name: "test", + Metadata: &ir.InfraMetadata{ + Labels: map[string]string{ + gatewayapi.OwningGatewayNamespaceLabel: "default", + gatewayapi.OwningGatewayNameLabel: "test", + }, + }, + }, + }, current: &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Namespace: cfg.ControllerNamespace, + Namespace: "test", Name: "envoy-test", Labels: map[string]string{ "app.kubernetes.io/name": "envoy", @@ -77,8 +103,12 @@ func TestCreateOrUpdateProxyConfigMap(t *testing.T) { Data: map[string]string{"foo": "bar"}, }, expect: &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + Kind: "ConfigMap", + APIVersion: "v1", + }, ObjectMeta: metav1.ObjectMeta{ - Namespace: cfg.ControllerNamespace, + Namespace: "test", Name: "envoy-test-9f86d081", Labels: map[string]string{ "app.kubernetes.io/name": "envoy", @@ -94,10 +124,65 @@ func TestCreateOrUpdateProxyConfigMap(t *testing.T) { }, }, }, + { + name: "create configmap with gateway namespace mode", + ns: "test", + in: &ir.Infra{ + Proxy: &ir.ProxyInfra{ + Name: "ns1/gateway-1", + Namespace: "ns1", + Metadata: &ir.InfraMetadata{ + Labels: map[string]string{ + gatewayapi.OwningGatewayNamespaceLabel: "ns1", + gatewayapi.OwningGatewayNameLabel: "gateway-1", + }, + OwnerReference: &ir.ResourceMetadata{ + Kind: "Gateway", + Name: "gateway-1", + }, + }, + }, + }, + gatewayNamespaceMode: true, + expect: &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + Kind: "ConfigMap", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "ns1", + Name: "envoy-ns1-gateway-1-02ae0474", + Labels: map[string]string{ + "app.kubernetes.io/name": "envoy", + "app.kubernetes.io/component": "proxy", + "app.kubernetes.io/managed-by": "envoy-gateway", + gatewayapi.OwningGatewayNamespaceLabel: "ns1", + gatewayapi.OwningGatewayNameLabel: "gateway-1", + }, + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: "gateway.networking.k8s.io/v1", + Kind: "Gateway", + Name: "gateway-1", + UID: "foo.bar", + }, + }, + }, + Data: map[string]string{ + common.SdsCAFilename: common.GetSdsCAConfigMapData(proxy.XdsTLSCaFilepath), + common.SdsCertFilename: common.GetSdsCertConfigMapData(proxy.XdsTLSCertFilepath, proxy.XdsTLSKeyFilepath), + }, + }, + }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + ctx := context.Background() + cfg, err := config.New(os.Stdout) + require.NoError(t, err) + cfg.ControllerNamespace = tc.ns + var cli client.Client if tc.current != nil { cli = fakeclient.NewClientBuilder(). @@ -112,8 +197,16 @@ func TestCreateOrUpdateProxyConfigMap(t *testing.T) { Build() } kube := NewInfra(cli, cfg) - r := proxy.NewResourceRender(kube.ControllerNamespace, cfg.ControllerNamespace, kube.DNSDomain, infra.GetProxyInfra(), kube.EnvoyGateway) - err := kube.createOrUpdateConfigMap(context.Background(), r) + if tc.gatewayNamespaceMode { + kube.EnvoyGateway.Provider.Kubernetes.Deploy = &egv1a1.KubernetesDeployMode{ + Type: ptr.To(egv1a1.KubernetesDeployModeType(egv1a1.KubernetesDeployModeTypeGatewayNamespace)), + } + require.NoError(t, createGatewayForGatewayNamespaceMode(ctx, kube.Client)) + } + + r, err := proxy.NewResourceRender(ctx, kube, tc.in) + require.NoError(t, err) + err = kube.createOrUpdateConfigMap(ctx, r) require.NoError(t, err) actual := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ @@ -121,9 +214,10 @@ func TestCreateOrUpdateProxyConfigMap(t *testing.T) { Name: tc.expect.Name, }, } - require.NoError(t, kube.Client.Get(context.Background(), client.ObjectKeyFromObject(actual), actual)) - require.Equal(t, tc.expect.Data, actual.Data) - assert.True(t, apiequality.Semantic.DeepEqual(tc.expect.Labels, actual.Labels)) + require.NoError(t, kube.Client.Get(ctx, client.ObjectKeyFromObject(actual), actual)) + + opts := cmpopts.IgnoreFields(metav1.ObjectMeta{}, "ResourceVersion") + assert.True(t, cmp.Equal(tc.expect, actual, opts)) }) } } @@ -164,20 +258,22 @@ func TestDeleteConfigProxyMap(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + ctx := context.Background() cli := fakeclient.NewClientBuilder().WithScheme(envoygateway.GetScheme()).WithObjects(tc.current).Build() kube := NewInfra(cli, cfg) infra.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNamespaceLabel] = "default" infra.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNameLabel] = infra.Proxy.Name - r := proxy.NewResourceRender(kube.ControllerNamespace, cfg.ControllerNamespace, kube.DNSDomain, infra.GetProxyInfra(), kube.EnvoyGateway) + r, err := proxy.NewResourceRender(ctx, kube, infra) + require.NoError(t, err) cm := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Namespace: kube.ControllerNamespace, Name: r.Name(), }, } - err = kube.Client.Delete(context.Background(), cm) + err = kube.Client.Delete(ctx, cm) require.NoError(t, err) }) } diff --git a/internal/infrastructure/kubernetes/proxy_daemonset_test.go b/internal/infrastructure/kubernetes/proxy_daemonset_test.go index 0217d871ff..1b060338b7 100644 --- a/internal/infrastructure/kubernetes/proxy_daemonset_test.go +++ b/internal/infrastructure/kubernetes/proxy_daemonset_test.go @@ -47,13 +47,25 @@ func daemonsetWithSelectorAndLabel(ds *appsv1.DaemonSet, selector *metav1.LabelS return dCopy } -func TestCreateOrUpdateProxyDaemonSet(t *testing.T) { - cfg, err := config.New(os.Stdout) - require.NoError(t, err) +func daemonsetWithOwnerReferences(ds *appsv1.DaemonSet, ownerReferences []metav1.OwnerReference) *appsv1.DaemonSet { + dCopy := ds.DeepCopy() + dCopy.OwnerReferences = ownerReferences + return dCopy +} +func setupCreateOrUpdateProxyDaemonSet(gatewayNamespaceMode bool) (*appsv1.DaemonSet, *ir.Infra, *config.Server, error) { + ctx := context.Background() + cfg, err := config.New(os.Stdout) + if err != nil { + return nil, nil, nil, err + } infra := ir.NewInfra() infra.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNamespaceLabel] = "default" infra.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNameLabel] = infra.Proxy.Name + infra.Proxy.GetProxyMetadata().OwnerReference = &ir.ResourceMetadata{ + Kind: "Gateway", + Name: infra.Proxy.Name, + } infra.Proxy.Config = &egv1a1.EnvoyProxy{ Spec: egv1a1.EnvoyProxySpec{ Provider: &egv1a1.EnvoyProxyProvider{ @@ -67,30 +79,72 @@ func TestCreateOrUpdateProxyDaemonSet(t *testing.T) { }, } - r := proxy.NewResourceRender(cfg.ControllerNamespace, cfg.ControllerNamespace, cfg.DNSDomain, infra.GetProxyInfra(), cfg.EnvoyGateway) + cli := fakeclient.NewClientBuilder(). + WithScheme(envoygateway.GetScheme()). + Build() + kube := NewInfra(cli, cfg) + + if gatewayNamespaceMode { + cfg.EnvoyGateway.Provider.Kubernetes.Deploy = &egv1a1.KubernetesDeployMode{ + Type: ptr.To(egv1a1.KubernetesDeployModeType(egv1a1.KubernetesDeployModeTypeGatewayNamespace)), + } + infra.Proxy.Name = "ns1/gateway-1" + infra.Proxy.Namespace = "ns1" + infra.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNamespaceLabel] = "ns1" + infra.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNameLabel] = "gateway-1" + infra.Proxy.GetProxyMetadata().OwnerReference = &ir.ResourceMetadata{ + Kind: "Gateway", + Name: "gateway-1", + } + + if err := createGatewayForGatewayNamespaceMode(ctx, kube.Client); err != nil { + return nil, nil, nil, err + } + } + + r, err := proxy.NewResourceRender(ctx, kube, infra) + if err != nil { + return nil, nil, nil, err + } ds, err := r.DaemonSet() + if err != nil { + return nil, nil, nil, err + } + return ds, infra, cfg, nil +} + +func TestCreateOrUpdateProxyDaemonSet(t *testing.T) { + ds, infra, cfg, err := setupCreateOrUpdateProxyDaemonSet(false) + require.NoError(t, err) + + gwDs, gwInfra, gwCfg, err := setupCreateOrUpdateProxyDaemonSet(true) require.NoError(t, err) testCases := []struct { - name string - in *ir.Infra - current *appsv1.DaemonSet - want *appsv1.DaemonSet - wantErr bool + name string + cfg *config.Server + in *ir.Infra + gatewayNamespaceMode bool + current *appsv1.DaemonSet + want *appsv1.DaemonSet + wantErr bool }{ { name: "create daemonset", + cfg: cfg, in: infra, want: ds, }, { name: "daemonset exists", + cfg: cfg, in: infra, current: ds, want: ds, }, { name: "update daemonset image", + cfg: cfg, in: &ir.Infra{ Proxy: &ir.ProxyInfra{ Metadata: &ir.InfraMetadata{ @@ -122,6 +176,7 @@ func TestCreateOrUpdateProxyDaemonSet(t *testing.T) { }, { name: "update daemonset label", + cfg: cfg, in: &ir.Infra{ Proxy: &ir.ProxyInfra{ Metadata: &ir.InfraMetadata{ @@ -158,6 +213,7 @@ func TestCreateOrUpdateProxyDaemonSet(t *testing.T) { }, { name: "the daemonset originally has a selector and label, and an user add a new label to the custom label config", + cfg: cfg, in: &ir.Infra{ Proxy: &ir.ProxyInfra{ Metadata: &ir.InfraMetadata{ @@ -193,6 +249,7 @@ func TestCreateOrUpdateProxyDaemonSet(t *testing.T) { }, { name: "the daemonset originally has a selector and label, and an user update an existing custom label", + cfg: cfg, in: &ir.Infra{ Proxy: &ir.ProxyInfra{ Metadata: &ir.InfraMetadata{ @@ -227,10 +284,18 @@ func TestCreateOrUpdateProxyDaemonSet(t *testing.T) { current: daemonsetWithSelectorAndLabel(ds, resource2.GetSelector(map[string]string{"custom-label": "version1"}), map[string]string{"custom-label": "version1"}), wantErr: true, }, + { + name: "create daemonset with gateway namespace mode", + cfg: gwCfg, + in: gwInfra, + gatewayNamespaceMode: true, + want: daemonsetWithOwnerReferences(gwDs, []metav1.OwnerReference{{APIVersion: "gateway.networking.k8s.io/v1", Kind: "Gateway", Name: "gateway-1", UID: "foo.bar"}}), + }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + ctx := context.Background() var cli client.Client if tc.current != nil { cli = fakeclient.NewClientBuilder(). @@ -245,9 +310,14 @@ func TestCreateOrUpdateProxyDaemonSet(t *testing.T) { Build() } - kube := NewInfra(cli, cfg) - r := proxy.NewResourceRender(kube.ControllerNamespace, cfg.ControllerNamespace, kube.DNSDomain, tc.in.GetProxyInfra(), cfg.EnvoyGateway) - err := kube.createOrUpdateDaemonSet(context.Background(), r) + kube := NewInfra(cli, tc.cfg) + if tc.gatewayNamespaceMode { + require.NoError(t, createGatewayForGatewayNamespaceMode(ctx, kube.Client)) + } + + r, err := proxy.NewResourceRender(ctx, kube, tc.in) + require.NoError(t, err) + err = kube.createOrUpdateDaemonSet(ctx, r) if tc.wantErr { require.Error(t, err) return @@ -256,12 +326,13 @@ func TestCreateOrUpdateProxyDaemonSet(t *testing.T) { actual := &appsv1.DaemonSet{ ObjectMeta: metav1.ObjectMeta{ - Namespace: kube.ControllerNamespace, + Namespace: kube.GetResourceNamespace(tc.in), Name: proxy.ExpectedResourceHashedName(tc.in.Proxy.Name), }, } - require.NoError(t, kube.Client.Get(context.Background(), client.ObjectKeyFromObject(actual), actual)) + require.NoError(t, kube.Client.Get(ctx, client.ObjectKeyFromObject(actual), actual)) require.Equal(t, tc.want.Spec, actual.Spec) + require.Equal(t, tc.want.OwnerReferences, actual.OwnerReferences) }) } } diff --git a/internal/infrastructure/kubernetes/proxy_deployment_test.go b/internal/infrastructure/kubernetes/proxy_deployment_test.go index efe72d4c2e..b4528cb448 100644 --- a/internal/infrastructure/kubernetes/proxy_deployment_test.go +++ b/internal/infrastructure/kubernetes/proxy_deployment_test.go @@ -52,38 +52,92 @@ func deploymentWithSelectorAndLabel(deploy *appsv1.Deployment, selector *metav1. return dCopy } -func TestCreateOrUpdateProxyDeployment(t *testing.T) { - cfg, err := config.New(os.Stdout) - require.NoError(t, err) +func deploymentWithOwnerReferences(deploy *appsv1.Deployment, ownerReferences []metav1.OwnerReference) *appsv1.Deployment { + dCopy := deploy.DeepCopy() + dCopy.OwnerReferences = ownerReferences + return dCopy +} +func setupCreateOrUpdateProxyDeployment(gatewayNamespaceMode bool) (*appsv1.Deployment, *ir.Infra, *config.Server, error) { + ctx := context.Background() + cfg, err := config.New(os.Stdout) + if err != nil { + return nil, nil, nil, err + } infra := ir.NewInfra() infra.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNamespaceLabel] = "default" infra.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNameLabel] = infra.Proxy.Name + infra.Proxy.GetProxyMetadata().OwnerReference = &ir.ResourceMetadata{ + Kind: "Gateway", + Name: infra.Proxy.Name, + } + + cli := fakeclient.NewClientBuilder(). + WithScheme(envoygateway.GetScheme()). + Build() + kube := NewInfra(cli, cfg) + + if gatewayNamespaceMode { + cfg.EnvoyGateway.Provider.Kubernetes.Deploy = &egv1a1.KubernetesDeployMode{ + Type: ptr.To(egv1a1.KubernetesDeployModeType(egv1a1.KubernetesDeployModeTypeGatewayNamespace)), + } + infra.Proxy.Name = "ns1/gateway-1" + infra.Proxy.Namespace = "ns1" + infra.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNamespaceLabel] = "ns1" + infra.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNameLabel] = "gateway-1" + infra.Proxy.GetProxyMetadata().OwnerReference = &ir.ResourceMetadata{ + Kind: "Gateway", + Name: "gateway-1", + } + + if err := createGatewayForGatewayNamespaceMode(ctx, kube.Client); err != nil { + return nil, nil, nil, err + } + } - r := proxy.NewResourceRender(cfg.ControllerNamespace, cfg.ControllerNamespace, cfg.DNSDomain, infra.GetProxyInfra(), cfg.EnvoyGateway) + r, err := proxy.NewResourceRender(ctx, kube, infra) + if err != nil { + return nil, nil, nil, err + } deploy, err := r.Deployment() + if err != nil { + return nil, nil, nil, err + } + return deploy, infra, cfg, nil +} + +func TestCreateOrUpdateProxyDeployment(t *testing.T) { + deploy, infra, cfg, err := setupCreateOrUpdateProxyDeployment(false) + require.NoError(t, err) + + gwDeploy, gwInfra, gwCfg, err := setupCreateOrUpdateProxyDeployment(true) require.NoError(t, err) testCases := []struct { - name string - in *ir.Infra - current *appsv1.Deployment - want *appsv1.Deployment - wantErr bool + name string + cfg *config.Server + in *ir.Infra + gatewayNamespaceMode bool + current *appsv1.Deployment + want *appsv1.Deployment + wantErr bool }{ { name: "create deployment", + cfg: cfg, in: infra, want: deploy, }, { name: "deployment exists", + cfg: cfg, in: infra, current: deploy, want: deploy, }, { name: "update deployment image", + cfg: cfg, in: &ir.Infra{ Proxy: &ir.ProxyInfra{ Metadata: &ir.InfraMetadata{ @@ -115,6 +169,7 @@ func TestCreateOrUpdateProxyDeployment(t *testing.T) { }, { name: "update deployment label", + cfg: cfg, in: &ir.Infra{ Proxy: &ir.ProxyInfra{ Metadata: &ir.InfraMetadata{ @@ -149,6 +204,7 @@ func TestCreateOrUpdateProxyDeployment(t *testing.T) { }, { name: "the daemonset originally has a selector and label, and an user add a new label to the custom label config", + cfg: cfg, in: &ir.Infra{ Proxy: &ir.ProxyInfra{ Metadata: &ir.InfraMetadata{ @@ -186,6 +242,7 @@ func TestCreateOrUpdateProxyDeployment(t *testing.T) { }, { name: "the deployment originally has a selector and label, and an user update an existing custom label", + cfg: cfg, in: &ir.Infra{ Proxy: &ir.ProxyInfra{ Metadata: &ir.InfraMetadata{ @@ -220,10 +277,18 @@ func TestCreateOrUpdateProxyDeployment(t *testing.T) { current: deploymentWithSelectorAndLabel(deploy, resource2.GetSelector(map[string]string{"custom-label": "version1"}), map[string]string{"custom-label": "version1"}), wantErr: true, }, + { + name: "create deployment with gateway namespace mode", + cfg: gwCfg, + in: gwInfra, + gatewayNamespaceMode: true, + want: deploymentWithOwnerReferences(gwDeploy, []metav1.OwnerReference{{APIVersion: "gateway.networking.k8s.io/v1", Kind: "Gateway", Name: "gateway-1", UID: "foo.bar"}}), + }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + ctx := context.Background() var cli client.Client if tc.current != nil { cli = fakeclient.NewClientBuilder(). @@ -238,9 +303,14 @@ func TestCreateOrUpdateProxyDeployment(t *testing.T) { Build() } - kube := NewInfra(cli, cfg) - r := proxy.NewResourceRender(kube.ControllerNamespace, cfg.ControllerNamespace, kube.DNSDomain, tc.in.GetProxyInfra(), cfg.EnvoyGateway) - err := kube.createOrUpdateDeployment(context.Background(), r) + kube := NewInfra(cli, tc.cfg) + if tc.gatewayNamespaceMode { + require.NoError(t, createGatewayForGatewayNamespaceMode(ctx, kube.Client)) + } + + r, err := proxy.NewResourceRender(ctx, kube, tc.in) + require.NoError(t, err) + err = kube.createOrUpdateDeployment(ctx, r) if tc.wantErr { require.Error(t, err) return @@ -249,12 +319,13 @@ func TestCreateOrUpdateProxyDeployment(t *testing.T) { actual := &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ - Namespace: kube.ControllerNamespace, + Namespace: kube.GetResourceNamespace(tc.in), Name: proxy.ExpectedResourceHashedName(tc.in.Proxy.Name), }, } - require.NoError(t, kube.Client.Get(context.Background(), client.ObjectKeyFromObject(actual), actual)) + require.NoError(t, kube.Client.Get(ctx, client.ObjectKeyFromObject(actual), actual)) require.Equal(t, tc.want.Spec, actual.Spec) + require.Equal(t, tc.want.OwnerReferences, actual.OwnerReferences) }) } } @@ -280,14 +351,16 @@ func TestDeleteProxyDeployment(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + ctx := context.Background() kube := NewInfra(cli, cfg) infra := ir.NewInfra() infra.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNamespaceLabel] = "default" infra.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNameLabel] = infra.Proxy.Name - r := proxy.NewResourceRender(kube.ControllerNamespace, cfg.ControllerNamespace, kube.DNSDomain, infra.GetProxyInfra(), kube.EnvoyGateway) + r, err := proxy.NewResourceRender(ctx, kube, infra) + require.NoError(t, err) - err := kube.createOrUpdateDeployment(context.Background(), r) + err = kube.createOrUpdateDeployment(ctx, r) require.NoError(t, err) deployment := &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ @@ -295,7 +368,7 @@ func TestDeleteProxyDeployment(t *testing.T) { Name: r.Name(), }, } - err = kube.Client.Delete(context.Background(), deployment) + err = kube.Client.Delete(ctx, deployment) require.NoError(t, err) }) } diff --git a/internal/infrastructure/kubernetes/proxy_infra.go b/internal/infrastructure/kubernetes/proxy_infra.go index 5250489878..c4d851772d 100644 --- a/internal/infrastructure/kubernetes/proxy_infra.go +++ b/internal/infrastructure/kubernetes/proxy_infra.go @@ -8,40 +8,87 @@ package kubernetes import ( "context" "errors" + "fmt" + "k8s.io/apimachinery/pkg/types" + gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" + + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" + "github.com/envoyproxy/gateway/internal/gatewayapi/resource" "github.com/envoyproxy/gateway/internal/infrastructure/kubernetes/proxy" "github.com/envoyproxy/gateway/internal/ir" ) // CreateOrUpdateProxyInfra creates the managed kube infra, if it doesn't exist. -func (i *Infra) CreateOrUpdateProxyInfra(ctx context.Context, infra *ir.Infra) error { - if infra == nil { +func (i *Infra) CreateOrUpdateProxyInfra(ctx context.Context, irInfra *ir.Infra) error { + if irInfra == nil { return errors.New("infra ir is nil") } - if infra.Proxy == nil { + if irInfra.Proxy == nil { return errors.New("infra proxy ir is nil") } - envoyNamespace := i.GetResourceNamespace(infra) - r := proxy.NewResourceRender(envoyNamespace, i.ControllerNamespace, i.DNSDomain, infra.GetProxyInfra(), i.EnvoyGateway) + r, err := proxy.NewResourceRender(ctx, i, irInfra) + if err != nil { + return fmt.Errorf("failed to initialize proxy resource render: %w", err) + } return i.createOrUpdate(ctx, r) } // DeleteProxyInfra removes the managed kube infra, if it doesn't exist. -func (i *Infra) DeleteProxyInfra(ctx context.Context, infra *ir.Infra) error { - if infra == nil { +func (i *Infra) DeleteProxyInfra(ctx context.Context, irInfra *ir.Infra) error { + if irInfra == nil { return errors.New("infra ir is nil") } - envoyNamespace := i.GetResourceNamespace(infra) - r := proxy.NewResourceRender(envoyNamespace, i.ControllerNamespace, i.DNSDomain, infra.GetProxyInfra(), i.EnvoyGateway) + r, err := proxy.NewResourceRender(ctx, i, irInfra) + if err != nil { + return fmt.Errorf("failed to create proxy resource render: %w", err) + } return i.delete(ctx, r) } -func (i *Infra) GetResourceNamespace(infra *ir.Infra) string { +func (i *Infra) GetControllerNamespace() string { + return i.ControllerNamespace +} + +func (i *Infra) GetDNSDomain() string { + return i.DNSDomain +} + +func (i *Infra) GetEnvoyGateway() *egv1a1.EnvoyGateway { + return i.EnvoyGateway +} + +func (i *Infra) GetOwnerReferenceUID(ctx context.Context, irInfra *ir.Infra) (map[string]types.UID, error) { + ownerReferenceUID := make(map[string]types.UID) + + if i.EnvoyGateway.GatewayNamespaceMode() { + if irInfra.GetProxyInfra().GetProxyMetadata() == nil { + return nil, errors.New("infra proxy metadata ir is nil") + } + if irInfra.GetProxyInfra().GetProxyMetadata().OwnerReference == nil { + return nil, errors.New("infra proxy metadata owner reference ir is nil") + } + key := types.NamespacedName{ + Namespace: i.GetResourceNamespace(irInfra), + Name: irInfra.GetProxyInfra().GetProxyMetadata().OwnerReference.Name, + } + gatewayUID, err := i.Client.GetUID(ctx, key, &gwapiv1.Gateway{}) + if err != nil { + return nil, err + } + ownerReferenceUID[resource.KindGateway] = gatewayUID + } + // TODO: set GatewayClass UID when enable merged gateways + + return ownerReferenceUID, nil +} + +func (i *Infra) GetResourceNamespace(irInfra *ir.Infra) string { if i.EnvoyGateway.GatewayNamespaceMode() { - return infra.Proxy.Namespace + return irInfra.Proxy.Namespace } return i.ControllerNamespace } diff --git a/internal/infrastructure/kubernetes/proxy_infra_test.go b/internal/infrastructure/kubernetes/proxy_infra_test.go index 36eec17056..d2630a07ff 100644 --- a/internal/infrastructure/kubernetes/proxy_infra_test.go +++ b/internal/infrastructure/kubernetes/proxy_infra_test.go @@ -223,3 +223,16 @@ func TestDeleteProxyInfra(t *testing.T) { }) } } + +// This function uses setup for GatewayNamespace mode. +// When enable GatewayNamespace mode, ProxyInfra Get OwnerReference from Gateway. +func createGatewayForGatewayNamespaceMode(ctx context.Context, client *InfraClient) error { + gw := &gwapiv1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "ns1", + Name: "gateway-1", + UID: "foo.bar", + }, + } + return client.Create(ctx, gw) +} diff --git a/internal/infrastructure/kubernetes/proxy_service_test.go b/internal/infrastructure/kubernetes/proxy_service_test.go index 296115d4b3..bc30ca7b0c 100644 --- a/internal/infrastructure/kubernetes/proxy_service_test.go +++ b/internal/infrastructure/kubernetes/proxy_service_test.go @@ -27,16 +27,18 @@ func TestDeleteProxyService(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + ctx := context.Background() kube := newTestInfra(t) infra := ir.NewInfra() infra.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNamespaceLabel] = "default" infra.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNameLabel] = infra.Proxy.Name - r := proxy.NewResourceRender(kube.ControllerNamespace, kube.ControllerNamespace, kube.DNSDomain, infra.GetProxyInfra(), kube.EnvoyGateway) - err := kube.createOrUpdateService(context.Background(), r) + r, err := proxy.NewResourceRender(ctx, kube, infra) + require.NoError(t, err) + err = kube.createOrUpdateService(ctx, r) require.NoError(t, err) - err = kube.deleteService(context.Background(), r) + err = kube.deleteService(ctx, r) require.NoError(t, err) }) } diff --git a/internal/infrastructure/kubernetes/proxy_serviceaccount_test.go b/internal/infrastructure/kubernetes/proxy_serviceaccount_test.go index 06eb5ef6e7..62c1b4963c 100644 --- a/internal/infrastructure/kubernetes/proxy_serviceaccount_test.go +++ b/internal/infrastructure/kubernetes/proxy_serviceaccount_test.go @@ -16,9 +16,11 @@ import ( "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake" + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/envoygateway" "github.com/envoyproxy/gateway/internal/envoygateway/config" "github.com/envoyproxy/gateway/internal/gatewayapi" @@ -28,11 +30,12 @@ import ( func TestCreateOrUpdateProxyServiceAccount(t *testing.T) { testCases := []struct { - name string - ns string - in *ir.Infra - current *corev1.ServiceAccount - want *corev1.ServiceAccount + name string + ns string + in *ir.Infra + gatewayNamespaceMode bool + current *corev1.ServiceAccount + want *corev1.ServiceAccount }{ { name: "create-sa", @@ -164,10 +167,57 @@ func TestCreateOrUpdateProxyServiceAccount(t *testing.T) { }, }, }, + { + name: "create-sa-with-gateway-namespace-mode", + ns: "test", + in: &ir.Infra{ + Proxy: &ir.ProxyInfra{ + Name: "ns1/gateway-1", + Namespace: "ns1", + Metadata: &ir.InfraMetadata{ + Labels: map[string]string{ + gatewayapi.OwningGatewayNamespaceLabel: "ns1", + gatewayapi.OwningGatewayNameLabel: "gateway-1", + }, + OwnerReference: &ir.ResourceMetadata{ + Kind: "Gateway", + Name: "gateway-1", + }, + }, + }, + }, + gatewayNamespaceMode: true, + want: &corev1.ServiceAccount{ + TypeMeta: metav1.TypeMeta{ + Kind: "ServiceAccount", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "ns1", + Name: "envoy-ns1-gateway-1-02ae0474", + Labels: map[string]string{ + "app.kubernetes.io/name": "envoy", + "app.kubernetes.io/component": "proxy", + "app.kubernetes.io/managed-by": "envoy-gateway", + gatewayapi.OwningGatewayNamespaceLabel: "ns1", + gatewayapi.OwningGatewayNameLabel: "gateway-1", + }, + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: "gateway.networking.k8s.io/v1", + Kind: "Gateway", + Name: "gateway-1", + UID: "foo.bar", + }, + }, + }, + }, + }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + ctx := context.Background() cfg, err := config.New(os.Stdout) require.NoError(t, err) cfg.ControllerNamespace = tc.ns @@ -187,18 +237,25 @@ func TestCreateOrUpdateProxyServiceAccount(t *testing.T) { } kube := NewInfra(cli, cfg) + if tc.gatewayNamespaceMode { + kube.EnvoyGateway.Provider.Kubernetes.Deploy = &egv1a1.KubernetesDeployMode{ + Type: ptr.To(egv1a1.KubernetesDeployModeType(egv1a1.KubernetesDeployModeTypeGatewayNamespace)), + } + require.NoError(t, createGatewayForGatewayNamespaceMode(ctx, kube.Client)) + } - r := proxy.NewResourceRender(kube.ControllerNamespace, cfg.ControllerNamespace, kube.DNSDomain, tc.in.GetProxyInfra(), cfg.EnvoyGateway) - err = kube.createOrUpdateServiceAccount(context.Background(), r) + r, err := proxy.NewResourceRender(ctx, kube, tc.in) + require.NoError(t, err) + err = kube.createOrUpdateServiceAccount(ctx, r) require.NoError(t, err) actual := &corev1.ServiceAccount{ ObjectMeta: metav1.ObjectMeta{ - Namespace: kube.ControllerNamespace, + Namespace: kube.GetResourceNamespace(tc.in), Name: proxy.ExpectedResourceHashedName(tc.in.Proxy.Name), }, } - require.NoError(t, kube.Client.Get(context.Background(), client.ObjectKeyFromObject(actual), actual)) + require.NoError(t, kube.Client.Get(ctx, client.ObjectKeyFromObject(actual), actual)) opts := cmpopts.IgnoreFields(metav1.ObjectMeta{}, "ResourceVersion") assert.True(t, cmp.Equal(tc.want, actual, opts)) @@ -216,17 +273,19 @@ func TestDeleteProxyServiceAccount(t *testing.T) { } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + ctx := context.Background() kube := newTestInfra(t) infra := ir.NewInfra() infra.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNamespaceLabel] = "default" infra.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNameLabel] = infra.Proxy.Name - r := proxy.NewResourceRender(kube.ControllerNamespace, kube.ControllerNamespace, kube.DNSDomain, infra.GetProxyInfra(), kube.EnvoyGateway) + r, err := proxy.NewResourceRender(ctx, kube, infra) + require.NoError(t, err) - err := kube.createOrUpdateServiceAccount(context.Background(), r) + err = kube.createOrUpdateServiceAccount(ctx, r) require.NoError(t, err) - err = kube.deleteServiceAccount(context.Background(), r) + err = kube.deleteServiceAccount(ctx, r) require.NoError(t, err) }) } diff --git a/internal/ir/infra.go b/internal/ir/infra.go index d6ab713c83..f4c95bd335 100644 --- a/internal/ir/infra.go +++ b/internal/ir/infra.go @@ -67,6 +67,8 @@ type InfraMetadata struct { // Labels define a map of string keys and values that can be used to organize // and categorize proxy infrastructure objects. Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"` + // OwnerReference define the values that be used to set ownerReference for proxy infrastructure objects. + OwnerReference *ResourceMetadata `json:"ownerReference,omitempty" yaml:"ownerReference,omitempty"` } // ProxyListener defines the listener configuration of the proxy infrastructure. diff --git a/internal/ir/xds.go b/internal/ir/xds.go index 30bd1d1fcb..2ee6c966fa 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -445,6 +445,20 @@ type TLSCACertificate struct { Certificate []byte `json:"certificate,omitempty" yaml:"certificate,omitempty"` } +// SubjectAltName holds the subject alternative name for the certificate +// This is the internal representation of the SubjectAltName in the Gateway API +// https://github.com/kubernetes-sigs/gateway-api/blob/6fbbd90954c2a30a6502cbb22ec6e7f3359ed3a0/apis/v1alpha3/backendtlspolicy_types.go#L177 +// +k8s:deepcopy-gen=true +type SubjectAltName struct { + // Only one of the following fields should be set. + // Hostname contains Subject Alternative Name specified in DNS name format. + Hostname *string `json:"hostname,omitempty" yaml:"hostname,omitempty"` + // URI contains Subject Alternative Name specified in a full URI format. + // It MUST include both a scheme (e.g., "http" or "ftp") and a scheme-specific-part. + // Common values include SPIFFE IDs like "spiffe://mycluster.example.com/ns/myns/sa/svc1sa". + URI *string `json:"uri,omitempty" yaml:"uri,omitempty"` +} + func (t TLSCertificate) Validate() error { var errs error if len(t.Certificate) == 0 { @@ -2850,6 +2864,7 @@ type TLSUpstreamConfig struct { UseSystemTrustStore bool `json:"useSystemTrustStore,omitempty" yaml:"useSystemTrustStore,omitempty"` CACertificate *TLSCACertificate `json:"caCertificate,omitempty" yaml:"caCertificate,omitempty"` TLSConfig `json:",inline"` + SubjectAltNames []SubjectAltName `json:"subjectAltNames,omitempty" yaml:"subjectAltNames,omitempty"` } func (t *TLSUpstreamConfig) ToTLSConfig() (*tls.Config, error) { diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go index eb5f63edb8..b7f47de7ea 100644 --- a/internal/ir/zz_generated.deepcopy.go +++ b/internal/ir/zz_generated.deepcopy.go @@ -1969,6 +1969,11 @@ func (in *InfraMetadata) DeepCopyInto(out *InfraMetadata) { (*out)[key] = val } } + if in.OwnerReference != nil { + in, out := &in.OwnerReference, &out.OwnerReference + *out = new(ResourceMetadata) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InfraMetadata. @@ -3213,6 +3218,31 @@ func (in *StringMatch) DeepCopy() *StringMatch { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubjectAltName) DeepCopyInto(out *SubjectAltName) { + *out = *in + if in.Hostname != nil { + in, out := &in.Hostname, &out.Hostname + *out = new(string) + **out = **in + } + if in.URI != nil { + in, out := &in.URI, &out.URI + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubjectAltName. +func (in *SubjectAltName) DeepCopy() *SubjectAltName { + if in == nil { + return nil + } + out := new(SubjectAltName) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TCPClientTimeout) DeepCopyInto(out *TCPClientTimeout) { *out = *in @@ -3588,6 +3618,13 @@ func (in *TLSUpstreamConfig) DeepCopyInto(out *TLSUpstreamConfig) { (*in).DeepCopyInto(*out) } in.TLSConfig.DeepCopyInto(&out.TLSConfig) + if in.SubjectAltNames != nil { + in, out := &in.SubjectAltNames, &out.SubjectAltNames + *out = make([]SubjectAltName, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSUpstreamConfig. diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go index b4eb87c0f3..8ee2266901 100644 --- a/internal/provider/kubernetes/controller.go +++ b/internal/provider/kubernetes/controller.go @@ -1069,6 +1069,7 @@ func (r *gatewayAPIReconciler) processGateways(ctx context.Context, managedGC *g continue } } + r.log.Info("processing Gateway", "namespace", gtw.Namespace, "name", gtw.Name) resourceMap.allAssociatedNamespaces.Insert(gtw.Namespace) @@ -2011,6 +2012,11 @@ func (r *gatewayAPIReconciler) processGatewayClassParamsRef(ctx context.Context, return fmt.Errorf("failed to find envoyproxy %s/%s: %w", r.namespace, gc.Spec.ParametersRef.Name, err) } + // Check for incompatible configuration: both MergeGateways and GatewayNamespaceMode enabled + if r.gatewayNamespaceMode && ep.Spec.MergeGateways != nil && *ep.Spec.MergeGateways { + return fmt.Errorf("using Merged Gateways with Gateway Namespace Mode is not supported.") + } + if err := r.processEnvoyProxy(ep, resourceMap); err != nil { return err } diff --git a/internal/provider/kubernetes/controller_test.go b/internal/provider/kubernetes/controller_test.go index 3914071992..86eba77554 100644 --- a/internal/provider/kubernetes/controller_test.go +++ b/internal/provider/kubernetes/controller_test.go @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" @@ -156,10 +157,12 @@ func TestProcessGatewayClassParamsRef(t *testing.T) { gcCtrlName := gwapiv1.GatewayController(egv1a1.GatewayControllerName) testCases := []struct { - name string - gc *gwapiv1.GatewayClass - ep *egv1a1.EnvoyProxy - expected bool + name string + gc *gwapiv1.GatewayClass + ep *egv1a1.EnvoyProxy + gatewayNamespaceMode bool + expected bool + expectedError string }{ { name: "valid envoyproxy reference", @@ -251,6 +254,88 @@ func TestProcessGatewayClassParamsRef(t *testing.T) { }, expected: false, }, + { + name: "incompatible configuration: merged gateways with gateway namespace mode", + gc: &gwapiv1.GatewayClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-merged-gw", + }, + Spec: gwapiv1.GatewayClassSpec{ + ControllerName: gcCtrlName, + ParametersRef: &gwapiv1.ParametersReference{ + Group: gwapiv1.Group(egv1a1.GroupVersion.Group), + Kind: gwapiv1.Kind(egv1a1.KindEnvoyProxy), + Name: "test-merge-gw", + Namespace: gatewayapi.NamespacePtr(config.DefaultNamespace), + }, + }, + }, + ep: &egv1a1.EnvoyProxy{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: config.DefaultNamespace, + Name: "test-merge-gw", + }, + Spec: egv1a1.EnvoyProxySpec{ + MergeGateways: ptr.To(true), + }, + }, + gatewayNamespaceMode: true, + expected: false, + expectedError: "using Merged Gateways with Gateway Namespace Mode is not supported.", + }, + { + name: "valid merged gateways enabled configuration", + gc: &gwapiv1.GatewayClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-merge-gw", + }, + Spec: gwapiv1.GatewayClassSpec{ + ControllerName: gcCtrlName, + ParametersRef: &gwapiv1.ParametersReference{ + Group: gwapiv1.Group(egv1a1.GroupVersion.Group), + Kind: gwapiv1.Kind(egv1a1.KindEnvoyProxy), + Name: "test-merge-gw", + Namespace: gatewayapi.NamespacePtr(config.DefaultNamespace), + }, + }, + }, + ep: &egv1a1.EnvoyProxy{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: config.DefaultNamespace, + Name: "test-merge-gw", + }, + Spec: egv1a1.EnvoyProxySpec{ + MergeGateways: ptr.To(true), + }, + }, + gatewayNamespaceMode: false, + expected: true, + }, + { + name: "valid gateway namespace mode enabled configuration", + gc: &gwapiv1.GatewayClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + }, + Spec: gwapiv1.GatewayClassSpec{ + ControllerName: gcCtrlName, + ParametersRef: &gwapiv1.ParametersReference{ + Group: gwapiv1.Group(egv1a1.GroupVersion.Group), + Kind: gwapiv1.Kind(egv1a1.KindEnvoyProxy), + Name: "test", + Namespace: gatewayapi.NamespacePtr(config.DefaultNamespace), + }, + }, + }, + ep: &egv1a1.EnvoyProxy{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: config.DefaultNamespace, + Name: "test", + }, + }, + gatewayNamespaceMode: true, + expected: true, + }, } for i := range testCases { @@ -260,9 +345,10 @@ func TestProcessGatewayClassParamsRef(t *testing.T) { logger := logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo) r := &gatewayAPIReconciler{ - log: logger, - classController: gcCtrlName, - namespace: config.DefaultNamespace, + log: logger, + classController: gcCtrlName, + namespace: config.DefaultNamespace, + gatewayNamespaceMode: tc.gatewayNamespaceMode, } // Run the test cases. @@ -287,6 +373,9 @@ func TestProcessGatewayClassParamsRef(t *testing.T) { require.Equal(t, tc.ep, resourceTree.EnvoyProxyForGatewayClass) } else { require.Error(t, err) + if tc.expectedError != "" { + require.Contains(t, err.Error(), tc.expectedError) + } } }) } diff --git a/internal/provider/kubernetes/topology_injector.go b/internal/provider/kubernetes/topology_injector.go index f507c72989..1757024ff7 100644 --- a/internal/provider/kubernetes/topology_injector.go +++ b/internal/provider/kubernetes/topology_injector.go @@ -72,7 +72,7 @@ func (m *ProxyTopologyInjector) Handle(ctx context.Context, req admission.Reques if binding.Annotations == nil { binding.Annotations = map[string]string{} } - binding.Annotations[corev1.LabelTopologyZone] = zone + binding.Annotations[corev1.LabelTopologyZone] = fmt.Sprintf("%q", zone) } else { return admission.Allowed("Skipping injection due to missing topology label on node") } diff --git a/internal/provider/kubernetes/topology_injector_test.go b/internal/provider/kubernetes/topology_injector_test.go index 6128214a80..399229c4a2 100644 --- a/internal/provider/kubernetes/topology_injector_test.go +++ b/internal/provider/kubernetes/topology_injector_test.go @@ -41,7 +41,7 @@ func TestProxyTopologyInjector_Handle(t *testing.T) { defaultNode := &corev1.Node{ ObjectMeta: metav1.ObjectMeta{ Name: "node-A", - Labels: map[string]string{corev1.LabelTopologyZone: "zone1"}, + Labels: map[string]string{corev1.LabelTopologyZone: "0"}, }, } @@ -67,7 +67,7 @@ func TestProxyTopologyInjector_Handle(t *testing.T) { Operation: "add", Path: "/metadata/annotations", Value: map[string]interface{}{ - "topology.kubernetes.io/zone": "zone1", + "topology.kubernetes.io/zone": "\"0\"", }, }}, }, diff --git a/internal/xds/bootstrap/bootstrap.yaml.tpl b/internal/xds/bootstrap/bootstrap.yaml.tpl index c4bb5e4843..8cb1824b23 100644 --- a/internal/xds/bootstrap/bootstrap.yaml.tpl +++ b/internal/xds/bootstrap/bootstrap.yaml.tpl @@ -12,7 +12,7 @@ cluster_manager: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) {{- if .StatsMatcher }} stats_config: stats_matcher: @@ -186,7 +186,7 @@ static_resources: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s diff --git a/internal/xds/bootstrap/testdata/render/custom-server-port.yaml b/internal/xds/bootstrap/testdata/render/custom-server-port.yaml index 79b64b4725..6ac82d857a 100644 --- a/internal/xds/bootstrap/testdata/render/custom-server-port.yaml +++ b/internal/xds/bootstrap/testdata/render/custom-server-port.yaml @@ -12,7 +12,7 @@ cluster_manager: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -97,7 +97,7 @@ static_resources: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s diff --git a/internal/xds/bootstrap/testdata/render/custom-stats-matcher.yaml b/internal/xds/bootstrap/testdata/render/custom-stats-matcher.yaml index 93f4c1a8c4..42602485aa 100644 --- a/internal/xds/bootstrap/testdata/render/custom-stats-matcher.yaml +++ b/internal/xds/bootstrap/testdata/render/custom-stats-matcher.yaml @@ -12,7 +12,7 @@ cluster_manager: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) stats_config: stats_matcher: inclusion_list: @@ -108,7 +108,7 @@ static_resources: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s diff --git a/internal/xds/bootstrap/testdata/render/disable-prometheus.yaml b/internal/xds/bootstrap/testdata/render/disable-prometheus.yaml index 937296ef3a..55a96506e6 100644 --- a/internal/xds/bootstrap/testdata/render/disable-prometheus.yaml +++ b/internal/xds/bootstrap/testdata/render/disable-prometheus.yaml @@ -12,7 +12,7 @@ cluster_manager: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -50,7 +50,7 @@ static_resources: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s diff --git a/internal/xds/bootstrap/testdata/render/enable-prometheus-brotli-compression.yaml b/internal/xds/bootstrap/testdata/render/enable-prometheus-brotli-compression.yaml index 652d532c9f..80b5de346d 100644 --- a/internal/xds/bootstrap/testdata/render/enable-prometheus-brotli-compression.yaml +++ b/internal/xds/bootstrap/testdata/render/enable-prometheus-brotli-compression.yaml @@ -12,7 +12,7 @@ cluster_manager: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -113,7 +113,7 @@ static_resources: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s diff --git a/internal/xds/bootstrap/testdata/render/enable-prometheus-gzip-compression.yaml b/internal/xds/bootstrap/testdata/render/enable-prometheus-gzip-compression.yaml index 66c8d04049..a63969b5a5 100644 --- a/internal/xds/bootstrap/testdata/render/enable-prometheus-gzip-compression.yaml +++ b/internal/xds/bootstrap/testdata/render/enable-prometheus-gzip-compression.yaml @@ -12,7 +12,7 @@ cluster_manager: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -113,7 +113,7 @@ static_resources: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s diff --git a/internal/xds/bootstrap/testdata/render/enable-prometheus.yaml b/internal/xds/bootstrap/testdata/render/enable-prometheus.yaml index 05aae78543..947f274350 100644 --- a/internal/xds/bootstrap/testdata/render/enable-prometheus.yaml +++ b/internal/xds/bootstrap/testdata/render/enable-prometheus.yaml @@ -12,7 +12,7 @@ cluster_manager: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -97,7 +97,7 @@ static_resources: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s diff --git a/internal/xds/bootstrap/testdata/render/ipv6.yaml b/internal/xds/bootstrap/testdata/render/ipv6.yaml index 90fa14380b..bafa099de8 100644 --- a/internal/xds/bootstrap/testdata/render/ipv6.yaml +++ b/internal/xds/bootstrap/testdata/render/ipv6.yaml @@ -12,7 +12,7 @@ cluster_manager: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -98,7 +98,7 @@ static_resources: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s diff --git a/internal/xds/bootstrap/testdata/render/otel-metrics-backendref.yaml b/internal/xds/bootstrap/testdata/render/otel-metrics-backendref.yaml index de2379c1fd..d89c3a85bf 100644 --- a/internal/xds/bootstrap/testdata/render/otel-metrics-backendref.yaml +++ b/internal/xds/bootstrap/testdata/render/otel-metrics-backendref.yaml @@ -12,7 +12,7 @@ cluster_manager: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -75,7 +75,7 @@ static_resources: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s diff --git a/internal/xds/bootstrap/testdata/render/otel-metrics.yaml b/internal/xds/bootstrap/testdata/render/otel-metrics.yaml index de2379c1fd..d89c3a85bf 100644 --- a/internal/xds/bootstrap/testdata/render/otel-metrics.yaml +++ b/internal/xds/bootstrap/testdata/render/otel-metrics.yaml @@ -12,7 +12,7 @@ cluster_manager: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -75,7 +75,7 @@ static_resources: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s diff --git a/internal/xds/bootstrap/testdata/render/with-max-heap-size-bytes.yaml b/internal/xds/bootstrap/testdata/render/with-max-heap-size-bytes.yaml index de27984f32..9b9eb6d8b9 100644 --- a/internal/xds/bootstrap/testdata/render/with-max-heap-size-bytes.yaml +++ b/internal/xds/bootstrap/testdata/render/with-max-heap-size-bytes.yaml @@ -12,7 +12,7 @@ cluster_manager: local_cluster_name: local_cluster node: locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) layered_runtime: layers: - name: global_config @@ -97,7 +97,7 @@ static_resources: load_balancing_weight: 1 load_balancing_weight: 1 locality: - zone: "$(ENVOY_SERVICE_ZONE)" + zone: $(ENVOY_SERVICE_ZONE) name: local_cluster type: STATIC - connect_timeout: 10s diff --git a/internal/xds/translator/accesslog.go b/internal/xds/translator/accesslog.go index ef9ffca1e1..9c584445f7 100644 --- a/internal/xds/translator/accesslog.go +++ b/internal/xds/translator/accesslog.go @@ -478,7 +478,7 @@ func convertToKeyValueList(attributes map[string]string, additionalLabels bool) // TODO: check the provider type and set the appropriate attributes keyValueList.Values = append(keyValueList.Values, &otlpcommonv1.KeyValue{ Key: k8sNamespaceNameKey, - Value: &otlpcommonv1.AnyValue{Value: &otlpcommonv1.AnyValue_StringValue{StringValue: "%ENVIRONMENT(ENVOY_GATEWAY_NAMESPACE)%"}}, + Value: &otlpcommonv1.AnyValue{Value: &otlpcommonv1.AnyValue_StringValue{StringValue: "%ENVIRONMENT(ENVOY_POD_NAMESPACE)%"}}, }) keyValueList.Values = append(keyValueList.Values, &otlpcommonv1.KeyValue{ diff --git a/internal/xds/translator/listener.go b/internal/xds/translator/listener.go index 78c09a7e03..459113e82c 100644 --- a/internal/xds/translator/listener.go +++ b/internal/xds/translator/listener.go @@ -423,7 +423,8 @@ func (t *Translator) addHCMToXDSListener(xdsListener *listenerv3.Listener, irLis config := irListener.TLS.DeepCopy() // If the listener has overlapping TLS config with other listeners, we need to disable HTTP/2 // to avoid the HTTP/2 Connection Coalescing issue (see https://gateway-api.sigs.k8s.io/geps/gep-3567/) - if irListener.TLSOverlaps { + // Note: if ALPN is explicitly set by the user using ClientTrafficPolicy, we keep it as is + if irListener.TLSOverlaps && config.ALPNProtocols == nil { config.ALPNProtocols = []string{"http/1.1"} } tSocket, err = buildXdsDownstreamTLSSocket(config) diff --git a/internal/xds/translator/ratelimit.go b/internal/xds/translator/ratelimit.go index e2d8ff8f77..b791626a09 100644 --- a/internal/xds/translator/ratelimit.go +++ b/internal/xds/translator/ratelimit.go @@ -9,6 +9,7 @@ import ( "bytes" "fmt" "net/url" + "sort" "strconv" "strings" @@ -25,6 +26,7 @@ import ( "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/wrapperspb" goyaml "gopkg.in/yaml.v3" // nolint: depguard + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/utils/ptr" egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" @@ -84,50 +86,33 @@ func (t *Translator) buildRateLimitFilter(irListener *ir.HTTPListener) []*hcmv3. if irListener == nil || irListener.Routes == nil { return nil } - - filters := []*hcmv3.HttpFilter{} - created := make(map[string]bool) - + domains := sets.New[string]() for _, route := range irListener.Routes { if !isValidGlobalRateLimit(route) { continue } - - hasShared, hasNonShared := false, false - var sharedRuleName string - for _, rule := range route.Traffic.RateLimit.Global.Rules { if isRuleShared(rule) { - hasShared = true - sharedRuleName = stripRuleIndexSuffix(rule.Name) - } else { - hasNonShared = true + domains.Insert(stripRuleIndexSuffix(rule.Name)) } } + } + domains.Insert(irListener.Name) - if hasShared { - sharedDomain := sharedRuleName - if !created[sharedDomain] { - filterName := fmt.Sprintf("%s/%s", egv1a1.EnvoyFilterRateLimit.String(), sharedRuleName) - if filter := createRateLimitFilter(t, irListener, sharedDomain, filterName); filter != nil { - filters = append(filters, filter) - } - created[sharedDomain] = true - } - } + // Deterministic order otherwise tests break + domainList := sets.List(domains) + sort.Strings(domainList) - if hasNonShared { - nonSharedDomain := irListener.Name - if !created[nonSharedDomain] { - filterName := egv1a1.EnvoyFilterRateLimit.String() - if filter := createRateLimitFilter(t, irListener, nonSharedDomain, filterName); filter != nil { - filters = append(filters, filter) - } - created[nonSharedDomain] = true - } + var filters []*hcmv3.HttpFilter + for _, domain := range domainList { + filterName := egv1a1.EnvoyFilterRateLimit.String() + if domain != irListener.Name { + filterName += "/" + domain + } + if filter := createRateLimitFilter(t, irListener, domain, filterName); filter != nil { + filters = append(filters, filter) } } - return filters } @@ -450,13 +435,15 @@ func BuildRateLimitServiceConfig(irListeners []*ir.HTTPListener) []*rlsconfv3.Ra continue } - // Process shared rules - add to traffic policy domain - sharedDomain := getDomainSharedName(route) - addRateLimitDescriptor(route, descriptors, sharedDomain, domainDesc, true) - - // Process non-shared rules - add to listener-specific domain - listenerDomain := irListener.Name - addRateLimitDescriptor(route, descriptors, listenerDomain, domainDesc, false) + // For each rule, add to the correct domain only + for rIdx, rule := range route.Traffic.RateLimit.Global.Rules { + descriptor := descriptors[rIdx] + domain := irListener.Name + if isRuleShared(rule) { + domain = stripRuleIndexSuffix(rule.Name) + } + addRateLimitDescriptor(route, rule, descriptor, domain, domainDesc) + } } } @@ -500,7 +487,7 @@ func descriptorsEqual(a, b *rlsconfv3.RateLimitDescriptor) bool { return true } -// addRateLimitDescriptor adds rate limit descriptors to the domain descriptor map. +// addRateLimitDescriptor adds rate limit descriptors from a single rule to the domain descriptor map. // Handles both shared and route-specific rate limits. // // An example of route descriptor looks like this: @@ -513,54 +500,48 @@ func descriptorsEqual(a, b *rlsconfv3.RateLimitDescriptor) bool { // - ... func addRateLimitDescriptor( route *ir.HTTPRoute, - serviceDescriptors []*rlsconfv3.RateLimitDescriptor, + rule *ir.RateLimitRule, + descriptor *rlsconfv3.RateLimitDescriptor, domain string, domainDescriptors map[string][]*rlsconfv3.RateLimitDescriptor, - includeShared bool, ) { - if !isValidGlobalRateLimit(route) || len(serviceDescriptors) == 0 { + if !isValidGlobalRateLimit(route) || descriptor == nil { return } - for i, rule := range route.Traffic.RateLimit.Global.Rules { - if i >= len(serviceDescriptors) || (includeShared != isRuleShared(rule)) { - continue - } - - var descriptorKey string - if isRuleShared(rule) { - descriptorKey = rule.Name - } else { - descriptorKey = getRouteDescriptor(route.Name) - } + var descriptorKey string + if isRuleShared(rule) { + descriptorKey = rule.Name + } else { + descriptorKey = getRouteDescriptor(route.Name) + } - // Find or create descriptor in domainDescriptors[domain] - var descriptorRule *rlsconfv3.RateLimitDescriptor - found := false - for _, d := range domainDescriptors[domain] { - if d.Key == descriptorKey { - descriptorRule = d - found = true - break - } - } - if !found { - descriptorRule = &rlsconfv3.RateLimitDescriptor{Key: descriptorKey, Value: descriptorKey} - domainDescriptors[domain] = append(domainDescriptors[domain], descriptorRule) + // Find or create descriptor in domainDescriptors[domain] + var descriptorRule *rlsconfv3.RateLimitDescriptor + found := false + for _, d := range domainDescriptors[domain] { + if d.Key == descriptorKey { + descriptorRule = d + found = true + break } + } + if !found { + descriptorRule = &rlsconfv3.RateLimitDescriptor{Key: descriptorKey, Value: descriptorKey} + domainDescriptors[domain] = append(domainDescriptors[domain], descriptorRule) + } - // Ensure no duplicate descriptors - alreadyExists := false - for _, existing := range descriptorRule.Descriptors { - if descriptorsEqual(existing, serviceDescriptors[i]) { - alreadyExists = true - break - } - } - if !alreadyExists { - descriptorRule.Descriptors = append(descriptorRule.Descriptors, serviceDescriptors[i]) + // Ensure no duplicate descriptors + alreadyExists := false + for _, existing := range descriptorRule.Descriptors { + if descriptorsEqual(existing, descriptor) { + alreadyExists = true + break } } + if !alreadyExists { + descriptorRule.Descriptors = append(descriptorRule.Descriptors, descriptor) + } } // isSharedRateLimit checks if a route has at least one shared rate limit rule. @@ -591,16 +572,6 @@ func isRuleShared(rule *ir.RateLimitRule) bool { return rule != nil && rule.Shared != nil && *rule.Shared } -// Helper function to check if a specific rule in a route is shared -func isRuleAtIndexShared(route *ir.HTTPRoute, ruleIndex int) bool { - if route == nil || route.Traffic == nil || route.Traffic.RateLimit == nil || - route.Traffic.RateLimit.Global == nil || len(route.Traffic.RateLimit.Global.Rules) <= ruleIndex || ruleIndex < 0 { - return false - } - - return isRuleShared(route.Traffic.RateLimit.Global.Rules[ruleIndex]) -} - // Helper function to map a global rule index to a domain-specific rule index // This ensures that both shared and non-shared rules have indices starting from 0 in their own domains. func getDomainRuleIndex(rules []*ir.RateLimitRule, globalRuleIdx int, ruleIsShared bool) int { @@ -722,19 +693,8 @@ func buildRateLimitServiceDescriptors(route *ir.HTTPRoute) []*rlsconfv3.RateLimi // 3) No Match (apply to all traffic) if !rule.IsMatchSet() { pbDesc := new(rlsconfv3.RateLimitDescriptor) - - // Determine if we should use the shared rate limit key (rule-based) or a generic route key - if isRuleAtIndexShared(route, rIdx) { - // For shared rate limits, use rule name - pbDesc.Key = rule.Name - pbDesc.Value = rule.Name - } else { - // Use generic key for non-shared rate limits, with prefix for uniqueness - descriptorKey := getRouteRuleDescriptor(domainRuleIdx, -1) - pbDesc.Key = descriptorKey - pbDesc.Value = pbDesc.Key - } - + pbDesc.Key = getRouteRuleDescriptor(domainRuleIdx, -1) + pbDesc.Value = getRouteRuleDescriptor(domainRuleIdx, -1) head = pbDesc cur = head } @@ -814,11 +774,6 @@ func (t *Translator) createRateLimitServiceCluster(tCtx *types.ResourceVersionTa }) } -// getDomainSharedName returns the shared domain (stripped policy name), stripRuleIndexSuffix is used to remove the rule index suffix. -func getDomainSharedName(route *ir.HTTPRoute) string { - return stripRuleIndexSuffix(route.Traffic.RateLimit.Global.Rules[0].Name) -} - func getRouteRuleDescriptor(ruleIndex, matchIndex int) string { return "rule-" + strconv.Itoa(ruleIndex) + "-match-" + strconv.Itoa(matchIndex) } diff --git a/internal/xds/translator/testdata/in/xds-ir/http-route-with-tlsbundle.yaml b/internal/xds/translator/testdata/in/xds-ir/http-route-with-tlsbundle.yaml index 5eff08a35f..b0a453e792 100644 --- a/internal/xds/translator/testdata/in/xds-ir/http-route-with-tlsbundle.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/http-route-with-tlsbundle.yaml @@ -26,6 +26,9 @@ http: certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K name: policy-btls/policies-ca SNI: example.com + subjectAltNames: + - uri: spiffe://cluster.local/ns/istio-demo/sa/echo-v1 + - hostname: subdomain.secondexample.com weight: 1 hostname: '*' name: httproute/envoy-gateway/httproute-btls/rule/0/match/0/* diff --git a/internal/xds/translator/testdata/in/xds-ir/listener-overlapping-tls-config.yaml b/internal/xds/translator/testdata/in/xds-ir/listener-overlapping-tls-config.yaml index 7baf96ccd2..8fe100c3c4 100644 --- a/internal/xds/translator/testdata/in/xds-ir/listener-overlapping-tls-config.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/listener-overlapping-tls-config.yaml @@ -38,7 +38,7 @@ http: tls: alpnProtocols: null certificates: - - name: envoy-gateway/tls-secret-example-com + - name: envoy-gateway/tls-secret-foo-example-com privateKey: '[redacted]' serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMyRENDQWNBQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5UQTBNakV3T1RFd05ETmFGdzB6TlRBMApNVGt3T1RFd05ETmFNRGN4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHhIVEFiQmdOVkJBb01GR1Y0CllXMXdiR1VnYjNKbllXNXBlbUYwYVc5dU1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0MKQVFFQXY0anl4TUh1YzQzMHdvWkk4M1JSMXVxU2gvbm9MVWVPdDZnMkNKaFVFYXNaeUNOMzN3bFRRRDE0SEhkSwpOb1k4SThWd1pOZFZCNGpjRzlnb3dDVmVQY3lqRzZPaGl1aUZNWnU2NzV6dWZEWnRlRTNEY3lTbFgrY2lSbVZZCkNuSmk3QkV3NlJMUUJ0bVV6WGxtYmRpVXE5djJwalVBL2R3ZnRLRHRZTHFrVytvTSt5MWg3cjRJV0JVK2RVcU0KcGtTem5VSCtKN1JoRkFsdytmRWlVSFRLemlCMkVtdjc3Mi91bS96NHdMWnJIeWNGbmc4L1FCM0JIUktXVTV4eQp3bWNTQ2xrVlMvWWNpMFVXcnR2eGhwck9wTUhQUGR2QkZ2M2NaWGNpUUJjb0ZNcGxsQzV0UURvdWJ0dEV1d3JpCi8rVktKWkUrSVl4ei9YeUd3Y3dJRnIzWG13SURBUUFCTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFBU3VLaE8KcGtwL1VSclphbEU0OUlnc0xkN3hSTlBhREVkQ1RWZ3Qvc3praUhnSDB1NDBVaVV6KzVzaDRpdlJOazRqTm1zRwprb3FwQlBVS3pvVmtrSTcxUWQ4bHh1VzF2dkxZMXVvM0RIS2svdDFpUWVZWWpERlk3YzUxVG1BT015WUdKTlhxCi9EbW84UWgzaFB1RnI3a29kUjBLSkJyc0RsMEhoWVBjUnpWOW1sQ2lrU1B4THJGTUNwZGx0QUw2UEprSVpucUgKc1g5dEtVZk1uYW5jMkpHZTZVTDE1ODBEV2xQTUcrMU1qRElCVXdxWWYzaWNKb0NYclAwbzNmckRKcTE2VnpidApkalRtVGswakx1bGkvQ2JCZzh4dWp4emo4bmRPcVNkd05kd091OWoxSmZ2Q0I1RjZ4S0VTenowOVo5TzlOZUM5CjMrd1pLTlRSOXVEdDRKNksKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= tlsOverlaps: true @@ -85,3 +85,47 @@ http: privateKey: '[redacted]' serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMyRENDQWNBQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5UQTBNakV3T1RFd05ETmFGdzB6TlRBMApNVGt3T1RFd05ETmFNRGN4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHhIVEFiQmdOVkJBb01GR1Y0CllXMXdiR1VnYjNKbllXNXBlbUYwYVc5dU1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0MKQVFFQXY0anl4TUh1YzQzMHdvWkk4M1JSMXVxU2gvbm9MVWVPdDZnMkNKaFVFYXNaeUNOMzN3bFRRRDE0SEhkSwpOb1k4SThWd1pOZFZCNGpjRzlnb3dDVmVQY3lqRzZPaGl1aUZNWnU2NzV6dWZEWnRlRTNEY3lTbFgrY2lSbVZZCkNuSmk3QkV3NlJMUUJ0bVV6WGxtYmRpVXE5djJwalVBL2R3ZnRLRHRZTHFrVytvTSt5MWg3cjRJV0JVK2RVcU0KcGtTem5VSCtKN1JoRkFsdytmRWlVSFRLemlCMkVtdjc3Mi91bS96NHdMWnJIeWNGbmc4L1FCM0JIUktXVTV4eQp3bWNTQ2xrVlMvWWNpMFVXcnR2eGhwck9wTUhQUGR2QkZ2M2NaWGNpUUJjb0ZNcGxsQzV0UURvdWJ0dEV1d3JpCi8rVktKWkUrSVl4ei9YeUd3Y3dJRnIzWG13SURBUUFCTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFBU3VLaE8KcGtwL1VSclphbEU0OUlnc0xkN3hSTlBhREVkQ1RWZ3Qvc3praUhnSDB1NDBVaVV6KzVzaDRpdlJOazRqTm1zRwprb3FwQlBVS3pvVmtrSTcxUWQ4bHh1VzF2dkxZMXVvM0RIS2svdDFpUWVZWWpERlk3YzUxVG1BT015WUdKTlhxCi9EbW84UWgzaFB1RnI3a29kUjBLSkJyc0RsMEhoWVBjUnpWOW1sQ2lrU1B4THJGTUNwZGx0QUw2UEprSVpucUgKc1g5dEtVZk1uYW5jMkpHZTZVTDE1ODBEV2xQTUcrMU1qRElCVXdxWWYzaWNKb0NYclAwbzNmckRKcTE2VnpidApkalRtVGswakx1bGkvQ2JCZzh4dWp4emo4bmRPcVNkd05kd091OWoxSmZ2Q0I1RjZ4S0VTenowOVo5TzlOZUM5CjMrd1pLTlRSOXVEdDRKNksKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= tlsOverlaps: true +- address: 0.0.0.0 # this listener should keep the ALPN because it's explictily set + hostnames: + - bar.example.com + isHTTP2: false + metadata: + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: https-1 + name: envoy-gateway/gateway-1/https-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 8443 + routes: + - destination: + name: httproute/envoy-gateway/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + name: httproute/envoy-gateway/httproute-1/rule/0/backend/0 + protocol: HTTP + weight: 1 + hostname: foo.example.com + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: envoy-gateway + name: httproute/envoy-gateway/httproute-1/rule/0/match/0/foo_example_com + pathMatch: + distinct: false + name: "" + prefix: / + tls: + alpnProtocols: + - h2 + certificates: + - name: envoy-gateway/tls-secret-bar-example-com + privateKey: '[redacted]' + serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMyRENDQWNBQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5UQTBNakV3T1RFd05ETmFGdzB6TlRBMApNVGt3T1RFd05ETmFNRGN4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHhIVEFiQmdOVkJBb01GR1Y0CllXMXdiR1VnYjNKbllXNXBlbUYwYVc5dU1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0MKQVFFQXY0anl4TUh1YzQzMHdvWkk4M1JSMXVxU2gvbm9MVWVPdDZnMkNKaFVFYXNaeUNOMzN3bFRRRDE0SEhkSwpOb1k4SThWd1pOZFZCNGpjRzlnb3dDVmVQY3lqRzZPaGl1aUZNWnU2NzV6dWZEWnRlRTNEY3lTbFgrY2lSbVZZCkNuSmk3QkV3NlJMUUJ0bVV6WGxtYmRpVXE5djJwalVBL2R3ZnRLRHRZTHFrVytvTSt5MWg3cjRJV0JVK2RVcU0KcGtTem5VSCtKN1JoRkFsdytmRWlVSFRLemlCMkVtdjc3Mi91bS96NHdMWnJIeWNGbmc4L1FCM0JIUktXVTV4eQp3bWNTQ2xrVlMvWWNpMFVXcnR2eGhwck9wTUhQUGR2QkZ2M2NaWGNpUUJjb0ZNcGxsQzV0UURvdWJ0dEV1d3JpCi8rVktKWkUrSVl4ei9YeUd3Y3dJRnIzWG13SURBUUFCTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFBU3VLaE8KcGtwL1VSclphbEU0OUlnc0xkN3hSTlBhREVkQ1RWZ3Qvc3praUhnSDB1NDBVaVV6KzVzaDRpdlJOazRqTm1zRwprb3FwQlBVS3pvVmtrSTcxUWQ4bHh1VzF2dkxZMXVvM0RIS2svdDFpUWVZWWpERlk3YzUxVG1BT015WUdKTlhxCi9EbW84UWgzaFB1RnI3a29kUjBLSkJyc0RsMEhoWVBjUnpWOW1sQ2lrU1B4THJGTUNwZGx0QUw2UEprSVpucUgKc1g5dEtVZk1uYW5jMkpHZTZVTDE1ODBEV2xQTUcrMU1qRElCVXdxWWYzaWNKb0NYclAwbzNmckRKcTE2VnpidApkalRtVGswakx1bGkvQ2JCZzh4dWp4emo4bmRPcVNkd05kd091OWoxSmZ2Q0I1RjZ4S0VTenowOVo5TzlOZUM5CjMrd1pLTlRSOXVEdDRKNksKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + tlsOverlaps: true diff --git a/internal/xds/translator/testdata/in/xds-ir/tcp-route-with-no-routes.yaml b/internal/xds/translator/testdata/in/xds-ir/tcp-route-with-no-routes.yaml new file mode 100644 index 0000000000..dafca1cf20 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/tcp-route-with-no-routes.yaml @@ -0,0 +1,4 @@ +tcp: +- name: "tcp-listener-with-no-routes" + address: "::" + port: 10080 diff --git a/internal/xds/translator/testdata/in/xds-ir/udp-route-with-no-routes.yaml b/internal/xds/translator/testdata/in/xds-ir/udp-route-with-no-routes.yaml new file mode 100644 index 0000000000..fc6a647cba --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/udp-route-with-no-routes.yaml @@ -0,0 +1,4 @@ +udp: +- name: "udp-route-with-no-routes" + address: "::" + port: 10080 diff --git a/internal/xds/translator/testdata/out/xds-ir/accesslog-cel.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/accesslog-cel.listeners.yaml index 82af12d133..6739031b0f 100644 --- a/internal/xds/translator/testdata/out/xds-ir/accesslog-cel.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/accesslog-cel.listeners.yaml @@ -58,7 +58,7 @@ values: - key: k8s.namespace.name value: - stringValue: '%ENVIRONMENT(ENVOY_GATEWAY_NAMESPACE)%' + stringValue: '%ENVIRONMENT(ENVOY_POD_NAMESPACE)%' - key: k8s.pod.name value: stringValue: '%ENVIRONMENT(ENVOY_POD_NAME)%' @@ -134,7 +134,7 @@ values: - key: k8s.namespace.name value: - stringValue: '%ENVIRONMENT(ENVOY_GATEWAY_NAMESPACE)%' + stringValue: '%ENVIRONMENT(ENVOY_POD_NAMESPACE)%' - key: k8s.pod.name value: stringValue: '%ENVIRONMENT(ENVOY_POD_NAME)%' diff --git a/internal/xds/translator/testdata/out/xds-ir/accesslog-endpoint-stats.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/accesslog-endpoint-stats.listeners.yaml index ac530c829e..e2ee899af5 100644 --- a/internal/xds/translator/testdata/out/xds-ir/accesslog-endpoint-stats.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/accesslog-endpoint-stats.listeners.yaml @@ -37,7 +37,7 @@ values: - key: k8s.namespace.name value: - stringValue: '%ENVIRONMENT(ENVOY_GATEWAY_NAMESPACE)%' + stringValue: '%ENVIRONMENT(ENVOY_POD_NAMESPACE)%' - key: k8s.pod.name value: stringValue: '%ENVIRONMENT(ENVOY_POD_NAME)%' @@ -95,7 +95,7 @@ values: - key: k8s.namespace.name value: - stringValue: '%ENVIRONMENT(ENVOY_GATEWAY_NAMESPACE)%' + stringValue: '%ENVIRONMENT(ENVOY_POD_NAMESPACE)%' - key: k8s.pod.name value: stringValue: '%ENVIRONMENT(ENVOY_POD_NAME)%' diff --git a/internal/xds/translator/testdata/out/xds-ir/accesslog-formatters.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/accesslog-formatters.listeners.yaml index 7e51cbeb1d..6e500f3c5e 100644 --- a/internal/xds/translator/testdata/out/xds-ir/accesslog-formatters.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/accesslog-formatters.listeners.yaml @@ -57,7 +57,7 @@ values: - key: k8s.namespace.name value: - stringValue: '%ENVIRONMENT(ENVOY_GATEWAY_NAMESPACE)%' + stringValue: '%ENVIRONMENT(ENVOY_POD_NAMESPACE)%' - key: k8s.pod.name value: stringValue: '%ENVIRONMENT(ENVOY_POD_NAME)%' @@ -141,7 +141,7 @@ values: - key: k8s.namespace.name value: - stringValue: '%ENVIRONMENT(ENVOY_GATEWAY_NAMESPACE)%' + stringValue: '%ENVIRONMENT(ENVOY_POD_NAMESPACE)%' - key: k8s.pod.name value: stringValue: '%ENVIRONMENT(ENVOY_POD_NAME)%' diff --git a/internal/xds/translator/testdata/out/xds-ir/accesslog-multi-cel.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/accesslog-multi-cel.listeners.yaml index f1efd67797..43694629e0 100644 --- a/internal/xds/translator/testdata/out/xds-ir/accesslog-multi-cel.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/accesslog-multi-cel.listeners.yaml @@ -73,7 +73,7 @@ values: - key: k8s.namespace.name value: - stringValue: '%ENVIRONMENT(ENVOY_GATEWAY_NAMESPACE)%' + stringValue: '%ENVIRONMENT(ENVOY_POD_NAMESPACE)%' - key: k8s.pod.name value: stringValue: '%ENVIRONMENT(ENVOY_POD_NAME)%' @@ -170,7 +170,7 @@ values: - key: k8s.namespace.name value: - stringValue: '%ENVIRONMENT(ENVOY_GATEWAY_NAMESPACE)%' + stringValue: '%ENVIRONMENT(ENVOY_POD_NAMESPACE)%' - key: k8s.pod.name value: stringValue: '%ENVIRONMENT(ENVOY_POD_NAME)%' diff --git a/internal/xds/translator/testdata/out/xds-ir/accesslog-types.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/accesslog-types.listeners.yaml index 9b89cf5c79..3a120ea85e 100644 --- a/internal/xds/translator/testdata/out/xds-ir/accesslog-types.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/accesslog-types.listeners.yaml @@ -116,7 +116,7 @@ values: - key: k8s.namespace.name value: - stringValue: '%ENVIRONMENT(ENVOY_GATEWAY_NAMESPACE)%' + stringValue: '%ENVIRONMENT(ENVOY_POD_NAMESPACE)%' - key: k8s.pod.name value: stringValue: '%ENVIRONMENT(ENVOY_POD_NAME)%' @@ -146,7 +146,7 @@ values: - key: k8s.namespace.name value: - stringValue: '%ENVIRONMENT(ENVOY_GATEWAY_NAMESPACE)%' + stringValue: '%ENVIRONMENT(ENVOY_POD_NAMESPACE)%' - key: k8s.pod.name value: stringValue: '%ENVIRONMENT(ENVOY_POD_NAME)%' @@ -276,7 +276,7 @@ values: - key: k8s.namespace.name value: - stringValue: '%ENVIRONMENT(ENVOY_GATEWAY_NAMESPACE)%' + stringValue: '%ENVIRONMENT(ENVOY_POD_NAMESPACE)%' - key: k8s.pod.name value: stringValue: '%ENVIRONMENT(ENVOY_POD_NAME)%' @@ -302,7 +302,7 @@ values: - key: k8s.namespace.name value: - stringValue: '%ENVIRONMENT(ENVOY_GATEWAY_NAMESPACE)%' + stringValue: '%ENVIRONMENT(ENVOY_POD_NAMESPACE)%' - key: k8s.pod.name value: stringValue: '%ENVIRONMENT(ENVOY_POD_NAME)%' diff --git a/internal/xds/translator/testdata/out/xds-ir/accesslog-with-format.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/accesslog-with-format.listeners.yaml index 20adb39d58..82d7bc9277 100644 --- a/internal/xds/translator/testdata/out/xds-ir/accesslog-with-format.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/accesslog-with-format.listeners.yaml @@ -56,7 +56,7 @@ values: - key: k8s.namespace.name value: - stringValue: '%ENVIRONMENT(ENVOY_GATEWAY_NAMESPACE)%' + stringValue: '%ENVIRONMENT(ENVOY_POD_NAMESPACE)%' - key: k8s.pod.name value: stringValue: '%ENVIRONMENT(ENVOY_POD_NAME)%' @@ -129,7 +129,7 @@ values: - key: k8s.namespace.name value: - stringValue: '%ENVIRONMENT(ENVOY_GATEWAY_NAMESPACE)%' + stringValue: '%ENVIRONMENT(ENVOY_POD_NAMESPACE)%' - key: k8s.pod.name value: stringValue: '%ENVIRONMENT(ENVOY_POD_NAME)%' diff --git a/internal/xds/translator/testdata/out/xds-ir/accesslog.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/accesslog.listeners.yaml index 71f4affea9..edd3542f3d 100644 --- a/internal/xds/translator/testdata/out/xds-ir/accesslog.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/accesslog.listeners.yaml @@ -56,7 +56,7 @@ values: - key: k8s.namespace.name value: - stringValue: '%ENVIRONMENT(ENVOY_GATEWAY_NAMESPACE)%' + stringValue: '%ENVIRONMENT(ENVOY_POD_NAMESPACE)%' - key: k8s.pod.name value: stringValue: '%ENVIRONMENT(ENVOY_POD_NAME)%' @@ -129,7 +129,7 @@ values: - key: k8s.namespace.name value: - stringValue: '%ENVIRONMENT(ENVOY_GATEWAY_NAMESPACE)%' + stringValue: '%ENVIRONMENT(ENVOY_POD_NAMESPACE)%' - key: k8s.pod.name value: stringValue: '%ENVIRONMENT(ENVOY_POD_NAME)%' diff --git a/internal/xds/translator/testdata/out/xds-ir/dns-lookup-family.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/dns-lookup-family.listeners.yaml index cb9e097946..89e04f85a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/dns-lookup-family.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/dns-lookup-family.listeners.yaml @@ -58,7 +58,7 @@ values: - key: k8s.namespace.name value: - stringValue: '%ENVIRONMENT(ENVOY_GATEWAY_NAMESPACE)%' + stringValue: '%ENVIRONMENT(ENVOY_POD_NAMESPACE)%' - key: k8s.pod.name value: stringValue: '%ENVIRONMENT(ENVOY_POD_NAME)%' @@ -101,7 +101,7 @@ values: - key: k8s.namespace.name value: - stringValue: '%ENVIRONMENT(ENVOY_GATEWAY_NAMESPACE)%' + stringValue: '%ENVIRONMENT(ENVOY_POD_NAMESPACE)%' - key: k8s.pod.name value: stringValue: '%ENVIRONMENT(ENVOY_POD_NAME)%' diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-with-tlsbundle.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-with-tlsbundle.clusters.yaml index 0ba4829c93..991b3dbbaa 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-with-tlsbundle.clusters.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-with-tlsbundle.clusters.yaml @@ -29,6 +29,12 @@ - matcher: exact: example.com sanType: DNS + - matcher: + exact: spiffe://cluster.local/ns/istio-demo/sa/echo-v1 + sanType: URI + - matcher: + exact: subdomain.secondexample.com + sanType: DNS validationContextSdsSecretConfig: name: policy-btls/policies-ca sdsConfig: diff --git a/internal/xds/translator/testdata/out/xds-ir/listener-overlapping-tls-config.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/listener-overlapping-tls-config.listeners.yaml index 5fa916377e..6dbba2fc28 100644 --- a/internal/xds/translator/testdata/out/xds-ir/listener-overlapping-tls-config.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/listener-overlapping-tls-config.listeners.yaml @@ -41,7 +41,7 @@ alpnProtocols: - http/1.1 tlsCertificateSdsSecretConfigs: - - name: envoy-gateway/tls-secret-example-com + - name: envoy-gateway/tls-secret-foo-example-com sdsConfig: ads: {} resourceApiVersion: V3 @@ -97,3 +97,58 @@ '@type': type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector name: envoy-gateway/gateway-1/https-1 perConnectionBufferLimitBytes: 32768 +- address: + socketAddress: + address: 0.0.0.0 + portValue: 8443 + filterChains: + - filterChainMatch: + serverNames: + - bar.example.com + filters: + - name: envoy.filters.network.http_connection_manager + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + commonHttpProtocolOptions: + headersWithUnderscoresAction: REJECT_REQUEST + http2ProtocolOptions: + initialConnectionWindowSize: 1048576 + initialStreamWindowSize: 65536 + maxConcurrentStreams: 100 + httpFilters: + - name: envoy.filters.http.router + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + suppressEnvoyHeaders: true + mergeSlashes: true + normalizePath: true + pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: envoy-gateway/gateway-1/https-1 + serverHeaderTransformation: PASS_THROUGH + statPrefix: https-8443 + useRemoteAddress: true + name: envoy-gateway/gateway-1/https-1 + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + commonTlsContext: + alpnProtocols: + - h2 + tlsCertificateSdsSecretConfigs: + - name: envoy-gateway/tls-secret-bar-example-com + sdsConfig: + ads: {} + resourceApiVersion: V3 + disableStatefulSessionResumption: true + disableStatelessSessionResumption: true + listenerFilters: + - name: envoy.filters.listener.tls_inspector + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector + name: envoy-gateway/gateway-1/https-1 + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/listener-overlapping-tls-config.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/listener-overlapping-tls-config.routes.yaml index 3e4ce3d3f4..181066a5d0 100644 --- a/internal/xds/translator/testdata/out/xds-ir/listener-overlapping-tls-config.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/listener-overlapping-tls-config.routes.yaml @@ -56,3 +56,32 @@ cluster: httproute/envoy-gateway/httproute-1/rule/0 upgradeConfigs: - upgradeType: websocket +- ignorePortInHostMatching: true + name: envoy-gateway/gateway-1/https-1 + virtualHosts: + - domains: + - foo.example.com + metadata: + filterMetadata: + envoy-gateway: + resources: + - kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: https-1 + name: envoy-gateway/gateway-1/https-1/foo_example_com + routes: + - match: + prefix: / + metadata: + filterMetadata: + envoy-gateway: + resources: + - kind: HTTPRoute + name: httproute-1 + namespace: envoy-gateway + name: httproute/envoy-gateway/httproute-1/rule/0/match/0/foo_example_com + route: + cluster: httproute/envoy-gateway/httproute-1/rule/0 + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/listener-overlapping-tls-config.secrets.yaml b/internal/xds/translator/testdata/out/xds-ir/listener-overlapping-tls-config.secrets.yaml index 5a622cfd20..1527953136 100644 --- a/internal/xds/translator/testdata/out/xds-ir/listener-overlapping-tls-config.secrets.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/listener-overlapping-tls-config.secrets.yaml @@ -1,4 +1,4 @@ -- name: envoy-gateway/tls-secret-example-com +- name: envoy-gateway/tls-secret-foo-example-com tlsCertificate: certificateChain: inlineBytes: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMyRENDQWNBQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5UQTBNakV3T1RFd05ETmFGdzB6TlRBMApNVGt3T1RFd05ETmFNRGN4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHhIVEFiQmdOVkJBb01GR1Y0CllXMXdiR1VnYjNKbllXNXBlbUYwYVc5dU1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0MKQVFFQXY0anl4TUh1YzQzMHdvWkk4M1JSMXVxU2gvbm9MVWVPdDZnMkNKaFVFYXNaeUNOMzN3bFRRRDE0SEhkSwpOb1k4SThWd1pOZFZCNGpjRzlnb3dDVmVQY3lqRzZPaGl1aUZNWnU2NzV6dWZEWnRlRTNEY3lTbFgrY2lSbVZZCkNuSmk3QkV3NlJMUUJ0bVV6WGxtYmRpVXE5djJwalVBL2R3ZnRLRHRZTHFrVytvTSt5MWg3cjRJV0JVK2RVcU0KcGtTem5VSCtKN1JoRkFsdytmRWlVSFRLemlCMkVtdjc3Mi91bS96NHdMWnJIeWNGbmc4L1FCM0JIUktXVTV4eQp3bWNTQ2xrVlMvWWNpMFVXcnR2eGhwck9wTUhQUGR2QkZ2M2NaWGNpUUJjb0ZNcGxsQzV0UURvdWJ0dEV1d3JpCi8rVktKWkUrSVl4ei9YeUd3Y3dJRnIzWG13SURBUUFCTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFBU3VLaE8KcGtwL1VSclphbEU0OUlnc0xkN3hSTlBhREVkQ1RWZ3Qvc3praUhnSDB1NDBVaVV6KzVzaDRpdlJOazRqTm1zRwprb3FwQlBVS3pvVmtrSTcxUWQ4bHh1VzF2dkxZMXVvM0RIS2svdDFpUWVZWWpERlk3YzUxVG1BT015WUdKTlhxCi9EbW84UWgzaFB1RnI3a29kUjBLSkJyc0RsMEhoWVBjUnpWOW1sQ2lrU1B4THJGTUNwZGx0QUw2UEprSVpucUgKc1g5dEtVZk1uYW5jMkpHZTZVTDE1ODBEV2xQTUcrMU1qRElCVXdxWWYzaWNKb0NYclAwbzNmckRKcTE2VnpidApkalRtVGswakx1bGkvQ2JCZzh4dWp4emo4bmRPcVNkd05kd091OWoxSmZ2Q0I1RjZ4S0VTenowOVo5TzlOZUM5CjMrd1pLTlRSOXVEdDRKNksKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= @@ -10,3 +10,9 @@ inlineBytes: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMyRENDQWNBQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5UQTBNakV3T1RFd05ETmFGdzB6TlRBMApNVGt3T1RFd05ETmFNRGN4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHhIVEFiQmdOVkJBb01GR1Y0CllXMXdiR1VnYjNKbllXNXBlbUYwYVc5dU1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0MKQVFFQXY0anl4TUh1YzQzMHdvWkk4M1JSMXVxU2gvbm9MVWVPdDZnMkNKaFVFYXNaeUNOMzN3bFRRRDE0SEhkSwpOb1k4SThWd1pOZFZCNGpjRzlnb3dDVmVQY3lqRzZPaGl1aUZNWnU2NzV6dWZEWnRlRTNEY3lTbFgrY2lSbVZZCkNuSmk3QkV3NlJMUUJ0bVV6WGxtYmRpVXE5djJwalVBL2R3ZnRLRHRZTHFrVytvTSt5MWg3cjRJV0JVK2RVcU0KcGtTem5VSCtKN1JoRkFsdytmRWlVSFRLemlCMkVtdjc3Mi91bS96NHdMWnJIeWNGbmc4L1FCM0JIUktXVTV4eQp3bWNTQ2xrVlMvWWNpMFVXcnR2eGhwck9wTUhQUGR2QkZ2M2NaWGNpUUJjb0ZNcGxsQzV0UURvdWJ0dEV1d3JpCi8rVktKWkUrSVl4ei9YeUd3Y3dJRnIzWG13SURBUUFCTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFBU3VLaE8KcGtwL1VSclphbEU0OUlnc0xkN3hSTlBhREVkQ1RWZ3Qvc3praUhnSDB1NDBVaVV6KzVzaDRpdlJOazRqTm1zRwprb3FwQlBVS3pvVmtrSTcxUWQ4bHh1VzF2dkxZMXVvM0RIS2svdDFpUWVZWWpERlk3YzUxVG1BT015WUdKTlhxCi9EbW84UWgzaFB1RnI3a29kUjBLSkJyc0RsMEhoWVBjUnpWOW1sQ2lrU1B4THJGTUNwZGx0QUw2UEprSVpucUgKc1g5dEtVZk1uYW5jMkpHZTZVTDE1ODBEV2xQTUcrMU1qRElCVXdxWWYzaWNKb0NYclAwbzNmckRKcTE2VnpidApkalRtVGswakx1bGkvQ2JCZzh4dWp4emo4bmRPcVNkd05kd091OWoxSmZ2Q0I1RjZ4S0VTenowOVo5TzlOZUM5CjMrd1pLTlRSOXVEdDRKNksKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= privateKey: inlineBytes: W3JlZGFjdGVkXQ== +- name: envoy-gateway/tls-secret-bar-example-com + tlsCertificate: + certificateChain: + inlineBytes: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMyRENDQWNBQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5UQTBNakV3T1RFd05ETmFGdzB6TlRBMApNVGt3T1RFd05ETmFNRGN4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHhIVEFiQmdOVkJBb01GR1Y0CllXMXdiR1VnYjNKbllXNXBlbUYwYVc5dU1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0MKQVFFQXY0anl4TUh1YzQzMHdvWkk4M1JSMXVxU2gvbm9MVWVPdDZnMkNKaFVFYXNaeUNOMzN3bFRRRDE0SEhkSwpOb1k4SThWd1pOZFZCNGpjRzlnb3dDVmVQY3lqRzZPaGl1aUZNWnU2NzV6dWZEWnRlRTNEY3lTbFgrY2lSbVZZCkNuSmk3QkV3NlJMUUJ0bVV6WGxtYmRpVXE5djJwalVBL2R3ZnRLRHRZTHFrVytvTSt5MWg3cjRJV0JVK2RVcU0KcGtTem5VSCtKN1JoRkFsdytmRWlVSFRLemlCMkVtdjc3Mi91bS96NHdMWnJIeWNGbmc4L1FCM0JIUktXVTV4eQp3bWNTQ2xrVlMvWWNpMFVXcnR2eGhwck9wTUhQUGR2QkZ2M2NaWGNpUUJjb0ZNcGxsQzV0UURvdWJ0dEV1d3JpCi8rVktKWkUrSVl4ei9YeUd3Y3dJRnIzWG13SURBUUFCTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFBU3VLaE8KcGtwL1VSclphbEU0OUlnc0xkN3hSTlBhREVkQ1RWZ3Qvc3praUhnSDB1NDBVaVV6KzVzaDRpdlJOazRqTm1zRwprb3FwQlBVS3pvVmtrSTcxUWQ4bHh1VzF2dkxZMXVvM0RIS2svdDFpUWVZWWpERlk3YzUxVG1BT015WUdKTlhxCi9EbW84UWgzaFB1RnI3a29kUjBLSkJyc0RsMEhoWVBjUnpWOW1sQ2lrU1B4THJGTUNwZGx0QUw2UEprSVpucUgKc1g5dEtVZk1uYW5jMkpHZTZVTDE1ODBEV2xQTUcrMU1qRElCVXdxWWYzaWNKb0NYclAwbzNmckRKcTE2VnpidApkalRtVGswakx1bGkvQ2JCZzh4dWp4emo4bmRPcVNkd05kd091OWoxSmZ2Q0I1RjZ4S0VTenowOVo5TzlOZUM5CjMrd1pLTlRSOXVEdDRKNksKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + privateKey: + inlineBytes: W3JlZGFjdGVkXQ== diff --git a/internal/xds/translator/testdata/out/xds-ir/ratelimit-global-shared.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/ratelimit-global-shared.listeners.yaml index fd03d88dca..fd3c8f9467 100644 --- a/internal/xds/translator/testdata/out/xds-ir/ratelimit-global-shared.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/ratelimit-global-shared.listeners.yaml @@ -14,30 +14,30 @@ initialStreamWindowSize: 65536 maxConcurrentStreams: 100 httpFilters: - - name: envoy.filters.http.ratelimit/test-namespace/test-policy-1 + - name: envoy.filters.http.ratelimit typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit - domain: test-namespace/test-policy-1 + domain: first-listener enableXRatelimitHeaders: DRAFT_VERSION_03 rateLimitService: grpcService: envoyGrpc: clusterName: ratelimit_cluster transportApiVersion: V3 - - name: envoy.filters.http.ratelimit/test-namespace/test-policy-2 + - name: envoy.filters.http.ratelimit/test-namespace/test-policy-1 typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit - domain: test-namespace/test-policy-2 + domain: test-namespace/test-policy-1 enableXRatelimitHeaders: DRAFT_VERSION_03 rateLimitService: grpcService: envoyGrpc: clusterName: ratelimit_cluster transportApiVersion: V3 - - name: envoy.filters.http.ratelimit + - name: envoy.filters.http.ratelimit/test-namespace/test-policy-2 typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit - domain: first-listener + domain: test-namespace/test-policy-2 enableXRatelimitHeaders: DRAFT_VERSION_03 rateLimitService: grpcService: diff --git a/internal/xds/translator/testdata/out/xds-ir/ratelimit-multi-global-shared.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/ratelimit-multi-global-shared.listeners.yaml index 0e76130891..fd3c8f9467 100644 --- a/internal/xds/translator/testdata/out/xds-ir/ratelimit-multi-global-shared.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/ratelimit-multi-global-shared.listeners.yaml @@ -14,6 +14,16 @@ initialStreamWindowSize: 65536 maxConcurrentStreams: 100 httpFilters: + - name: envoy.filters.http.ratelimit + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit + domain: first-listener + enableXRatelimitHeaders: DRAFT_VERSION_03 + rateLimitService: + grpcService: + envoyGrpc: + clusterName: ratelimit_cluster + transportApiVersion: V3 - name: envoy.filters.http.ratelimit/test-namespace/test-policy-1 typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit diff --git a/internal/xds/translator/testdata/out/xds-ir/tcp-route-with-no-routes.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/tcp-route-with-no-routes.clusters.yaml new file mode 100644 index 0000000000..0764d46f0e --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/tcp-route-with-no-routes.clusters.yaml @@ -0,0 +1,2 @@ +- name: EmptyCluster + type: STATIC diff --git a/internal/xds/translator/testdata/out/xds-ir/tcp-route-with-no-routes.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/tcp-route-with-no-routes.endpoints.yaml new file mode 100644 index 0000000000..fe51488c70 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/tcp-route-with-no-routes.endpoints.yaml @@ -0,0 +1 @@ +[] diff --git a/internal/xds/translator/testdata/out/xds-ir/tcp-route-with-no-routes.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/tcp-route-with-no-routes.listeners.yaml new file mode 100644 index 0000000000..4250f0a6b5 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/tcp-route-with-no-routes.listeners.yaml @@ -0,0 +1,14 @@ +- address: + socketAddress: + address: '::' + portValue: 10080 + filterChains: + - filters: + - name: envoy.filters.network.tcp_proxy + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy + cluster: EmptyCluster + statPrefix: tcp-10080 + name: EmptyCluster + name: tcp-listener-with-no-routes + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/tcp-route-with-no-routes.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/tcp-route-with-no-routes.routes.yaml new file mode 100644 index 0000000000..fe51488c70 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/tcp-route-with-no-routes.routes.yaml @@ -0,0 +1 @@ +[] diff --git a/internal/xds/translator/testdata/out/xds-ir/udp-route-with-no-routes.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/udp-route-with-no-routes.clusters.yaml new file mode 100644 index 0000000000..0764d46f0e --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/udp-route-with-no-routes.clusters.yaml @@ -0,0 +1,2 @@ +- name: EmptyCluster + type: STATIC diff --git a/internal/xds/translator/testdata/out/xds-ir/udp-route-with-no-routes.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/udp-route-with-no-routes.endpoints.yaml new file mode 100644 index 0000000000..fe51488c70 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/udp-route-with-no-routes.endpoints.yaml @@ -0,0 +1 @@ +[] diff --git a/internal/xds/translator/testdata/out/xds-ir/udp-route-with-no-routes.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/udp-route-with-no-routes.listeners.yaml new file mode 100644 index 0000000000..ce76497d0c --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/udp-route-with-no-routes.listeners.yaml @@ -0,0 +1,18 @@ +- address: + socketAddress: + address: '::' + portValue: 10080 + protocol: UDP + listenerFilters: + - name: envoy.filters.udp_listener.udp_proxy + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.udp.udp_proxy.v3.UdpProxyConfig + matcher: + onNoMatch: + action: + name: route + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.udp.udp_proxy.v3.Route + cluster: EmptyCluster + statPrefix: service + name: udp-route-with-no-routes diff --git a/internal/xds/translator/testdata/out/xds-ir/udp-route-with-no-routes.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/udp-route-with-no-routes.routes.yaml new file mode 100644 index 0000000000..fe51488c70 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/udp-route-with-no-routes.routes.yaml @@ -0,0 +1 @@ +[] diff --git a/internal/xds/translator/translator.go b/internal/xds/translator/translator.go index 5118ffd329..439288409e 100644 --- a/internal/xds/translator/translator.go +++ b/internal/xds/translator/translator.go @@ -38,10 +38,16 @@ import ( const ( AuthorityHeaderKey = ":authority" - // The dummy cluster for TCP listeners that have no routes + // The dummy cluster name for TCP/UDP listeners that have no routes emptyClusterName = "EmptyCluster" ) +// The dummy cluster for TCP/UDP listeners that have no routes +var emptyRouteCluster = &clusterv3.Cluster{ + Name: emptyClusterName, + ClusterDiscoveryType: &clusterv3.Cluster_Type{Type: clusterv3.Cluster_STATIC}, +} + // Translator translates the xDS IR into xDS resources. type Translator struct { // GlobalRateLimit holds the global rate limit settings @@ -723,11 +729,6 @@ func (t *Translator) processTCPListenerXdsTranslation( // If there are no routes, add a route without a destination to the listener to create a filter chain // This is needed because Envoy requires a filter chain to be present in the listener, otherwise it will reject the listener and report a warning if len(tcpListener.Routes) == 0 { - emptyRouteCluster := &clusterv3.Cluster{ - Name: emptyClusterName, - ClusterDiscoveryType: &clusterv3.Cluster_Type{Type: clusterv3.Cluster_STATIC}, - } - if findXdsCluster(tCtx, emptyClusterName) == nil { if err := tCtx.AddXdsResource(resourcev3.ClusterType, emptyRouteCluster); err != nil { errs = errors.Join(errs, err) @@ -762,28 +763,40 @@ func processUDPListenerXdsTranslation( // There won't be multiple UDP listeners on the same port since it's already been checked at the gateway api // translator if udpListener.Route != nil { - route := udpListener.Route - - xdsListener, err := buildXdsUDPListener(route.Destination.Name, udpListener, accesslog) - if err != nil { - // skip this listener if failed to build xds listener - errs = errors.Join(errs, err) - continue - } - if err := tCtx.AddXdsResource(resourcev3.ListenerType, xdsListener); err != nil { - // skip this listener if failed to add xds listener to the resource version table - errs = errors.Join(errs, err) - continue - } - // 1:1 between IR UDPRoute and xDS Cluster if err := processXdsCluster(tCtx, - route.Destination.Name, - route.Destination.Settings, - &UDPRouteTranslator{route}, + udpListener.Route.Destination.Name, + udpListener.Route.Destination.Settings, + &UDPRouteTranslator{udpListener.Route}, &ExtraArgs{metrics: metrics}); err != nil { errs = errors.Join(errs, err) } + } else { + udpListener.Route = &ir.UDPRoute{ + Name: emptyClusterName, + Destination: &ir.RouteDestination{ + Name: emptyClusterName, + }, + } + + // Add empty cluster for UDP listener which have no Route, when empty cluster is not found. + if findXdsCluster(tCtx, emptyClusterName) == nil { + if err := tCtx.AddXdsResource(resourcev3.ClusterType, emptyRouteCluster); err != nil { + errs = errors.Join(errs, err) + } + } + } + + xdsListener, err := buildXdsUDPListener(udpListener.Route.Destination.Name, udpListener, accesslog) + if err != nil { + // skip this listener if failed to build xds listener + errs = errors.Join(errs, err) + continue + } + if err := tCtx.AddXdsResource(resourcev3.ListenerType, xdsListener); err != nil { + // skip this listener if failed to add xds listener to the resource version table + errs = errors.Join(errs, err) + continue } } return errs @@ -1043,6 +1056,30 @@ func buildXdsUpstreamTLSSocketWthCert(tlsConfig *ir.TLSUpstreamConfig) (*corev3. }, }, } + for _, san := range tlsConfig.SubjectAltNames { + var sanType tlsv3.SubjectAltNameMatcher_SanType + var value string + + // Exactly one of san.Hostname or san.URI is guaranteed to be set + if san.Hostname != nil { + sanType = tlsv3.SubjectAltNameMatcher_DNS + value = *san.Hostname + } else if san.URI != nil { + sanType = tlsv3.SubjectAltNameMatcher_URI + value = *san.URI + } + validationContext.DefaultValidationContext.MatchTypedSubjectAltNames = append( + validationContext.DefaultValidationContext.MatchTypedSubjectAltNames, + &tlsv3.SubjectAltNameMatcher{ + SanType: sanType, + Matcher: &matcherv3.StringMatcher{ + MatchPattern: &matcherv3.StringMatcher_Exact{ + Exact: value, + }, + }, + }, + ) + } } tlsCtx := &tlsv3.UpstreamTlsContext{ diff --git a/release-notes/current.yaml b/release-notes/current.yaml index 3271a4f907..32b53627d1 100644 --- a/release-notes/current.yaml +++ b/release-notes/current.yaml @@ -8,8 +8,18 @@ security updates: | # New features or capabilities added in this release. new features: | + Added support for percentage-based request mirroring + Add an option to OIDC authentication to bypass it and defer to JWT when the request contains an "Authorization: Bearer ..." header. + Added support for configuring Subject Alternative Names (SANs) for upstream TLS validation via `BackendTLSPolicy.validation.subjectAltNames`. + Added support for local rate limit header. + Added XDS metadata for clusters and endpoints from xRoutes and referenced backend resources (Backend, Service, ServiceImport). + Added support for setting ownerreference to infra resources when enable gateway namespace mode. bug fixes: | + Handle integer zone annotation values + Fixed issue where WASM cache init failure caused routes with WASM-less EnvoyExtensionPolicies to have 500 direct responses. + Fixed issue which UDP listeners were not created in the Envoy proxy config when Gateway was created. + Keep ALPN configuration for listeners with overlapping certificates when ALPN is explicitly set in ClientTrafficPolicy. # Enhancements that improve performance. performance improvements: | diff --git a/site/content/en/latest/tasks/observability/proxy-trace.md b/site/content/en/latest/tasks/observability/proxy-trace.md index e4b43d4434..054e9fb5e6 100644 --- a/site/content/en/latest/tasks/observability/proxy-trace.md +++ b/site/content/en/latest/tasks/observability/proxy-trace.md @@ -72,7 +72,7 @@ spec: "k8s.namespace.name": type: Environment environment: - name: ENVOY_GATEWAY_NAMESPACE + name: ENVOY_POD_NAMESPACE defaultValue: "envoy-gateway-system" # This is an example of using a header value as a tag value header1: @@ -138,7 +138,7 @@ spec: "k8s.namespace.name": type: Environment environment: - name: ENVOY_GATEWAY_NAMESPACE + name: ENVOY_POD_NAMESPACE defaultValue: "envoy-gateway-system" # This is an example of using a header value as a tag value header1: @@ -202,7 +202,7 @@ spec: "k8s.namespace.name": type: Environment environment: - name: ENVOY_GATEWAY_NAMESPACE + name: ENVOY_POD_NAMESPACE defaultValue: "envoy-gateway-system" # This is an example of using a header value as a tag value header1: @@ -277,7 +277,7 @@ spec: "k8s.namespace.name": type: Environment environment: - name: ENVOY_GATEWAY_NAMESPACE + name: ENVOY_POD_NAMESPACE defaultValue: "envoy-gateway-system" # This is an example of using a header value as a tag value header1: @@ -336,7 +336,7 @@ spec: "k8s.namespace.name": type: Environment environment: - name: ENVOY_GATEWAY_NAMESPACE + name: ENVOY_POD_NAMESPACE defaultValue: "envoy-gateway-system" # This is an example of using a header value as a tag value header1: @@ -348,4 +348,4 @@ EOF ``` -[envoy-proxy-crd]: ../../api/extension_types#envoyproxy \ No newline at end of file +[envoy-proxy-crd]: ../../api/extension_types#envoyproxy diff --git a/site/content/en/latest/tasks/operations/customize-envoyproxy.md b/site/content/en/latest/tasks/operations/customize-envoyproxy.md index 561d1d9a42..e183ea8960 100644 --- a/site/content/en/latest/tasks/operations/customize-envoyproxy.md +++ b/site/content/en/latest/tasks/operations/customize-envoyproxy.md @@ -375,7 +375,7 @@ spec: {{% /tab %}} {{< /tabpane >}} -> Envoy Gateway has provided two initial `env` `ENVOY_GATEWAY_NAMESPACE` and `ENVOY_POD_NAME` for envoyproxy container. +> Envoy Gateway has provided two initial `env` `ENVOY_POD_NAMESPACE` and `ENVOY_POD_NAME` for envoyproxy container. After applying the config, you can get the envoyproxy deployment, and see resources has been changed. @@ -513,7 +513,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: default + namespace: default spec: bootstrap: type: Replace @@ -733,7 +733,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: default + namespace: default spec: bootstrap: type: JSONPatch @@ -787,7 +787,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: default + namespace: default spec: provider: type: Kubernetes @@ -815,7 +815,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: default + namespace: default spec: provider: type: Kubernetes @@ -851,10 +851,10 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: default + namespace: default spec: extraArgs: - - --disable-extensions envoy.access_loggers/envoy.access_loggers.wasm + - --disable-extensions envoy.access_loggers/envoy.access_loggers.wasm EOF ``` @@ -868,10 +868,10 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: default + namespace: default spec: extraArgs: - - --disable-extensions envoy.access_loggers/envoy.access_loggers.wasm + - --disable-extensions envoy.access_loggers/envoy.access_loggers.wasm ``` {{% /tab %}} @@ -894,7 +894,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: eg - namespace: default + namespace: default spec: provider: type: Kubernetes @@ -1036,7 +1036,7 @@ By default, Envoy Gateway applies the following filters in the order shown: * envoy.filters.http.ratelimit * envoy.filters.http.router -The default order in which these filters are applied is opinionated and may not suit all use cases. +The default order in which these filters are applied is opinionated and may not suit all use cases. To address this, Envoy Gateway allows you to adjust the execution order of these filters with the `filterOrder` field in the [EnvoyProxy][] resource. `filterOrder` is a list of customized filter order configurations. Each configuration can specify a filter @@ -1137,4 +1137,4 @@ After applying the config, the EnvoyProxy deployment will be configured to use t [Gateway API documentation]: https://gateway-api.sigs.k8s.io/ [EnvoyProxy]: ../../../api/extension_types#envoyproxy -[egctl x translate]: ../operations/egctl#egctl-experimental-translate \ No newline at end of file +[egctl x translate]: ../operations/egctl#egctl-experimental-translate diff --git a/site/go.mod b/site/go.mod index 1f97d802bd..f61b8059b1 100644 --- a/site/go.mod +++ b/site/go.mod @@ -1,6 +1,6 @@ module github.com/google/docsy-example -go 1.24.2 +go 1.24.3 require ( github.com/FortAwesome/Font-Awesome v0.0.0-20240402185447-c0f460dca7f7 // indirect diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go index 399087cb71..6c8446eb12 100644 --- a/test/e2e/e2e_test.go +++ b/test/e2e/e2e_test.go @@ -41,7 +41,6 @@ func TestE2E(t *testing.T) { skipTests := []string{ tests.GatewayInfraResourceTest.ShortName, // https://github.com/envoyproxy/gateway/issues/3191 - tests.BackendTLSSettingsTest.ShortName, // https://github.com/envoyproxy/gateway/pull/6029 } // Skip test only work on DualStack cluster @@ -68,7 +67,6 @@ func TestE2E(t *testing.T) { tests.HTTPWasmTest.ShortName, tests.OCIWasmTest.ShortName, tests.ZoneAwareRoutingTest.ShortName, - // Skip RateLimit tests because they are not supported in GatewayNamespaceMode tests.RateLimitCIDRMatchTest.ShortName, tests.RateLimitHeaderMatchTest.ShortName, diff --git a/test/e2e/merge_gateways/merge_gateways_test.go b/test/e2e/merge_gateways/merge_gateways_test.go index ffa1e1774e..9729a514d9 100644 --- a/test/e2e/merge_gateways/merge_gateways_test.go +++ b/test/e2e/merge_gateways/merge_gateways_test.go @@ -25,6 +25,10 @@ import ( ) func TestMergeGateways(t *testing.T) { + // Skip the entire test suite if we're in Gateway Namespace Mode + if tests.IsGatewayNamespaceMode() { + t.Skip("MergeGateways tests are not supported in Gateway Namespace Mode") + } flag.Parse() c, cfg := kubetest.NewClient(t) @@ -46,7 +50,7 @@ func TestMergeGateways(t *testing.T) { RunTest: *flags.RunTest, // SupportedFeatures cannot be empty, so we set it to SupportGateway // All e2e tests should leave Features empty. - SupportedFeatures: sets.New[features.FeatureName](features.SupportGateway), + SupportedFeatures: sets.New(features.SupportGateway), SkipTests: []string{}, }) if err != nil { diff --git a/test/e2e/testdata/backend-tls-settings-client-cert-rotation.yaml b/test/e2e/testdata/backend-tls-settings-client-cert-rotation.yaml index 03ac6f32db..de0492570d 100644 --- a/test/e2e/testdata/backend-tls-settings-client-cert-rotation.yaml +++ b/test/e2e/testdata/backend-tls-settings-client-cert-rotation.yaml @@ -1,20 +1,13 @@ --- +# This is used as the client certificate for the envoy to connect to the backend service +# openssl req -out envoy.csr -newkey rsa:2048 -nodes -keyout envoy.key -subj "/CN=envoy/O=example organization" +# openssl x509 -req -days 36500 -CA ca.crt -CAkey ca.key -set_serial 0 -in envoy.csr -out envoy.crt apiVersion: v1 -data: - tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURFVENDQWZrQ0ZGZ1A5ckEyNFA2NnhXcDRQSnEzY05KdHJYRXBNQTBHQ1NxR1NJYjNEUUVCQ3dVQU1FVXgKQ3pBSkJnTlZCQVlUQWtGVk1STXdFUVlEVlFRSURBcFRiMjFsTFZOMFlYUmxNU0V3SHdZRFZRUUtEQmhKYm5SbApjbTVsZENCWGFXUm5hWFJ6SUZCMGVTQk1kR1F3SGhjTk1qUXdOakF5TVRnMU5ESXlXaGNOTWpVd05qQXlNVGcxCk5ESXlXakJGTVFzd0NRWURWUVFHRXdKQlZURVRNQkVHQTFVRUNBd0tVMjl0WlMxVGRHRjBaVEVoTUI4R0ExVUUKQ2d3WVNXNTBaWEp1WlhRZ1YybGtaMmwwY3lCUWRIa2dUSFJrTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQwpBUThBTUlJQkNnS0NBUUVBblpYeHQ0Tk5TQVYxT2YyWDBDY1E2clk1eUlKQjRVWlkzVytPSlpQZmZtT0xZSFE5Cld6ZEQyUStCdHpocHNnVmhuZ25XZjVCeDlzbFExakdmSWY3eGFJbDNHcE13S3dsbk1mRlB6d0lxcTc1MHV4bzIKcU9QV1VwTHhoWXl4eVVHU0xXeTZuZ1RHOTBnRjM2MUNsWkJqVWxML2g3M2VHSmMydERVWG85T1k1SFhJc0hnbwp0WlJTWXdJV1kwbjgyMmFTT0tPTCtBeDc0eVV3ODMwSnRxK1RmbDlCbjFZMWNZVjgrNDZqVnhodzBVWHlac1diCk5CdllzQk1jZmFVcmdyWjlSVXYzYlJuNS9kUVFlanMvRzJVOGlmNW9qR0NaSG5nUEFLV0NyS0MxejU1RmVYbEgKSDR1cVJ5ZGRKL1IyYUVsYnkyeUhrSmVEaFRjQmhxUXFIT2dMU1FJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQ3dVQQpBNElCQVFBTU1ldzg2dmVrM1hpdGNUd25lcnlNOUU0MjVCOVYrd24ya2swYTFNMDhlSGhNU2xHREQ4bG5mb1hKClNhZHEzbStBSlgyNHByZTBJQkMzRlhXajBrdCt5ZXN1dCtQR01jaHR1YXJYOU1PakpPRVk1NFFCRUdBNXJ0TzgKRWM0bWdqNkkzSGxGa2RTbUVkZTJjVTFPMDFlU3JZZG9vWUpmc2RLN1drUWEzNElRb1lPREhPbUFnMnluaVhZbQppSXZaUHkzUHdYSnN5VFNpYi9BMXQ3WEpoS3RIdUxvWGxPTHpVSUFMVkZsRzRNQjRreHcrMlVueFZHdjI0NUg0CjFsTnVaRk1BSXhWMXdZYkplbTFUT1ZLcFdMVmVqWE85SWZvcks1VmdqVzV2TkM1ejU3Um41dDljSGwxUHVhVmQKYk01U2ozU2pMWW52cXNQZ2JReXAxdWc3UEJBUwotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== - tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2QUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktZd2dnU2lBZ0VBQW9JQkFRQ2RsZkczZzAxSUJYVTUKL1pmUUp4RHF0am5JZ2tIaFJsamRiNDRsazk5K1k0dGdkRDFiTjBQWkQ0RzNPR215QldHZUNkWi9rSEgyeVZEVwpNWjhoL3ZGb2lYY2FrekFyQ1djeDhVL1BBaXFydm5TN0dqYW80OVpTa3ZHRmpMSEpRWkl0YkxxZUJNYjNTQVhmCnJVS1ZrR05TVXYrSHZkNFlsemEwTlJlajA1amtkY2l3ZUNpMWxGSmpBaFpqU2Z6YlpwSTRvNHY0REh2akpURHoKZlFtMnI1TitYMEdmVmpWeGhYejdqcU5YR0hEUlJmSm14WnMwRzlpd0V4eDlwU3VDdG4xRlMvZHRHZm45MUJCNgpPejhiWlR5Si9taU1ZSmtlZUE4QXBZS3NvTFhQbmtWNWVVY2ZpNnBISjEwbjlIWm9TVnZMYkllUWw0T0ZOd0dHCnBDb2M2QXRKQWdNQkFBRUNnZ0VBVVN0ejl4K2x4ZXd4eHE0TjdZVEIzUFFCN1hyU3JsUEs0RHhlenBKTmMwK1kKOGhUTnFkZGNsa2k3ZXdHT3g4aW4wSHlteE14Rk4yWFl3b3VLdVRzVlk5QXl6amgwZmlaNHhpdlMvUURUcytVRgpRWDZ1R3U1SWJmNE1jOHJWcEtHbXhza1RrdU5KRFFSSEtrQ1haR3ljREVKK0pwQXcveCtjYU5SVUdlbWEva215CklrZ0FRMUpxQ1lFNTJKUG1PWGRhL3VjMEJtMGYyQkFZUmh6V3JmRGV4SnlzelloMDdhNHNWVW9FRXlxbjlFV2EKbVZOQkV2SzQwVm1KVFcyV1ZuN3lZUnk2OUgvbGl2cGZWdG1RbE9SaVBkYXRaK1RUaXA2VHF2SFIwNHZyam1pMApQUXdhbkJmN3Z6aE9SU3Z1VDhOUEtWV1pkeHAxQm1JaWtrUmpSYjRyMFFLQmdRRE0yaWk5QXowZDVSbnZzV24zClJrWlNZbG1CaHhROGFKajBqY1l0cHBycEQ3ZFgvbGh4dDRHNFBSVWx5QTcwSmFMOVBrTVhZcklhNlpJMUQyRC8Kb2ZSbFoybE9HMUtnVVVTUW42bFFiaWo3NkdyaFhlOXhvRDE5eEdEai9HWTFSRDB1VGI5OWhtU1lyVzJySnREQwpMWG0vWUV1TjJGc2N4Q3QzOHhBVWl1bzZiUUtCZ1FERTdwV1laa3RzeXcyTkJhRmo1NXZJYkcyVjhkUk9vdzFsCnY4cWxsMllHWXpHWEJzNlBodzlGMUNzcjl4dm9HNmhPR1hFNmxOL25RZGtxTEtONEJqM25lNXZJMGUxKzI0TG0Ka0lZK0ltTWo1U2w4QzFuUzR3MVFVTlREYWIyakhackFXd0hJQlBUdFYzbDdMY3cvQXh5NnRjcVJ2alpoQjVnZAplL1N3RStzS3pRS0JnQm5wbHJHaUVUOFExZUVPRGh0clZrWGhqdlRsZzFmSTIyQkQ5c2ViaFlqcHBnV0pkT0tkCmxka2FVT3lBaS9PeU54WFZwR0wyNXhTa2F3d3ZMOVBtUnFYMUdNcjZoYzhsdUlpYXlhNFU0VFpNUmdqUCt4UGkKY3lUUGpIb0tXVnR2a0ZXbEhBM2l6Q0xML1UxakVaRWVjNElUeWpyZEhWbGNMeXR6SVp1WG50MVpBb0dBQUxsago0WENXM0dxT3ZUTUZHZW56SDdTT1hwdktEUlA2YTZKZDYyZjRIeFBrVGNyZm5aV0FqK0FzM0hlSEtiNVlTeGs2CjJsMUx5WHpyZ0lVemdMQjlMOG03ayt4NXRCcTRpNEtDaTkzeWdXSkpXY1JzNnlLY25Pdi9MRXpLUHJ4UUlsN3oKVGJuKzhKUit4TjR4UHhZUzEvanRLc1lKU3lnTS9pYkRpcFk0S2cwQ2dZQmExL0RYQlVIVWI3UlFWcVBrdVJsYQpHenhVeTd4c3dXQkNVbWtkNkdyUG4vM0pGRW5udTRCdUovUHBRNTNQY1hLTTNWM041Uis2dkVHdHRteWtxRDZZCkp5NjZrQkxMdk1aLzZvUHJzZWxNUUVZZjRwa21CSnlHdHNxOElkR3RZT1dVdXpwbmhuTUdWRG8vODVrUVIvaEwKaUhxQW9TMEJXMDU1eEdsVzVFa2VGZz09Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K kind: Secret metadata: name: client-tls-certificate namespace: envoy-gateway-system type: kubernetes.io/tls ---- -apiVersion: v1 data: - tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURFVENDQWZrQ0ZGZ1A5ckEyNFA2NnhXcDRQSnEzY05KdHJYRXBNQTBHQ1NxR1NJYjNEUUVCQ3dVQU1FVXgKQ3pBSkJnTlZCQVlUQWtGVk1STXdFUVlEVlFRSURBcFRiMjFsTFZOMFlYUmxNU0V3SHdZRFZRUUtEQmhKYm5SbApjbTVsZENCWGFXUm5hWFJ6SUZCMGVTQk1kR1F3SGhjTk1qUXdOakF5TVRnMU5ESXlXaGNOTWpVd05qQXlNVGcxCk5ESXlXakJGTVFzd0NRWURWUVFHRXdKQlZURVRNQkVHQTFVRUNBd0tVMjl0WlMxVGRHRjBaVEVoTUI4R0ExVUUKQ2d3WVNXNTBaWEp1WlhRZ1YybGtaMmwwY3lCUWRIa2dUSFJrTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQwpBUThBTUlJQkNnS0NBUUVBblpYeHQ0Tk5TQVYxT2YyWDBDY1E2clk1eUlKQjRVWlkzVytPSlpQZmZtT0xZSFE5Cld6ZEQyUStCdHpocHNnVmhuZ25XZjVCeDlzbFExakdmSWY3eGFJbDNHcE13S3dsbk1mRlB6d0lxcTc1MHV4bzIKcU9QV1VwTHhoWXl4eVVHU0xXeTZuZ1RHOTBnRjM2MUNsWkJqVWxML2g3M2VHSmMydERVWG85T1k1SFhJc0hnbwp0WlJTWXdJV1kwbjgyMmFTT0tPTCtBeDc0eVV3ODMwSnRxK1RmbDlCbjFZMWNZVjgrNDZqVnhodzBVWHlac1diCk5CdllzQk1jZmFVcmdyWjlSVXYzYlJuNS9kUVFlanMvRzJVOGlmNW9qR0NaSG5nUEFLV0NyS0MxejU1RmVYbEgKSDR1cVJ5ZGRKL1IyYUVsYnkyeUhrSmVEaFRjQmhxUXFIT2dMU1FJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQ3dVQQpBNElCQVFBTU1ldzg2dmVrM1hpdGNUd25lcnlNOUU0MjVCOVYrd24ya2swYTFNMDhlSGhNU2xHREQ4bG5mb1hKClNhZHEzbStBSlgyNHByZTBJQkMzRlhXajBrdCt5ZXN1dCtQR01jaHR1YXJYOU1PakpPRVk1NFFCRUdBNXJ0TzgKRWM0bWdqNkkzSGxGa2RTbUVkZTJjVTFPMDFlU3JZZG9vWUpmc2RLN1drUWEzNElRb1lPREhPbUFnMnluaVhZbQppSXZaUHkzUHdYSnN5VFNpYi9BMXQ3WEpoS3RIdUxvWGxPTHpVSUFMVkZsRzRNQjRreHcrMlVueFZHdjI0NUg0CjFsTnVaRk1BSXhWMXdZYkplbTFUT1ZLcFdMVmVqWE85SWZvcks1VmdqVzV2TkM1ejU3Um41dDljSGwxUHVhVmQKYk01U2ozU2pMWW52cXNQZ2JReXAxdWc3UEJBUwotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== - tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2QUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktZd2dnU2lBZ0VBQW9JQkFRQ2RsZkczZzAxSUJYVTUKL1pmUUp4RHF0am5JZ2tIaFJsamRiNDRsazk5K1k0dGdkRDFiTjBQWkQ0RzNPR215QldHZUNkWi9rSEgyeVZEVwpNWjhoL3ZGb2lYY2FrekFyQ1djeDhVL1BBaXFydm5TN0dqYW80OVpTa3ZHRmpMSEpRWkl0YkxxZUJNYjNTQVhmCnJVS1ZrR05TVXYrSHZkNFlsemEwTlJlajA1amtkY2l3ZUNpMWxGSmpBaFpqU2Z6YlpwSTRvNHY0REh2akpURHoKZlFtMnI1TitYMEdmVmpWeGhYejdqcU5YR0hEUlJmSm14WnMwRzlpd0V4eDlwU3VDdG4xRlMvZHRHZm45MUJCNgpPejhiWlR5Si9taU1ZSmtlZUE4QXBZS3NvTFhQbmtWNWVVY2ZpNnBISjEwbjlIWm9TVnZMYkllUWw0T0ZOd0dHCnBDb2M2QXRKQWdNQkFBRUNnZ0VBVVN0ejl4K2x4ZXd4eHE0TjdZVEIzUFFCN1hyU3JsUEs0RHhlenBKTmMwK1kKOGhUTnFkZGNsa2k3ZXdHT3g4aW4wSHlteE14Rk4yWFl3b3VLdVRzVlk5QXl6amgwZmlaNHhpdlMvUURUcytVRgpRWDZ1R3U1SWJmNE1jOHJWcEtHbXhza1RrdU5KRFFSSEtrQ1haR3ljREVKK0pwQXcveCtjYU5SVUdlbWEva215CklrZ0FRMUpxQ1lFNTJKUG1PWGRhL3VjMEJtMGYyQkFZUmh6V3JmRGV4SnlzelloMDdhNHNWVW9FRXlxbjlFV2EKbVZOQkV2SzQwVm1KVFcyV1ZuN3lZUnk2OUgvbGl2cGZWdG1RbE9SaVBkYXRaK1RUaXA2VHF2SFIwNHZyam1pMApQUXdhbkJmN3Z6aE9SU3Z1VDhOUEtWV1pkeHAxQm1JaWtrUmpSYjRyMFFLQmdRRE0yaWk5QXowZDVSbnZzV24zClJrWlNZbG1CaHhROGFKajBqY1l0cHBycEQ3ZFgvbGh4dDRHNFBSVWx5QTcwSmFMOVBrTVhZcklhNlpJMUQyRC8Kb2ZSbFoybE9HMUtnVVVTUW42bFFiaWo3NkdyaFhlOXhvRDE5eEdEai9HWTFSRDB1VGI5OWhtU1lyVzJySnREQwpMWG0vWUV1TjJGc2N4Q3QzOHhBVWl1bzZiUUtCZ1FERTdwV1laa3RzeXcyTkJhRmo1NXZJYkcyVjhkUk9vdzFsCnY4cWxsMllHWXpHWEJzNlBodzlGMUNzcjl4dm9HNmhPR1hFNmxOL25RZGtxTEtONEJqM25lNXZJMGUxKzI0TG0Ka0lZK0ltTWo1U2w4QzFuUzR3MVFVTlREYWIyakhackFXd0hJQlBUdFYzbDdMY3cvQXh5NnRjcVJ2alpoQjVnZAplL1N3RStzS3pRS0JnQm5wbHJHaUVUOFExZUVPRGh0clZrWGhqdlRsZzFmSTIyQkQ5c2ViaFlqcHBnV0pkT0tkCmxka2FVT3lBaS9PeU54WFZwR0wyNXhTa2F3d3ZMOVBtUnFYMUdNcjZoYzhsdUlpYXlhNFU0VFpNUmdqUCt4UGkKY3lUUGpIb0tXVnR2a0ZXbEhBM2l6Q0xML1UxakVaRWVjNElUeWpyZEhWbGNMeXR6SVp1WG50MVpBb0dBQUxsago0WENXM0dxT3ZUTUZHZW56SDdTT1hwdktEUlA2YTZKZDYyZjRIeFBrVGNyZm5aV0FqK0FzM0hlSEtiNVlTeGs2CjJsMUx5WHpyZ0lVemdMQjlMOG03ayt4NXRCcTRpNEtDaTkzeWdXSkpXY1JzNnlLY25Pdi9MRXpLUHJ4UUlsN3oKVGJuKzhKUit4TjR4UHhZUzEvanRLc1lKU3lnTS9pYkRpcFk0S2cwQ2dZQmExL0RYQlVIVWI3UlFWcVBrdVJsYQpHenhVeTd4c3dXQkNVbWtkNkdyUG4vM0pGRW5udTRCdUovUHBRNTNQY1hLTTNWM041Uis2dkVHdHRteWtxRDZZCkp5NjZrQkxMdk1aLzZvUHJzZWxNUUVZZjRwa21CSnlHdHNxOElkR3RZT1dVdXpwbmhuTUdWRG8vODVrUVIvaEwKaUhxQW9TMEJXMDU1eEdsVzVFa2VGZz09Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K -kind: Secret -metadata: - name: client-tls-validation - namespace: gateway-conformance-infra -type: kubernetes.io/tls + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMwakNDQWJvQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFnRncweU5UQTFNVE13TlRReE1ERmFHQTh5TVRJMQpNRFF4T1RBMU5ERXdNVm93THpFT01Bd0dBMVVFQXd3RlpXNTJiM2t4SFRBYkJnTlZCQW9NRkdWNFlXMXdiR1VnCmIzSm5ZVzVwZW1GMGFXOXVNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQWxBWGYKTFVOZS9jbEQ2VjA1MVNZTm5XWW82aU44T1cyOTZnTm1JeHF5Y0J0TFp0ZTBzdlJJVXZQclczUkErb0ZCRjFocgpTeWZGZGJ5Tk0yQjB3WFhFRTlRVTg0c1RZdk9wNkk4TjkxUlBHY2ZscVF1NEgrK040bGxHK1hOWDljMjk4ckJxCkVWaitQdmMyWW5WZ0JLUi94bVczTUJpZVhEOUVxaFBsc2Y3Z0d6MjBKYVlqWDZyZ2tUdVVnSTBKcEhLNTBwaDYKU1BwazFaSERoTzk1RUUySVFQYk5GTFNwam1YeEFSMkdxOTYrVzcySWlsaVFyRk13M0IxWVBrZ2loeVpGZUhKTAo5THg4SllicmdEQjZjcUFxL0lIazRBRmd6engrdDhVNDFZYkRHUlZRZ25sVDlYVXE1Zkh2aEtzVDB0cWY2U0diCkg2eGlhbnRpcnphVktnYi9EUUlEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQm1TY05IN3J5ZUFlNksKeU5WcWc2UlUrOFNoWTFnTTlCQTlUZTBLVmtEd0MyMVZhYkh0bjJiQm5MOHZlZzY2Ny9QUWZhbEhrR2tGMG94ago5SVRQb0tBTEt5dHV1VlFJRWtTVmxKOHhjZnplUHBzbGJEeXZ1R2Z2dGtkV0ZxbElsam9PSUU0SndSNjkxK3B1CjB3YnVzaGkyZHc4OVFmSXRGOFBsbVM5ZjZLSFVsTGtRdGV3c1hUSDVJZWo1dmxsOVV3ZEFjWWNQM096bXM0VlAKVjFtOW1tNjM1aDJJSDczajVkSmhyUzRTbmRRUVJqeGczN282Z1JLYXU3bi92alRZbmFhR01xTkgvMkc1cGtJSQpzVmViejM2SHZsNDluaU83Vmd4R3BXa1VyaU43Mno4OFpsK3J2T2dCSGIwTlFvQmhuNWt2TU1JL2svZVNRL2dDCnpVNmoydmZCCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ1VCZDh0UTE3OXlVUHAKWFRuVkpnMmRaaWpxSTN3NWJiM3FBMllqR3JKd0cwdG0xN1N5OUVoUzgrdGJkRUQ2Z1VFWFdHdExKOFYxdkkwegpZSFRCZGNRVDFCVHppeE5pODZub2p3MzNWRThaeCtXcEM3Z2Y3NDNpV1ViNWMxZjF6YjN5c0dvUldQNCs5elppCmRXQUVwSC9HWmJjd0dKNWNQMFNxRStXeC91QWJQYlFscGlOZnF1Q1JPNVNBalFta2NyblNtSHBJK21UVmtjT0UKNzNrUVRZaEE5czBVdEttT1pmRUJIWWFyM3I1YnZZaUtXSkNzVXpEY0hWZytTQ0tISmtWNGNrdjB2SHdsaHV1QQpNSHB5b0NyOGdlVGdBV0RQUEg2M3hUalZoc01aRlZDQ2VWUDFkU3JsOGUrRXF4UFMycC9wSVpzZnJHSnFlMkt2Ck5wVXFCdjhOQWdNQkFBRUNnZ0VBRlhTRmJRYmhINmw2MDdvOHpmbWlTeEI1K1RnVUF6SDJMMU4zVERyTUp1WTUKNTJuNEtlRXhFMzhCL0FOTmdOSFgyTFdxOVoySjZEOGdlMVF0a0RZTTZlL1phcFNieG9HNWZMa3hoY285WGVnRQowSndmZjllRjZndFZONGFCdHlIdmVKd2IvN0ExeC9RbXVKNDVRT3NFRDBLQ2l6RGlVVTRsV242Z1VreTJlSlFnClNoTGNkVjZobWFHVGhyUzNUTWlSMnlqK3F4UlhpSEdvSXdXN1BkM3V4bEZiMVJ1bW9JMGhUN3dEVWNSSk52K0cKemVlNUMwODk4UUlyeGxqME93amM4dGVMaDFJQXplTFNWazk3dEluaFVTRFlrSnNBcFhTYVNCam1pa2VCbzlJWAoyRlJQN1dxeTFQRjkvTCtzOTNSMTJycDJmOGh2ZGFXM0c2NHl4dnBLTVFLQmdRRExkd2NWYXQzUEtoNWU2d3VOCm1kVGFoN29LTHI2RUZxZ0tGNlRkcnV3bmlPbjQzQ0tQekgxK2tIdElKYXQyM3R4VzJUeVZqTkExY1REaUZnS00KK1MyWFdFTDBmU0x3VmVOaSt2MWdaYlFKZVQyMUt0cmVBb1VTZzZLU2NxZlFaam5BVXFrZ0xaUGJqZnQwZ0NWUAoyZ2Q0UXpyT05NQnlDdm5vd1JnNXc5T1lFUUtCZ1FDNlBpUytUUUVidDZYZHIvYXpncUlQSXBWYkFYbEpPbDBQCkt5eWxQY01OYkw0dCtHNXROdStjMEtIeVExbG9FMWg5eXRUMCtKTk16R1BtbkQ0b1VtUHBwUmZnL256bTlzbEsKVGNobXk1bnJLenMvVlRqTmlDRkxTdjJIc1ZBWkFWcnk4N2ZwOGt1VUhXbTlHUnVJRXIwZGhmK1BtQjFGTEpZegpSekxZdGFxVFBRS0JnUUNIMk9BTTU3NVRMRzc4dHZpT3diQUJmRysxanNJN1ZSazdLOUF6QnpDN3NNbHZGQ09yCldVQk0rZENtT2lpQ2hJZ2ZJSW8zMjczRWdOKy9oQ3lOelcwb1NKRGp4bzFHWkVJZSt5K2paaVJQMHZobGRzaU4KUktkdTFoNzhvcnJ6Qk4zNFQvaUYrSWhwSmlKSEJheGo1VkhwZFJIVlRobFR5NHBTWW1KM1p3MW0wUUtCZ0JGUQpwNy9kanVYUnpDVHhNQ0YrV3F6SGpWVTVyTm9IQ0JIWjlMdWtJMWRETGVjK09wNEN4b0l3ejIyam4xTlN3UjVvCjFpVzBXcFdBUnlWd2owTFdiaDJSME1lRlFYMkRvakU3VEE5cWpIUFZ3QnRpUS9hdjJsQ1N0MEYvVmJBTmRUUXoKUG4wTW5zUTFlOWd0MW1adlA0L1lIbXR1UEFKclk4ZCtyaGFCeFVzTkFvR0FiTXo4VnFpend5Si9rVlFQTUx5dQpJaHpyMThxUEIzcXp5QVVDOHJBMDNDcnM0L01mTTloOFB3TXdkRVdKb3JMQ1ZwRFhqbGVqZXE2Z3pPMmpCdWJDCldtYmxSaFUxN0NQQUJpY2dFR2hIVitFNnlzbk8zbnZ4Wi9uT2srUTcyRGdkZkFJQzc1UHdMbFF2NDVnbnI2Y3MKdWQ5TXVEOGtrZDVpQ3VHbTNrRGpZY009Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K diff --git a/test/e2e/testdata/backend-tls-settings.yaml b/test/e2e/testdata/backend-tls-settings.yaml index b78ace739f..2bcb291a28 100644 --- a/test/e2e/testdata/backend-tls-settings.yaml +++ b/test/e2e/testdata/backend-tls-settings.yaml @@ -6,52 +6,73 @@ metadata: spec: gatewayClassName: "{GATEWAY_CLASS_NAME}" listeners: - - name: https + - name: http + port: 80 + protocol: HTTP +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: http-with-backend-tls + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: backend-namespaces + rules: + - matches: + - path: + type: PathPrefix + value: /backend-tls + backendRefs: + - name: tls-backend port: 443 - protocol: HTTPS - tls: - certificateRefs: - - group: "" - kind: Secret - name: backend-tls-certificate - mode: Terminate - - name: http - port: 80 - protocol: HTTP - allowedRoutes: - namespaces: - from: Selector - selector: - matchLabels: - gateway-conformance: backend --- +# openssl req -x509 -sha256 -nodes -days 36500 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout ca.key -out ca.crt apiVersion: v1 +kind: ConfigMap +metadata: + name: ca-certificate + namespace: gateway-conformance-infra data: ca.crt: | -----BEGIN CERTIFICATE----- - MIIDQzCCAiugAwIBAgIBATANBgkqhkiG9w0BAQsFADBCMRMwEQYDVQQKEwpFbnZv - eVByb3h5MRAwDgYDVQQLEwdHYXRld2F5MRkwFwYDVQQDExBFbnZveSBHYXRld2F5 - IENBMCAXDTI0MDMxMDE1MzIxN1oYDzIxMjQwMzEwMTYzMjE3WjBCMRMwEQYDVQQK - EwpFbnZveVByb3h5MRAwDgYDVQQLEwdHYXRld2F5MRkwFwYDVQQDExBFbnZveSBH - YXRld2F5IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7ZFmGB4e - m1KdGEohAZBfqydAEGLDHJ1YyfHWdd+vBAevdW64bZx3pggJOtgCnePuFd02rDQS - dlsJlX/6mFtoQilo6wvxDSJRfaTDbtfTjw+7k8yfd/Jsmh0RWG+UeyI7Na9sXAz7 - b57mpxsCoNowzeK5ETiOGGNWPcjENJkSnBarz5muN00xIZWBU+yN5PLJNxZvxpZJ - Ol/SSI8sno0e0PxAmp3fe7QaXiZj/TAGJPGuTJkUxrHqyZGJtYUxsS8A0dT1zBjj - izA5Dp+b5yzYo23Hh7BgpbZ7X4gsDThFuwCD6fHyepuv2zHPqvSsdqg2hAhDp91R - zrn7a9GxG2VSIwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw - AwEB/zAdBgNVHQ4EFgQUUpP1aZ1M2KIuPPWrNPDV2c5CngowDQYJKoZIhvcNAQEL - BQADggEBAGSEkAVz+Z0qS4FmA0q4SCpIIq64bsdEjiUzev7pK1LEK0/Y28QBPixV - cUXfax18VPR9pls1JgXto9qY+C0hnRZic6611QTJlWK1p6dinQ/eDdYCBC+nv5xx - ssASwmplIxMvj3S1qF6dr7sMI2ZVD5HElTWdO19UBLyhiKKZW2KxDsYj+5NRwGFe - G+JuDgq7njUM8mdyYk0NehefdBUEUUCQtnwUtW95/429XwqQROuRDteGT9kjD+Y5 - ea5mW4mfqLeuGJXZs9bdWjKKdLQPrn9IshPysWqz2Hz8dQ1f7N9/g8UWVSjd4cyx - S5EAolzVv0yB7wHCWCgfG/ckdOTUNnE= + MIIDPTCCAiWgAwIBAgIUCPaRrg+0wCmznOMf9HxtYXPc+rowDQYJKoZIhvcNAQEL + BQAwLTEVMBMGA1UECgwMZXhhbXBsZSBJbmMuMRQwEgYDVQQDDAtleGFtcGxlLmNv + bTAgFw0yNTA1MTMwMTI0MDRaGA8yMTI1MDQxOTAxMjQwNFowLTEVMBMGA1UECgwM + ZXhhbXBsZSBJbmMuMRQwEgYDVQQDDAtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcN + AQEBBQADggEPADCCAQoCggEBAO7E7Gtx+tUS5UujhJ/DdSqsqQQ391WnrQbI1i9c + tiYSj8p8/eq1dAw4u3gG5426UaVph8LG5GLYCGT8XPmeWQMZncGvf9TeqlmBz/WM + NJ6Ow7dh6pWfGuZ7FHkv+l7L7pd/SFd8z0yuLBeTkE3weZ0jcnoThpm7Unu5ULdV + /ZE0rnAG7cjqiTALj/QE1gF0VkXw6D9fT5SamKYasYT0ZQND5tVOlLoqXjYU1fJF + Gyqs7hI24c6KeB1G6giWvwiUSzHBmCL0seCDDGeIjhtO7YubRZqNHaE1cw3FFlb7 + FwXbff8XVb85Mxy6Jwdq27sCy4iMUSBVgbRhLRb9Cp+iUBMCAwEAAaNTMFEwHQYD + VR0OBBYEFAhZJV5u/3sXGacaUkuP5zIFZYGiMB8GA1UdIwQYMBaAFAhZJV5u/3sX + GacaUkuP5zIFZYGiMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB + AJJmuyGwjP9KG1uwhfJ5jq3b+vUUZW29HnFzEfd50GAk++W1WBTyxpWXCX0VW4Va + /QcJJiROXoKUqGtqPHYKx8UQ/mzrmlRGMgKwYReoMLU6ukydox9AUDVQFnOQZm26 + QTCwXb288715UeK+c+TdmpkFkTPh3F67HDn0q9mtoT9g9BckJRxoHaez1LfxbytW + nNBx3Rpk1Ps79EfjtKL1BJIvG/N/ar9Jey2CR+tlVKwrrPCGG1ObcGvHooQWOOCq + 7jD99R8PXZV5VDyP8qoHPYYyqkaQH4nQtVm288vFNQRF+/vUUQsNKl/JQcTG2UCc + IwP0azf9fJ+Xxx19TOMO3FA= -----END CERTIFICATE----- -kind: ConfigMap +--- +apiVersion: gateway.networking.k8s.io/v1alpha3 +kind: BackendTLSPolicy metadata: - name: backend-tls-certificate + name: policy-btls namespace: gateway-conformance-infra +spec: + targetRefs: + - group: "" + kind: Service + name: tls-backend + sectionName: https + validation: + caCertificateRefs: + - name: ca-certificate + group: "" + kind: ConfigMap + hostname: example.com --- apiVersion: v1 kind: Service @@ -62,10 +83,10 @@ spec: selector: app: tls-backend ports: - - name: https - protocol: TCP - port: 443 - targetPort: 8443 + - name: https + protocol: TCP + port: 443 + targetPort: 8443 --- apiVersion: apps/v1 kind: Deployment @@ -85,100 +106,80 @@ spec: app: tls-backend spec: containers: - - name: tls-backend - image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e - volumeMounts: - - name: secret-volume - mountPath: /etc/secret-volume - - name: client-certs-volume - mountPath: /etc/client-certs - env: - - name: TLS_CLIENT_CACERTS - value: /etc/client-certs/crt - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: SERVICE_NAME - value: tls-backend - - name: TLS_SERVER_CERT - value: /etc/secret-volume/crt - - name: TLS_SERVER_PRIVKEY - value: /etc/secret-volume/key - resources: - requests: - cpu: 10m - volumes: - - name: client-certs-volume - secret: - secretName: client-tls-validation - items: - - key: tls.crt - path: crt + - name: tls-backend + image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e + volumeMounts: - name: secret-volume - secret: - secretName: backend-tls-certificate - items: - - key: tls.crt - path: crt - - key: tls.key - path: key ---- -apiVersion: gateway.networking.k8s.io/v1alpha3 -kind: BackendTLSPolicy -metadata: - name: policy-btls - namespace: gateway-conformance-infra -spec: - targetRefs: - - group: "" - kind: Service - name: tls-backend - sectionName: https - validation: - caCertificateRefs: - - name: backend-tls-certificate - group: "" - kind: ConfigMap - hostname: example.com ---- -apiVersion: gateway.networking.k8s.io/v1 -kind: HTTPRoute -metadata: - name: http-with-backend-tls - namespace: gateway-conformance-infra -spec: - parentRefs: - - name: backend-namespaces - rules: - - matches: - - path: - type: PathPrefix - value: /backend-tls - backendRefs: - - name: tls-backend - port: 443 + mountPath: /etc/secret-volume + - name: client-ca-volume + mountPath: /etc/client-ca + env: + - name: TLS_CLIENT_CACERTS + value: /etc/client-ca/ca.crt + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: SERVICE_NAME + value: tls-backend + - name: TLS_SERVER_CERT + value: /etc/secret-volume/crt + - name: TLS_SERVER_PRIVKEY + value: /etc/secret-volume/key + resources: + requests: + cpu: 10m + volumes: + - name: client-ca-volume + configMap: + name: ca-certificate + - name: secret-volume + secret: + secretName: backend-tls-certificate-tls-settings + items: + - key: tls.crt + path: crt + - key: tls.key + path: key --- +# This is used as the client certificate for the envoy to connect to the backend service +# openssl req -out envoy.csr -newkey rsa:2048 -nodes -keyout envoy.key -subj "/CN=envoy/O=example organization" +# openssl x509 -req -days 36500 -CA ca.crt -CAkey ca.key -set_serial 0 -in envoy.csr -out envoy.crt apiVersion: v1 -data: - tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURPVENDQWlHZ0F3SUJBZ0lVUWNxbnZtQXlkRUtuOEdqWTdjZzVDb3A2QWp3d0RRWUpLb1pJaHZjTkFRRUwKQlFBd1JURUxNQWtHQTFVRUJoTUNRVlV4RXpBUkJnTlZCQWdNQ2xOdmJXVXRVM1JoZEdVeElUQWZCZ05WQkFvTQpHRWx1ZEdWeWJtVjBJRmRwWkdkcGRITWdVSFI1SUV4MFpEQWVGdzB5TkRBMU1USXhOakF3TlROYUZ3MHlOVEExCk1USXhOakF3TlROYU1FVXhDekFKQmdOVkJBWVRBa0ZWTVJNd0VRWURWUVFJREFwVGIyMWxMVk4wWVhSbE1TRXcKSHdZRFZRUUtEQmhKYm5SbGNtNWxkQ0JYYVdSbmFYUnpJRkIwZVNCTWRHUXdnZ0VpTUEwR0NTcUdTSWIzRFFFQgpBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQ2kzUis1WGx3SnlYSTNidTRVQ3E0NXgwSkdWQVBTVXRFTFlLUkxpOEo2CnlxOStySE1hVUtubDhsdldLaHlCNDk4WkJBdVVGS0RpcGhkS1A2eU0rRGl1azVIa2UrK0NmeGxkUDFiSGZiNlkKSGFWczh2cFMyUThneUF6NEZqc3NnNThMV1NKWTdEeEhSOWJibUVWelhSUjNWOEtDeDVaYVlkZ3RxU0NZTGJMTwozaGtGRGQramZxSzM3RHdiT253d21OQ2R0QmpRSTF1TmF2dm1QZzB0c3pwd29TQUtPRitPR0pHcTZHcDdNY0NtClFHZ3dYNkV0YzMwd3hJQTd6c3RnTWwzT293a3p4NHNMcFdJamdCSDVlVk9oYnB6NXROLzB2VFZ3Z3hlbTlOVisKQURjSTFBcnY5M1ZsaFB6VEFmZUNDUlljeFFiNlp4dnBuMWlRbVIrZkVpT0JBZ01CQUFHaklUQWZNQjBHQTFVZApEZ1FXQkJTMGRnRHNtQ3AyU0pZVzNPa3pkNDZtbFNndHZ6QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFab0NCCnE0M2taV1RZT21QR3JYMU5RMllIVTQ2Y0pzRGxsN2JFL0ZIRUo1eEJEcWRGaUdhWkZBcGRkK3Mra2tkUUw5NUUKcU1SVk9nYS83TUFIL042dlRmb2tXcnVKUUFqaStpLzhGSllWb1VZTWMyeUxqYXp3ZS9ZMHlzTDRWRTNGUlZybApmVHRCTC9nVkhjNk9ZOFBpVFh4eitqdy9FN2kxQkRxZkdSK29sYmt4ZkVmWnhHN0tEZUVtQnVva0dxbDlYQXhSCjMzbnhSbFZuODdxSnJrdUlzdWl2ZzczaVVNMVpGUE1CRVp0OEJjU05MaWhxZEx0b29FVy9mcGZ1am9oaC9yTjUKOFA1ajJpWm9KOGpBS0t4YW5SaWhXTklSNzJtYnJ1R2hYOFRIQkxzczFvZlpLdHBXMzlUOTBTM2hnWkFwSmNZYQp2aGVwSnRtbm9jcHNnYUJiL0E9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== - tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2kzUis1WGx3SnlYSTMKYnU0VUNxNDV4MEpHVkFQU1V0RUxZS1JMaThKNnlxOStySE1hVUtubDhsdldLaHlCNDk4WkJBdVVGS0RpcGhkSwpQNnlNK0RpdWs1SGtlKytDZnhsZFAxYkhmYjZZSGFWczh2cFMyUThneUF6NEZqc3NnNThMV1NKWTdEeEhSOWJiCm1FVnpYUlIzVjhLQ3g1WmFZZGd0cVNDWUxiTE8zaGtGRGQramZxSzM3RHdiT253d21OQ2R0QmpRSTF1TmF2dm0KUGcwdHN6cHdvU0FLT0YrT0dKR3E2R3A3TWNDbVFHZ3dYNkV0YzMwd3hJQTd6c3RnTWwzT293a3p4NHNMcFdJagpnQkg1ZVZPaGJwejV0Ti8wdlRWd2d4ZW05TlYrQURjSTFBcnY5M1ZsaFB6VEFmZUNDUlljeFFiNlp4dnBuMWlRCm1SK2ZFaU9CQWdNQkFBRUNnZ0VBQkZlOUxUbXNMb3VBWGZTWmdRZStnT0pZbU1pTDZpcG91aWI0Wlk1dFUvM3kKYVZoRXlOVHhuVlRadkoyT2lWc0JzWVNLWUo5TzBaRmFSOUhJSnBHR1BTYzRvOGNYWGpkb2RqUmFrbjdtbDQ2NwprT3JQR0lsQ3ZFb0NVTVdTdkExNXpzMGdmNTZUdmthMjFxL2VHdmtPZ3c3SVBEbVJSNEZpT05nNGt3ODlwRU1FClhNMVROK1NZSGR1eU50RG1wSy90bjFFcUxtOUJUVy9XSk8rMHhLaG1EVStDZnN6Y2hmcS82QitQSVNteEhXUTUKV2JVL3BBNVlvRlM3TWZYbjhMcXVuSG55RGcvNERaQ2NXQkpZZTdZNWtqczVVd2c2MnJBanZxTUZPaWk2ZEgvWgpSQWFWbzlUeEEwZVB4TkZIY2w5M2xuQzRvSGpFV0pvajIzOUdTb3pMWVFLQmdRRGJaNDhNOUpNdkJ2Q2JvSWlXCi9jc3U2ZFRNNmlRTzd3dVJEekhETlpGN0pxWmxOVUhkMU1hZXVYOGhYaE1YeWZpN2FFcGhKMGFZOXNwZ29SdWYKamIyeWVhb3JBbnlOL1VIZ2NjdG5ESWdheEJ0K1JVREZUeE1uTnhrRUVnTnF5WDJCZllOdlNyMmxOVm9PbGhUWQo4VzV6UGJyekNDbUgzSXd6bkhmcW54QVZJUUtCZ1FDK0IwOEVpRERZd1ZKRU9uNyt3eDZyZWlQQklmanBFNUNICjM4ekpYVVBUaWRLZWpORnU4aUlGZmkrdzEvY0VBTTJXcE1xVEtnM2RCSTlzUGZnWXZFSUlvMW5adUFNVnhaY04Kb0k2QXdUckdWMldHSjdQNlNNbjhyWTJhUGRQcDl1ZXE2MFEwZ2p2NVQ1eUliekdPaElmeUpxSXJHYlFvbGdkagp3cXg4K2ZQaVlRS0JnRWJSdklqd0FQb3pBVU1hcER3b200Yi9EeU05aUhvUml1Zzl3VkJEWUR3aUU1K2pleWxCClh3TW8yUEpLVFZ0bVpCVUo2c2hGUnpKa3BwcGVKbTV2OEFWRjVEbVJ5ZWFERXRxQm9LZ1lrVzRpVXNXRlVRemYKSTAyTEtWWDVBb1ZibUZsTnpEa0dKUVRJbmRNTGVwczBBdlRMdmlab1FnK0tqdTZ4Mkxzd3NKNUJBb0dCQUxFcApDUzcxZFd5dkZ1NUxCdGltdWpJdDVhV0o4WkFDVUcyTVpWU1o0Y0VXcmNocENsdi8yMTM1bmFhbVFVRjNLalEyCm9ER0JOSG1JWmRvSkVBS25pSHliSmdwSGRvRFd2SlBVeXVZWXY1M29IdHRxcW0wOWJTcG45eXNFVjB1NWg1UWUKVUhFUHRiQWgyNUtLNzgycG0wQlRhajc2Y0s2aDZIUEdLNTg4UEhZaEFvR0FILzJMS044WnJ3c1R6Nmx6T2c3ZApzdUFuaDVFTUp0TEhTSDJHeFJ5aFcrYVFHdGNxdDZYK1dkNDZnd1BMQjRjd2QzL01nQkFvcFhGazhYV3pTVUlhCnI5SG9SQzZJT2tzQ0lOallCd2h2TjArcm5oN3JzTm5XZVd5Z2tWQ2tERDN5NlNTa2RTZjliOUZzWUJtOHY0VkcKYzFqdmVjWVF6S243QzFRU2FtUnAzRUk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K kind: Secret metadata: - name: client-tls-validation - namespace: gateway-conformance-infra + name: client-tls-certificate + namespace: envoy-gateway-system type: kubernetes.io/tls +data: + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMwakNDQWJvQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFnRncweU5UQTFNVE13TWpVMU1EUmFHQTh5TVRJMQpNRFF4T1RBeU5UVXdORm93THpFT01Bd0dBMVVFQXd3RlpXNTJiM2t4SFRBYkJnTlZCQW9NRkdWNFlXMXdiR1VnCmIzSm5ZVzVwZW1GMGFXOXVNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQWlIS3EKU016TkpkM2lCbTg3MzB1OFQ0R25wK2FMaG1rYWFvSHAwMXB6YWJJVitxRUlnREJZUFNLemtsQnk2UVRYcDZ2Zwp4UXIvbDNEdGRqQWFEOEpoNVRRU2syNnRlbnJVWkhyTHFlTTl1VGtZR29jMmF1Nlk4V0tHbCt5QTBKUHNET3VKCjZNRlpZUy82Q2oveDJ0RkZEdFloVjR3cmJXQzUxVU1mY05iYzFoNHozSndGUlpLZi9BdkdDa1c2NkUvZFFDeXEKalRvMEs0SDRqNjZncWJXdGRLY1ZGOTUySUtwYkZwRmh4WmM3VWRJbGNUK1FyVUNCaHFVLzRKNmJXODg1TEZBSwpmWnpLbzBFckl0RFJ3WGNKZU0xSVUrTGs5bkJnUjZYTTVOOHEvVTluVHQ3MGFFR25sVWJSWHhyNmsvVWF1QjdBClRqbXJsVnZBOFVVU1BZbXpVUUlEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQTZyNkd2WVF5NHEwRksKWWlqdkR6bTlOS1JaWlY1ajU0WEEwcWFwRGhUQ3loYzFueGQ5cTRLamNZQmhPRzhBczBkWi9SNTg1bzRnZDhpZQpDUmhQSWJ2cEJMZnc3MWFxOVIxSHBIOW9JRlBLN1VnemhpTnQyL0tVWkdURTVGZkRFNFhJa2E3ckVjT0RzMlNKClFxMnkwMmRXTmxLSDZ1cThLTi9zenBYR1RnRUkxT09BYSs2SW11QkF0SVJRY3Jra2JJcyt4eUxWMWlGNnNZZXQKTFdMMnA1MUdOanBiZFdaOXBrZWdvd1JJSXBEWmhDbFVPZHlMREFuQjQ3dE8vNGRTVGxZdndvSUs0UGN3RGxQRQpkUzdqZDI3Y0FzZ0ttb2NyMDhIOHVGUUZaK1VCWmN3YU5qL0lNODhjS0QxWHJIY2F3SXRsc0dKVHlxZkNhUmFPCjNPc0ZSUWNFCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktnd2dnU2tBZ0VBQW9JQkFRQ0ljcXBJek0wbDNlSUcKYnp2ZlM3eFBnYWVuNW91R2FScHFnZW5UV25OcHNoWDZvUWlBTUZnOUlyT1NVSExwQk5lbnErREZDditYY08xMgpNQm9Qd21IbE5CS1RicTE2ZXRSa2VzdXA0ejI1T1JnYWh6WnE3cGp4WW9hWDdJRFFrK3dNNjRub3dWbGhML29LClAvSGEwVVVPMWlGWGpDdHRZTG5WUXg5dzF0eldIalBjbkFWRmtwLzhDOFlLUmJyb1Q5MUFMS3FOT2pRcmdmaVAKcnFDcHRhMTBweFVYM25ZZ3Fsc1drV0hGbHp0UjBpVnhQNUN0UUlHR3BUL2ducHRienprc1VBcDluTXFqUVNzaQowTkhCZHdsNHpVaFQ0dVQyY0dCSHBjemszeXI5VDJkTzN2Um9RYWVWUnRGZkd2cVQ5UnE0SHNCT09hdVZXOER4ClJSSTlpYk5SQWdNQkFBRUNnZ0VBUDBNMnUya2xKb3pnK2szQmF5N1FvT1pDeHVCbnlVcGF3bzM0VFJOdlZrNkkKelRxelY4ZlNhWW40eXZvOHhOZ0hhc2lRZnBzeVZOTTViZVl3ZHlVUFFYY3FzNnVKaURPQjNSSm44aDBYWlpUWQpuWmdhUFdyaGcyMUViUlRzeG9nRzFoaXd5TGM0aXd4MCtDS2NybkQvZlRqL25Ya3lPMVN3NUhWcUV1V3ozeHZWCmE0WW1TdTJnRkNQZlZDemhQT1IwbGc5ZFRYZmlWQzEvTHpXRXllbEVpMExtMm90cFJaUXVUd1ZzekVuLzNjQTEKamlKREJEWVEvS1ZESTJ2QW9OK25rRWozMTMwVHFaaUphNlQrYTkreEdqMHpyQzNXdU9yU0oyVml2N1JwSytMWgpveGxpazBkNkU5Q3lIa2JXWTRPQlM3UEt2c1hqRHpFY3Vuc29SRngzMXdLQmdRQzgwSTV0YkNFV0VqaHRSdmdPCldVUkJ1OFNPek9qT2hGc0Y1ekNjMEJzWlVHak1pUm1KYUFLa2t2MHhvOVVmK05DU2NQWVJpTFJoZkoyRUZuM2wKR2dYOFJrdGZKMTRFd2d0d0ZJd1pzSkhuOEczdXJPcjJRd3JCcTNCb0dGb3NyR091L0V5Wk5UYmF4VUZrZVhBbQp1TysvZmpaSFVnZXFQSVdvR0ZUclk0SzhCd0tCZ1FDNC8rN2NLLzQ0Y3ZwTHpPK0xzY25vc2VnY2xqUWpkZm41CjNDQzNQL2E0UjlveFR5VWorejlPWXdiUkhMTmYwTzJQNWRhUGdTV0pIV2owM0FUemJ6L2xxVi9Td2hkTTNFejAKU2pqU2Z4NktKS2VyK0dyeXQ2V2tIa3k5QjVwcVN5UVlueDBBZ0lvdURuY3NQazI2cUV4Mkdzb1RURlowR3EvMQpHbStBeDkxdjV3S0JnUUNzL2ZRUWd3cEpXNFpCY00xaThCeWVrVGVFa204V2o2T0o1QWpoRTdaUVdpQzZqVDVOCmEzTkliN2YxSENMdmVSczNvTEdDM1JwUFcwcENOQTFDczdZYUxobHVZL1k3SzhJby9WcGpTeWhUTmpDeWhkRjgKc1c0UWhVK212L0VXanhlQnduMDN2YzYxWUJjS3hFeWgzYjBqV0xMSVkzck1XVWtuK3FzTFE1QUxUd0tCZ0RHdgpRclpNOW1Td3RIb2hHd0NZaWhKOW5VbjRLUjZRODhiZ0VNVkdYM3VVaUl3UHBuam9aRk1vRTArYjlxeTREdVZECnBBRThmUms3RmRJVk9Sc3IrS3cwZGZERGdjQjV0ZzB4MWRycW13Z2MyZzg4azNTR1QrMG8yaEUyZG9rdmp3MHgKeG5jNURtTmFMVFZyc2pKOE9yVEpjeFlGdlg1SElKU2lPZW9MUTNSbkFvR0JBTEpuejJja3dZVXM5UHFVNjd4TgpRc21UM25ON2g5SEZ2WVJTR2xJUWROT2l3SlpiMWRZUHM2QzFlYUF1U09iWHNEWkRsNmtBVXZ3U1JHRTRKa2ZnCmpBQ2h5QVRKV3NJTVNMbkY1SHlJeE1GQVZwa3d1QW93RlIrdCt2NXppakxJZ2RPWnhhaG9BNjdENVcvb3hsMlAKMWRSdDVuaS8zTGNRaEdpMmtDWG9vK2JnCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K --- +# cat > openssl.conf < 0 && vals[0] == "3, 3;w=3600" + }, suite.TimeoutConfig.MaxTimeToConsistency, suite.TimeoutConfig.RequestTimeout, "rate limit header not yet present") - _ = GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &expectOk1, gwAddr2, "HTTP", "http"), expectOk1) - _ = GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &expectOk2, gwAddr1, "HTTP", "http"), expectOk2) - _ = GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &expectOk3, gwAddr2, "HTTP", "http"), expectOk3) - _ = GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &expectLimit, gwAddr1, "HTTP", "http"), expectLimit) + for _, expect := range []http.ExpectedResponse{expectOk1, expectOk2} { + if err := GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &expect, gwAddr2, "HTTP", "http"), expect); err != nil { + t.Errorf("expected 200 response: %v", err) + } + } + if err := GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &expectLimit, gwAddr1, "HTTP", "http"), expectLimit); err != nil { + t.Errorf("expected 429 response: %v", err) + } }) t.Run("unshared_route_policy_x-user-id=two", func(t *testing.T) { headers := map[string]string{"x-user-id": "two"} - // Route 1 (/foo) - ok1 := http.ExpectedResponse{Request: http.Request{Path: "/foo", Headers: headers}, Response: http.Response{StatusCode: 200}, Namespace: ns} - limit1 := http.ExpectedResponse{Request: http.Request{Path: "/foo", Headers: headers}, Response: http.Response{StatusCode: 429}, Namespace: ns} - // Route 2 (/bar) - ok2 := http.ExpectedResponse{Request: http.Request{Path: "/bar", Headers: headers}, Response: http.Response{StatusCode: 200}, Namespace: ns} - limit2 := http.ExpectedResponse{Request: http.Request{Path: "/bar", Headers: headers}, Response: http.Response{StatusCode: 429}, Namespace: ns} + okFoo := http.ExpectedResponse{Request: http.Request{Path: "/foo", Headers: headers}, Response: http.Response{StatusCode: 200}, Namespace: ns} + limitFoo := http.ExpectedResponse{Request: http.Request{Path: "/foo", Headers: headers}, Response: http.Response{StatusCode: 429}, Namespace: ns} + okBar := http.ExpectedResponse{Request: http.Request{Path: "/bar", Headers: headers}, Response: http.Response{StatusCode: 200}, Namespace: ns} + limitBar := http.ExpectedResponse{Request: http.Request{Path: "/bar", Headers: headers}, Response: http.Response{StatusCode: 429}, Namespace: ns} - http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr1, ok1) + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr1, okFoo) - _ = GotExactExpectedResponse(t, 3, suite.RoundTripper, http.MakeRequest(t, &ok1, gwAddr1, "HTTP", "http"), ok1) - _ = GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &limit1, gwAddr1, "HTTP", "http"), limit1) + for i := 0; i < 2; i++ { + if err := GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &okFoo, gwAddr1, "HTTP", "http"), okFoo); err != nil { + t.Errorf("foo request #%d failed: %v", i+1, err) + } + } + if err := GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &limitFoo, gwAddr1, "HTTP", "http"), limitFoo); err != nil { + t.Errorf("expected 429 on 4th foo: %v", err) + } - _ = GotExactExpectedResponse(t, 3, suite.RoundTripper, http.MakeRequest(t, &ok2, gwAddr2, "HTTP", "http"), ok2) - _ = GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &limit2, gwAddr2, "HTTP", "http"), limit2) + for i := 0; i < 3; i++ { + if err := GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &okBar, gwAddr2, "HTTP", "http"), okBar); err != nil { + t.Errorf("bar request #%d failed: %v", i+1, err) + } + } + if err := GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &limitBar, gwAddr2, "HTTP", "http"), limitBar); err != nil { + t.Errorf("expected 429 on 4th bar: %v", err) + } }) t.Run("shared_gateway_policy_x-user-id=three", func(t *testing.T) { @@ -1000,32 +1020,58 @@ var RateLimitGlobalMergeTest = suite.ConformanceTest{ ok1 := http.ExpectedResponse{Request: http.Request{Path: "/bar", Headers: headers}, Response: http.Response{StatusCode: 200}, Namespace: ns} ok2 := http.ExpectedResponse{Request: http.Request{Path: "/foo", Headers: headers}, Response: http.Response{StatusCode: 200}, Namespace: ns} - ok3 := http.ExpectedResponse{Request: http.Request{Path: "/bar", Headers: headers}, Response: http.Response{StatusCode: 200}, Namespace: ns} limit := http.ExpectedResponse{Request: http.Request{Path: "/foo", Headers: headers}, Response: http.Response{StatusCode: 429}, Namespace: ns} http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr2, ok1) - _ = GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &ok1, gwAddr2, "HTTP", "http"), ok1) - _ = GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &ok2, gwAddr1, "HTTP", "http"), ok2) - _ = GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &ok3, gwAddr2, "HTTP", "http"), ok3) - _ = GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &limit, gwAddr1, "HTTP", "http"), limit) + for _, expect := range []http.ExpectedResponse{ok1, ok2} { + if err := GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &expect, gwAddr2, "HTTP", "http"), expect); err != nil { + t.Errorf("expected 200 response: %v", err) + } + } + if err := GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &limit, gwAddr1, "HTTP", "http"), limit); err != nil { + t.Errorf("expected 429 response: %v", err) + } }) t.Run("unshared_gateway_policy__x-user-id=four", func(t *testing.T) { headers := map[string]string{"x-user-id": "four"} - ok1 := http.ExpectedResponse{Request: http.Request{Path: "/foo", Headers: headers}, Response: http.Response{StatusCode: 200}, Namespace: ns} - limit1 := http.ExpectedResponse{Request: http.Request{Path: "/foo", Headers: headers}, Response: http.Response{StatusCode: 429}, Namespace: ns} - ok2 := http.ExpectedResponse{Request: http.Request{Path: "/bar", Headers: headers}, Response: http.Response{StatusCode: 200}, Namespace: ns} - limit2 := http.ExpectedResponse{Request: http.Request{Path: "/bar", Headers: headers}, Response: http.Response{StatusCode: 429}, Namespace: ns} + okFoo := http.ExpectedResponse{Request: http.Request{Path: "/foo", Headers: headers}, Response: http.Response{StatusCode: 200}, Namespace: ns} + limitFoo := http.ExpectedResponse{Request: http.Request{Path: "/foo", Headers: headers}, Response: http.Response{StatusCode: 429}, Namespace: ns} + okBar := http.ExpectedResponse{Request: http.Request{Path: "/bar", Headers: headers}, Response: http.Response{StatusCode: 200}, Namespace: ns} + limitBar := http.ExpectedResponse{Request: http.Request{Path: "/bar", Headers: headers}, Response: http.Response{StatusCode: 429}, Namespace: ns} - http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr1, ok1) + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr1, okFoo) + + for i := 0; i < 2; i++ { + if err := GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &okFoo, gwAddr1, "HTTP", "http"), okFoo); err != nil { + t.Errorf("foo request #%d failed: %v", i+1, err) + } + } + if err := GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &limitFoo, gwAddr1, "HTTP", "http"), limitFoo); err != nil { + t.Errorf("expected 429 on 4th foo: %v", err) + } + + for i := 0; i < 3; i++ { + if err := GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &okBar, gwAddr2, "HTTP", "http"), okBar); err != nil { + t.Errorf("bar request #%d failed: %v", i+1, err) + } + } + if err := GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &limitBar, gwAddr2, "HTTP", "http"), limitBar); err != nil { + t.Errorf("expected 429 on 4th bar: %v", err) + } + }) - _ = GotExactExpectedResponse(t, 3, suite.RoundTripper, http.MakeRequest(t, &ok1, gwAddr1, "HTTP", "http"), ok1) - _ = GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &limit1, gwAddr1, "HTTP", "http"), limit1) + t.Run("shared_no_client_selectors", func(t *testing.T) { + ok1 := http.ExpectedResponse{Request: http.Request{Path: "/bar"}, Response: http.Response{StatusCode: 200}, Namespace: ns} + limit := http.ExpectedResponse{Request: http.Request{Path: "/bar"}, Response: http.Response{StatusCode: 429}, Namespace: ns} - _ = GotExactExpectedResponse(t, 3, suite.RoundTripper, http.MakeRequest(t, &ok2, gwAddr2, "HTTP", "http"), ok2) - _ = GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &limit2, gwAddr2, "HTTP", "http"), limit2) + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr1, ok1) + + if err := GotExactExpectedResponse(t, 1, suite.RoundTripper, http.MakeRequest(t, &limit, gwAddr1, "HTTP", "http"), limit); err != nil { + t.Errorf("expected 429 for third request: %v", err) + } }) }, } diff --git a/test/fuzz/testdata/FuzzGatewayAPIToXDS/proxy_tracing b/test/fuzz/testdata/FuzzGatewayAPIToXDS/proxy_tracing index b9c8baa433..57904783bd 100644 --- a/test/fuzz/testdata/FuzzGatewayAPIToXDS/proxy_tracing +++ b/test/fuzz/testdata/FuzzGatewayAPIToXDS/proxy_tracing @@ -40,11 +40,11 @@ spec: "k8s.namespace.name": type: Environment environment: - name: ENVOY_GATEWAY_NAMESPACE + name: ENVOY_POD_NAMESPACE defaultValue: "envoy-gateway-system" # This is an example of using a header value as a tag value header1: type: RequestHeader requestHeader: name: X-Header-1 - defaultValue: "-" \ No newline at end of file + defaultValue: "-" diff --git a/test/helm/gateway-addons-helm/default.out.yaml b/test/helm/gateway-addons-helm/default.out.yaml index af620e2596..ee3e59f822 100644 --- a/test/helm/gateway-addons-helm/default.out.yaml +++ b/test/helm/gateway-addons-helm/default.out.yaml @@ -8494,7 +8494,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "description": "The fraction of this program's available CPU time used by the GC since the program started.", "fieldConfig": { @@ -8578,7 +8578,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "disableTextWrap": false, "editorMode": "code", @@ -8601,7 +8601,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "description": "Resident memory size", "fieldConfig": { @@ -8650,7 +8650,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "disableTextWrap": false, "editorMode": "code", @@ -8672,7 +8672,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "description": "Virtual memory size", "fieldConfig": { @@ -8722,7 +8722,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "disableTextWrap": false, "editorMode": "code", @@ -8744,7 +8744,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "description": "Number of ratelimit rule hits in total", "fieldConfig": { @@ -8797,7 +8797,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "disableTextWrap": false, "editorMode": "builder", @@ -8819,7 +8819,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "description": "Number of rule hits over the NearLimit ratio threshold (currently 80%) but under the threshold rate.", "fieldConfig": { @@ -8872,7 +8872,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "disableTextWrap": false, "editorMode": "builder", @@ -8894,7 +8894,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "description": "Number of rule hits exceeding the threshold rate", "fieldConfig": { @@ -8947,7 +8947,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "disableTextWrap": false, "editorMode": "builder", @@ -8978,7 +8978,7 @@ data: "current": { "selected": false, "text": "Prometheus", - "value": "PBFA97CFB590B2093" + "value": "$datasource" }, "hide": 0, "includeAll": false, diff --git a/test/helm/gateway-addons-helm/e2e.out.yaml b/test/helm/gateway-addons-helm/e2e.out.yaml index e561695f6b..60c1ec512d 100644 --- a/test/helm/gateway-addons-helm/e2e.out.yaml +++ b/test/helm/gateway-addons-helm/e2e.out.yaml @@ -8586,7 +8586,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "description": "The fraction of this program's available CPU time used by the GC since the program started.", "fieldConfig": { @@ -8670,7 +8670,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "disableTextWrap": false, "editorMode": "code", @@ -8693,7 +8693,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "description": "Resident memory size", "fieldConfig": { @@ -8742,7 +8742,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "disableTextWrap": false, "editorMode": "code", @@ -8764,7 +8764,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "description": "Virtual memory size", "fieldConfig": { @@ -8814,7 +8814,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "disableTextWrap": false, "editorMode": "code", @@ -8836,7 +8836,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "description": "Number of ratelimit rule hits in total", "fieldConfig": { @@ -8889,7 +8889,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "disableTextWrap": false, "editorMode": "builder", @@ -8911,7 +8911,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "description": "Number of rule hits over the NearLimit ratio threshold (currently 80%) but under the threshold rate.", "fieldConfig": { @@ -8964,7 +8964,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "disableTextWrap": false, "editorMode": "builder", @@ -8986,7 +8986,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "description": "Number of rule hits exceeding the threshold rate", "fieldConfig": { @@ -9039,7 +9039,7 @@ data: { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "$datasource" }, "disableTextWrap": false, "editorMode": "builder", @@ -9070,7 +9070,7 @@ data: "current": { "selected": false, "text": "Prometheus", - "value": "PBFA97CFB590B2093" + "value": "$datasource" }, "hide": 0, "includeAll": false, diff --git a/test/helm/gateway-crds-helm/all.out.yaml b/test/helm/gateway-crds-helm/all.out.yaml index 2612431a81..a18c940126 100644 --- a/test/helm/gateway-crds-helm/all.out.yaml +++ b/test/helm/gateway-crds-helm/all.out.yaml @@ -22006,6 +22006,7 @@ spec: - Streamed - Buffered - BufferedPartial + - FullDuplexStreamed type: string type: object response: @@ -22029,6 +22030,7 @@ spec: - Streamed - Buffered - BufferedPartial + - FullDuplexStreamed type: string type: object type: object diff --git a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml index 9dc657ce74..65b9f354fb 100644 --- a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml +++ b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml @@ -4694,6 +4694,7 @@ spec: - Streamed - Buffered - BufferedPartial + - FullDuplexStreamed type: string type: object response: @@ -4717,6 +4718,7 @@ spec: - Streamed - Buffered - BufferedPartial + - FullDuplexStreamed type: string type: object type: object diff --git a/tools/hack/create-cluster.sh b/tools/hack/create-cluster.sh index 6c2a93f515..6b440b084c 100755 --- a/tools/hack/create-cluster.sh +++ b/tools/hack/create-cluster.sh @@ -30,14 +30,14 @@ networking: nodes: - role: control-plane labels: - "topology.kubernetes.io/zone": "0" + "topology.kubernetes.io/zone": 0 EOM ) # https://kind.sigs.k8s.io/docs/user/quick-start/#multi-node-clusters if [[ -n "${NUM_WORKERS}" ]]; then for i in $(seq 1 "${NUM_WORKERS}"); do - KIND_CFG+=$(printf "\n- role: worker\n labels:\n \"topology.kubernetes.io/zone\": \"%s\"" "$i") + KIND_CFG+=$(printf "\n- role: worker\n labels:\n \"topology.kubernetes.io/zone\": %s" "$i") done fi