diff --git a/.github/workflows/build_and_test.yaml b/.github/workflows/build_and_test.yaml index 7db36c998b2..d0a960e8469 100644 --- a/.github/workflows/build_and_test.yaml +++ b/.github/workflows/build_and_test.yaml @@ -52,7 +52,7 @@ jobs: - name: Run Coverage Tests run: make go.test.coverage - name: Upload coverage to Codecov - uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4 + uses: codecov/codecov-action@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # v3.1.5 with: fail_ci_if_error: true files: ./coverage.xml @@ -70,7 +70,7 @@ jobs: run: make build-multiarch PLATFORMS="linux_amd64 linux_arm64" - name: Upload EG Binaries - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: envoy-gateway path: bin/ @@ -86,7 +86,7 @@ jobs: - uses: ./tools/github-actions/setup-deps - name: Download EG Binaries - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: envoy-gateway path: bin/ @@ -114,7 +114,7 @@ jobs: - uses: ./tools/github-actions/setup-deps - name: Download EG Binaries - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: envoy-gateway path: bin/ @@ -139,7 +139,7 @@ jobs: - uses: ./tools/github-actions/setup-deps - name: Download EG Binaries - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: envoy-gateway path: bin/ diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 37fdcd9aa8e..ce15ada7e85 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -36,14 +36,14 @@ jobs: - uses: ./tools/github-actions/setup-deps - name: Initialize CodeQL - uses: github/codeql-action/init@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12 + uses: github/codeql-action/init@379614612a29c9e28f31f39a59013eb8012a51f0 # v3.24.3 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12 + uses: github/codeql-action/autobuild@379614612a29c9e28f31f39a59013eb8012a51f0 # v3.24.3 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12 + uses: github/codeql-action/analyze@379614612a29c9e28f31f39a59013eb8012a51f0 # v3.24.3 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index b1ada048858..a1b89d5ce97 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -50,7 +50,7 @@ jobs: extended: true - name: Setup Node - uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.1.0 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.1.0 with: node-version: '18' @@ -59,7 +59,7 @@ jobs: # Upload docs for GitHub Pages - name: Upload GitHub Pages artifact - uses: actions/upload-pages-artifact@0252fc4ba7626f0298f0cf00902a25c6afc77fa8 # v3.0.0 + uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1 with: # Path of the directory containing the static assets. path: site/public @@ -86,4 +86,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@7a9bd943aa5e5175aeb8502edcc6c1c02d398e10 # v4.0.2 + uses: actions/deploy-pages@decdde0ac072f6dcbe43649d82d9c635fff5b4e4 # v4.0.4 diff --git a/.github/workflows/experimental_conformance.yaml b/.github/workflows/experimental_conformance.yaml index e0d30b810c3..3a62c7ffdb8 100644 --- a/.github/workflows/experimental_conformance.yaml +++ b/.github/workflows/experimental_conformance.yaml @@ -32,7 +32,7 @@ jobs: run: make experimental-conformance - name: Upload Conformance Report - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: conformance-report-k8s-${{ matrix.version }} path: ./test/conformance/conformance-report-k8s-${{ matrix.version }}.yaml diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index e4946a3c678..5596fb78638 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -33,13 +33,13 @@ jobs: publish_results: true - name: "Upload artifact" - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: SARIF file path: results.sarif retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12 + uses: github/codeql-action/upload-sarif@379614612a29c9e28f31f39a59013eb8012a51f0 # v3.24.3 with: sarif_file: results.sarif diff --git a/OWNERS b/OWNERS index 4d581494fd7..8ca35470bb6 100644 --- a/OWNERS +++ b/OWNERS @@ -25,3 +25,5 @@ reviewers: - tanujd11 - cnvergence - shawnh2 +- guydc +- liorokman diff --git a/README.md b/README.md index dec6d31280f..0c8eb33a63b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Envoy Gateway -[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/envoyproxy/gateway/badge)](https://api.securityscorecards.dev/projects/github.com/envoyproxy/gateway) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/envoyproxy/gateway/badge)](https://securityscorecards.dev/viewer/?uri=github.com/envoyproxy/gateway) [![Build and Test](https://github.com/envoyproxy/gateway/actions/workflows/build_and_test.yaml/badge.svg)](https://github.com/envoyproxy/gateway/actions/workflows/build_and_test.yaml) [![codecov](https://codecov.io/gh/envoyproxy/gateway/branch/main/graph/badge.svg)](https://codecov.io/gh/envoyproxy/gateway) diff --git a/api/v1alpha1/backendtrafficpolicy_types.go b/api/v1alpha1/backendtrafficpolicy_types.go index ce8e6b93037..41325dc0991 100644 --- a/api/v1alpha1/backendtrafficpolicy_types.go +++ b/api/v1alpha1/backendtrafficpolicy_types.go @@ -22,7 +22,7 @@ const ( // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` // // BackendTrafficPolicy allows the user to configure the behavior of the connection -// between the downstream client and Envoy Proxy listener. +// between the Envoy Proxy listener and the backend service. type BackendTrafficPolicy struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` @@ -81,6 +81,21 @@ type BackendTrafficPolicySpec struct { // // +optional CircuitBreaker *CircuitBreaker `json:"circuitBreaker,omitempty"` + + // Retry provides more advanced usage, allowing users to customize the number of retries, retry fallback strategy, and retry triggering conditions. + // If not set, retry will be disabled. + // +optional + Retry *Retry `json:"retry,omitempty"` + + // Timeout settings for the backend connections. + // + // +optional + Timeout *Timeout `json:"timeout,omitempty"` + + // The compression config for the http streams. + // + // +optional + Compression []*Compression `json:"compression,omitempty"` } // BackendTrafficPolicyStatus defines the state of BackendTrafficPolicy diff --git a/api/v1alpha1/circuitbreaker_types.go b/api/v1alpha1/circuitbreaker_types.go index d045ae09517..33d394446e2 100644 --- a/api/v1alpha1/circuitbreaker_types.go +++ b/api/v1alpha1/circuitbreaker_types.go @@ -30,4 +30,12 @@ type CircuitBreaker struct { // +kubebuilder:default=1024 // +optional MaxParallelRequests *int64 `json:"maxParallelRequests,omitempty"` + + // The maximum number of requests that Envoy will make over a single connection to the referenced backend defined within a xRoute rule. + // Default: unlimited. + // + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=4294967295 + // +optional + MaxRequestsPerConnection *int64 `json:"maxRequestsPerConnection,omitempty"` } diff --git a/api/v1alpha1/clienttrafficpolicy_types.go b/api/v1alpha1/clienttrafficpolicy_types.go index 9ec283ce08d..3037e4b0c04 100644 --- a/api/v1alpha1/clienttrafficpolicy_types.go +++ b/api/v1alpha1/clienttrafficpolicy_types.go @@ -53,12 +53,6 @@ type ClientTrafficPolicySpec struct { // // +optional TCPKeepalive *TCPKeepalive `json:"tcpKeepalive,omitempty"` - // SuppressEnvoyHeaders configures the Envoy Router filter to suppress the "x-envoy-' - // headers from both requests and responses. - // By default these headers are added to both requests and responses. - // - // +optional - SuppressEnvoyHeaders *bool `json:"suppressEnvoyHeaders,omitempty"` // EnableProxyProtocol interprets the ProxyProtocol header and adds the // Client Address into the X-Forwarded-For header. // Note Proxy Protocol must be present when this field is set, else the connection @@ -66,6 +60,10 @@ type ClientTrafficPolicySpec struct { // // +optional EnableProxyProtocol *bool `json:"enableProxyProtocol,omitempty"` + // ClientIPDetectionSettings provides configuration for determining the original client IP address for requests. + // + // +optional + ClientIPDetection *ClientIPDetectionSettings `json:"clientIPDetection,omitempty"` // HTTP3 provides HTTP/3 configuration on the listener. // // +optional @@ -78,12 +76,105 @@ type ClientTrafficPolicySpec struct { // // +optional Path *PathSettings `json:"path,omitempty"` + // HTTP1 provides HTTP/1 configuration on the listener. + // + // +optional + HTTP1 *HTTP1Settings `json:"http1,omitempty"` + // HeaderSettings provides configuration for header management. + // + // +optional + Headers *HeaderSettings `json:"headers,omitempty"` + // Timeout settings for the client connections. + // + // +optional + Timeout *ClientTimeout `json:"timeout,omitempty"` +} + +// HeaderSettings providess configuration options for headers on the listener. +type HeaderSettings struct { + // EnableEnvoyHeaders configures Envoy Proxy to add the "X-Envoy-" headers to requests + // and responses. + // +optional + EnableEnvoyHeaders *bool `json:"enableEnvoyHeaders,omitempty"` +} + +// ClientIPDetectionSettings provides configuration for determining the original client IP address for requests. +// +// +kubebuilder:validation:XValidation:rule="!(has(self.xForwardedFor) && has(self.customHeader))",message="customHeader cannot be used in conjunction with xForwardedFor" +type ClientIPDetectionSettings struct { + // XForwardedForSettings provides configuration for using X-Forwarded-For headers for determining the client IP address. + // + // +optional + XForwardedFor *XForwardedForSettings `json:"xForwardedFor,omitempty"` + // CustomHeader provides configuration for determining the client IP address for a request based on + // a trusted custom HTTP header. This uses the the custom_header original IP detection extension. + // Refer to https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/http/original_ip_detection/custom_header/v3/custom_header.proto + // for more details. + // + // +optional + CustomHeader *CustomHeaderExtensionSettings `json:"customHeader,omitempty"` +} + +// XForwardedForSettings provides configuration for using X-Forwarded-For headers for determining the client IP address. +type XForwardedForSettings struct { + // NumTrustedHops controls the number of additional ingress proxy hops from the right side of XFF HTTP + // headers to trust when determining the origin client's IP address. + // Refer to https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers#x-forwarded-for + // for more details. + // + // +optional + NumTrustedHops *uint32 `json:"numTrustedHops,omitempty"` +} + +// CustomHeader provides configuration for determining the client IP address for a request based on +// a trusted custom HTTP header. This uses the the custom_header original IP detection extension. +// Refer to https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/http/original_ip_detection/custom_header/v3/custom_header.proto +// for more details. +type CustomHeaderExtensionSettings struct { + // Name of the header containing the original downstream remote address, if present. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=255 + // +kubebuilder:validation:Pattern="^[A-Za-z0-9-]+$" + // + Name string `json:"name"` + // FailClosed is a switch used to control the flow of traffic when client IP detection + // fails. If set to true, the listener will respond with 403 Forbidden when the client + // IP address cannot be determined. + // + // +optional + FailClosed *bool `json:"failClosed,omitempty"` } // HTTP3Settings provides HTTP/3 configuration on the listener. type HTTP3Settings struct { } +// HTTP1Settings provides HTTP/1 configuration on the listener. +type HTTP1Settings struct { + // EnableTrailers defines if HTTP/1 trailers should be proxied by Envoy. + // +optional + EnableTrailers *bool `json:"enableTrailers,omitempty"` + // PreserveHeaderCase defines if Envoy should preserve the letter case of headers. + // By default, Envoy will lowercase all the headers. + // +optional + PreserveHeaderCase *bool `json:"preserveHeaderCase,omitempty"` + // HTTP10 turns on support for HTTP/1.0 and HTTP/0.9 requests. + // +optional + HTTP10 *HTTP10Settings `json:"http10,omitempty"` +} + +// HTTP10Settings provides HTTP/1.0 configuration on the listener. +type HTTP10Settings struct { + // UseDefaultHost defines if the HTTP/1.0 request is missing the Host header, + // then the hostname associated with the listener should be injected into the + // request. + // If this is not set and an HTTP/1.0 request arrives without a host, then + // it will be rejected. + // +optional + UseDefaultHost *bool `json:"useDefaultHost,omitempty"` +} + // ClientTrafficPolicyStatus defines the state of ClientTrafficPolicy type ClientTrafficPolicyStatus struct { // Conditions describe the current conditions of the ClientTrafficPolicy. diff --git a/api/v1alpha1/compression_types.go b/api/v1alpha1/compression_types.go new file mode 100644 index 00000000000..37c0ec8587b --- /dev/null +++ b/api/v1alpha1/compression_types.go @@ -0,0 +1,31 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package v1alpha1 + +// CompressorType defines the types of compressor library supported by Envoy Gateway. +// +// +kubebuilder:validation:Enum=Gzip +type CompressorType string + +// GzipCompressor defines the config for the Gzip compressor. +// The default values can be found here: +// https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/compression/gzip/compressor/v3/gzip.proto#extension-envoy-compression-gzip-compressor +type GzipCompressor struct { +} + +// Compression defines the config of enabling compression. +// This can help reduce the bandwidth at the expense of higher CPU. +type Compression struct { + // CompressorType defines the compressor type to use for compression. + // + // +required + Type CompressorType `json:"type"` + + // The configuration for GZIP compressor. + // + // +optional + Gzip *GzipCompressor `json:"gzip,omitempty"` +} diff --git a/api/v1alpha1/cors_types.go b/api/v1alpha1/cors_types.go index 6188978b206..2c2fb50f681 100644 --- a/api/v1alpha1/cors_types.go +++ b/api/v1alpha1/cors_types.go @@ -8,19 +8,22 @@ package v1alpha1 import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // Origin is defined by the scheme (protocol), hostname (domain), and port of -// the URL used to access it. The hostname can be “precise” which is just the -// domain name or “wildcard” which is a domain name prefixed with a single -// wildcard label such as “*.example.com”. +// the URL used to access it. The hostname can be "precise" which is just the +// domain name or "wildcard" which is a domain name prefixed with a single +// wildcard label such as "*.example.com". +// In addition to that a single wildcard (with or without scheme) can be +// configured to match any origin. // // For example, the following are valid origins: // - https://foo.example.com // - https://*.example.com // - http://foo.example.com:8080 // - http://*.example.com:8080 +// - https://* // // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 -// +kubebuilder:validation:Pattern=`^https?:\/\/(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*(:[0-9]+)?$` +// +kubebuilder:validation:Pattern=`^(\*|https?:\/\/(\*|(\*\.)?(([\w-]+\.?)+)?[\w-]+)(:\d{1,5})?)$` type Origin string // CORS defines the configuration for Cross-Origin Resource Sharing (CORS). diff --git a/api/v1alpha1/envoygateway_types.go b/api/v1alpha1/envoygateway_types.go index 66abfdec9c8..881b4d36443 100644 --- a/api/v1alpha1/envoygateway_types.go +++ b/api/v1alpha1/envoygateway_types.go @@ -200,9 +200,9 @@ const ( // KubernetesWatchModeTypeNamespaces indicates that the namespace watch mode is used. KubernetesWatchModeTypeNamespaces = "Namespaces" - // KubernetesWatchModeTypeNamespaceSelectors indicates that namespaceSelectors watch + // KubernetesWatchModeTypeNamespaceSelector indicates that namespaceSelector watch // mode is used. - KubernetesWatchModeTypeNamespaceSelectors = "NamespaceSelectors" + KubernetesWatchModeTypeNamespaceSelector = "NamespaceSelector" ) // KubernetesWatchModeType defines the type of KubernetesWatchMode @@ -211,7 +211,7 @@ type KubernetesWatchModeType string // KubernetesWatchMode holds the configuration for which input resources to watch and reconcile. type KubernetesWatchMode struct { // Type indicates what watch mode to use. KubernetesWatchModeTypeNamespaces and - // KubernetesWatchModeTypeNamespaceSelectors are currently supported + // KubernetesWatchModeTypeNamespaceSelector are currently supported // By default, when this field is unset or empty, Envoy Gateway will watch for input namespaced resources // from all namespaces. Type KubernetesWatchModeType `json:"type,omitempty"` @@ -219,14 +219,13 @@ type KubernetesWatchMode struct { // Namespaces holds the list of namespaces that Envoy Gateway will watch for namespaced scoped // resources such as Gateway, HTTPRoute and Service. // Note that Envoy Gateway will continue to reconcile relevant cluster scoped resources such as - // GatewayClass that it is linked to. Precisely one of Namespaces and NamespaceSelectors must be set + // GatewayClass that it is linked to. Precisely one of Namespaces and NamespaceSelector must be set. Namespaces []string `json:"namespaces,omitempty"` - // NamespaceSelectors holds a list of labels that namespaces have to have in order to be watched. - // Note this doesn't set the informer to watch the namespaces with the given labels. Informer still - // watches all namespaces. But the events for objects whois namespce have no given labels - // will be filtered out. Precisely one of Namespaces and NamespaceSelectors must be set - NamespaceSelectors []string `json:"namespaceSelectors,omitempty"` + // NamespaceSelector holds the label selector used to dynamically select namespaces. + // Envoy Gateway will watch for namespaces matching the specified label selector. + // Precisely one of Namespaces and NamespaceSelector must be set. + NamespaceSelector *metav1.LabelSelector `json:"namespaceSelector,omitempty"` } // KubernetesDeployMode holds configuration for how to deploy managed resources such as the Envoy Proxy diff --git a/api/v1alpha1/envoypatchpolicy_types.go b/api/v1alpha1/envoypatchpolicy_types.go index 1ac40697d66..d9d45ec8f44 100644 --- a/api/v1alpha1/envoypatchpolicy_types.go +++ b/api/v1alpha1/envoypatchpolicy_types.go @@ -86,7 +86,7 @@ type EnvoyJSONPatchConfig struct { } // EnvoyResourceType specifies the type URL of the Envoy resource. -// +kubebuilder:validation:Enum=type.googleapis.com/envoy.config.listener.v3.Listener;type.googleapis.com/envoy.config.route.v3.RouteConfiguration;type.googleapis.com/envoy.config.cluster.v3.Cluster;type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment +// +kubebuilder:validation:Enum=type.googleapis.com/envoy.config.listener.v3.Listener;type.googleapis.com/envoy.config.route.v3.RouteConfiguration;type.googleapis.com/envoy.config.cluster.v3.Cluster;type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment;type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret type EnvoyResourceType string const ( @@ -112,8 +112,15 @@ type JSONPatchOperation struct { // Path is the location of the target document/field where the operation will be performed // Refer to https://datatracker.ietf.org/doc/html/rfc6901 for more details. Path string `json:"path"` - // Value is the new value of the path location. - Value apiextensionsv1.JSON `json:"value"` + // From is the source location of the value to be copied or moved. Only valid + // for move or copy operations + // Refer to https://datatracker.ietf.org/doc/html/rfc6901 for more details. + // +optional + From *string `json:"from,omitempty"` + // Value is the new value of the path location. The value is only used by + // the `add` and `replace` operations. + // +optional + Value *apiextensionsv1.JSON `json:"value,omitempty"` } // EnvoyPatchPolicyStatus defines the state of EnvoyPatchPolicy @@ -153,6 +160,10 @@ const ( // PolicyReasonTargetNotFound is used with the "Programmed" condition when the // policy cannot find the resource type to patch to. PolicyReasonResourceNotFound gwapiv1a2.PolicyConditionReason = "ResourceNotFound" + + // PolicyReasonDisabled is used with the "Accepted" condition when the policy + // feature is disabled by the configuration. + PolicyReasonDisabled gwapiv1a2.PolicyConditionReason = "Disabled" ) //+kubebuilder:object:root=true diff --git a/api/v1alpha1/envoyproxy_types.go b/api/v1alpha1/envoyproxy_types.go index e11da79d850..6f971644f5d 100644 --- a/api/v1alpha1/envoyproxy_types.go +++ b/api/v1alpha1/envoyproxy_types.go @@ -67,6 +67,13 @@ type EnvoyProxySpec struct { // +optional Concurrency *int32 `json:"concurrency,omitempty"` + // ExtraArgs defines additional command line options that are provided to Envoy. + // More info: https://www.envoyproxy.io/docs/envoy/latest/operations/cli#command-line-options + // Note: some command line options are used internally(e.g. --log-level) so they cannot be provided here. + // + // +optional + ExtraArgs []string `json:"extraArgs,omitempty"` + // MergeGateways defines if Gateway resources should be merged onto the same Envoy Proxy Infrastructure. // Setting this field to true would merge all Gateway Listeners under the parent Gateway Class. // This means that the port, protocol and hostname tuple must be unique for every listener. @@ -123,18 +130,12 @@ type EnvoyProxyKubernetesProvider struct { // are applied. // // +optional - // +kubebuilder:validation:XValidation:message="allocateLoadBalancerNodePorts can only be set for LoadBalancer type",rule="!has(self.allocateLoadBalancerNodePorts) || self.type == 'LoadBalancer'" - // +kubebuilder:validation:XValidation:message="loadBalancerIP can only be set for LoadBalancer type",rule="!has(self.loadBalancerIP) || self.type == 'LoadBalancer'" - // +kubebuilder:validation:XValidation:message="loadBalancerIP must be a valid IPv4 address",rule="!has(self.loadBalancerIP) || self.loadBalancerIP.matches(r\"^(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.|$)){4})\")" EnvoyService *KubernetesServiceSpec `json:"envoyService,omitempty"` // EnvoyHpa defines the Horizontal Pod Autoscaler settings for Envoy Proxy Deployment. // Once the HPA is being set, Replicas field from EnvoyDeployment will be ignored. // // +optional - // +kubebuilder:validation:XValidation:message="minReplicas must be greater than 0",rule="!has(self.minReplicas) || self.minReplicas > 0" - // +kubebuilder:validation:XValidation:message="maxReplicas must be greater than 0",rule="!has(self.maxReplicas) || self.maxReplicas > 0" - // +kubebuilder:validation:XValidation:message="maxReplicas cannot be less than minReplicas",rule="!has(self.minReplicas) || self.maxReplicas >= self.minReplicas" EnvoyHpa *KubernetesHorizontalPodAutoscalerSpec `json:"envoyHpa,omitempty"` } diff --git a/api/v1alpha1/ext_auth_types.go b/api/v1alpha1/ext_auth_types.go new file mode 100644 index 00000000000..25d28a91003 --- /dev/null +++ b/api/v1alpha1/ext_auth_types.go @@ -0,0 +1,74 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package v1alpha1 + +import ( + gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" +) + +// +kubebuilder:validation:XValidation:rule="(has(self.grpc) || has(self.http))",message="one of grpc or http must be specified" +// +kubebuilder:validation:XValidation:rule="(has(self.grpc) && !has(self.http)) || (!has(self.grpc) && has(self.http))",message="only one of grpc or http can be specified" +// +kubebuilder:validation:XValidation:rule="has(self.grpc) ? (!has(self.grpc.backendRef.group) || self.grpc.backendRef.group == \"\") : true", message="group is invalid, only the core API group (specified by omitting the group field or setting it to an empty string) is supported" +// +kubebuilder:validation:XValidation:rule="has(self.grpc) ? (!has(self.grpc.backendRef.kind) || self.grpc.backendRef.kind == 'Service') : true", message="kind is invalid, only Service (specified by omitting the kind field or setting it to 'Service') is supported" +// +kubebuilder:validation:XValidation:rule="has(self.http) ? (!has(self.http.backendRef.group) || self.http.backendRef.group == \"\") : true", message="group is invalid, only the core API group (specified by omitting the group field or setting it to an empty string) is supported" +// +kubebuilder:validation:XValidation:rule="has(self.http) ? (!has(self.http.backendRef.kind) || self.http.backendRef.kind == 'Service') : true", message="kind is invalid, only Service (specified by omitting the kind field or setting it to 'Service') is supported" +// +// ExtAuth defines the configuration for External Authorization. +type ExtAuth struct { + // GRPC defines the gRPC External Authorization service. + // Either GRPCService or HTTPService must be specified, + // and only one of them can be provided. + GRPC *GRPCExtAuthService `json:"grpc,omitempty"` + + // HTTP defines the HTTP External Authorization service. + // Either GRPCService or HTTPService must be specified, + // and only one of them can be provided. + HTTP *HTTPExtAuthService `json:"http,omitempty"` + + // HeadersToExtAuth defines the client request headers that will be included + // in the request to the external authorization service. + // Note: If not specified, the default behavior for gRPC and HTTP external + // authorization services is different due to backward compatibility reasons. + // All headers will be included in the check request to a gRPC authorization server. + // Only the following headers will be included in the check request to an HTTP + // authorization server: Host, Method, Path, Content-Length, and Authorization. + // And these headers will always be included to the check request to an HTTP + // authorization server by default, no matter whether they are specified + // in HeadersToExtAuth or not. + // +optional + HeadersToExtAuth []string `json:"headersToExtAuth,omitempty"` +} + +// GRPCExtAuthService defines the gRPC External Authorization service +// The authorization request message is defined in +// https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto +type GRPCExtAuthService struct { + // BackendRef references a Kubernetes object that represents the + // backend server to which the authorization request will be sent. + // Only service Kind is supported for now. + BackendRef gwapiv1.BackendObjectReference `json:"backendRef"` +} + +// HTTPExtAuthService defines the HTTP External Authorization service +type HTTPExtAuthService struct { + // BackendRef references a Kubernetes object that represents the + // backend server to which the authorization request will be sent. + // Only service Kind is supported for now. + BackendRef gwapiv1.BackendObjectReference `json:"backendRef"` + + // Path is the path of the HTTP External Authorization service. + // If path is specified, the authorization request will be sent to that path, + // or else the authorization request will be sent to the root path. + Path *string `json:"path,omitempty"` + + // HeadersToBackend are the authorization response headers that will be added + // to the original client request before sending it to the backend server. + // Note that coexisting headers will be overridden. + // If not specified, no authorization response headers will be added to the + // original client request. + // +optional + HeadersToBackend []string `json:"headersToBackend,omitempty"` +} diff --git a/api/v1alpha1/healthcheck_types.go b/api/v1alpha1/healthcheck_types.go index a308c7d5719..61172273e3d 100644 --- a/api/v1alpha1/healthcheck_types.go +++ b/api/v1alpha1/healthcheck_types.go @@ -7,13 +7,75 @@ package v1alpha1 import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -// HealthCheck defines the health check configuration. -// EG supports various types of health checking including HTTP, TCP. +// HealthCheck configuration to decide which endpoints +// are healthy and can be used for routing. +type HealthCheck struct { + // Active health check configuration + // +optional + Active *ActiveHealthCheck `json:"active,omitempty"` + + // Passive passive check configuration + // +optional + Passive *PassiveHealthCheck `json:"passive,omitempty"` +} + +// PassiveHealthCheck defines the configuration for passive health checks in the context of Envoy's Outlier Detection, +// see https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/outlier +type PassiveHealthCheck struct { + + // SplitExternalLocalOriginErrors enables splitting of errors between external and local origin. + // + // +kubebuilder:default=false + // +optional + SplitExternalLocalOriginErrors *bool `json:"splitExternalLocalOriginErrors,omitempty"` + + // Interval defines the time between passive health checks. + // + // +kubebuilder:validation:Format=duration + // +kubebuilder:default="3s" + // +optional + Interval *metav1.Duration `json:"interval,omitempty"` + + // ConsecutiveLocalOriginFailures sets the number of consecutive local origin failures triggering ejection. + // Parameter takes effect only when split_external_local_origin_errors is set to true. + // + // +kubebuilder:default=5 + // +optional + ConsecutiveLocalOriginFailures *uint32 `json:"consecutiveLocalOriginFailures,omitempty"` + + // ConsecutiveGatewayErrors sets the number of consecutive gateway errors triggering ejection. + // + // +kubebuilder:default=0 + // +optional + ConsecutiveGatewayErrors *uint32 `json:"consecutiveGatewayErrors,omitempty"` + + // Consecutive5xxErrors sets the number of consecutive 5xx errors triggering ejection. + // + // +kubebuilder:default=5 + // +optional + Consecutive5xxErrors *uint32 `json:"consecutive5XxErrors,omitempty"` + + // BaseEjectionTime defines the base duration for which a host will be ejected on consecutive failures. + // + // +kubebuilder:validation:Format=duration + // +kubebuilder:default="30s" + // +optional + BaseEjectionTime *metav1.Duration `json:"baseEjectionTime,omitempty"` + + // MaxEjectionPercent sets the maximum percentage of hosts in a cluster that can be ejected. + // + // +kubebuilder:default=10 + // +optional + MaxEjectionPercent *int32 `json:"maxEjectionPercent,omitempty"` +} + +// ActiveHealthCheck defines the active health check configuration. +// EG supports various types of active health checking including HTTP, TCP. // +union // // +kubebuilder:validation:XValidation:rule="self.type == 'HTTP' ? has(self.http) : !has(self.http)",message="If Health Checker type is HTTP, http field needs to be set." // +kubebuilder:validation:XValidation:rule="self.type == 'TCP' ? has(self.tcp) : !has(self.tcp)",message="If Health Checker type is TCP, tcp field needs to be set." -type HealthCheck struct { +type ActiveHealthCheck struct { // Timeout defines the time to wait for a health check response. // // +kubebuilder:validation:Format=duration @@ -21,7 +83,7 @@ type HealthCheck struct { // +optional Timeout *metav1.Duration `json:"timeout"` - // Interval defines the time between health checks. + // Interval defines the time between active health checks. // // +kubebuilder:validation:Format=duration // +kubebuilder:default="3s" @@ -45,32 +107,32 @@ type HealthCheck struct { // Type defines the type of health checker. // +kubebuilder:validation:Enum=HTTP;TCP // +unionDiscriminator - Type HealthCheckerType `json:"type" yaml:"type"` + Type ActiveHealthCheckerType `json:"type" yaml:"type"` // HTTP defines the configuration of http health checker. // It's required while the health checker type is HTTP. // +optional - HTTP *HTTPHealthChecker `json:"http,omitempty" yaml:"http,omitempty"` + HTTP *HTTPActiveHealthChecker `json:"http,omitempty" yaml:"http,omitempty"` // TCP defines the configuration of tcp health checker. // It's required while the health checker type is TCP. // +optional - TCP *TCPHealthChecker `json:"tcp,omitempty" yaml:"tcp,omitempty"` + TCP *TCPActiveHealthChecker `json:"tcp,omitempty" yaml:"tcp,omitempty"` } -// HealthCheckerType is the type of health checker. +// ActiveHealthCheckerType is the type of health checker. // +kubebuilder:validation:Enum=HTTP;TCP -type HealthCheckerType string +type ActiveHealthCheckerType string const ( - // HealthCheckerTypeHTTP defines the HTTP type of health checking. - HealthCheckerTypeHTTP HealthCheckerType = "HTTP" - // HealthCheckerTypeTCP defines the TCP type of health checking. - HealthCheckerTypeTCP HealthCheckerType = "TCP" + // ActiveHealthCheckerTypeHTTP defines the HTTP type of health checking. + ActiveHealthCheckerTypeHTTP ActiveHealthCheckerType = "HTTP" + // ActiveHealthCheckerTypeTCP defines the TCP type of health checking. + ActiveHealthCheckerTypeTCP ActiveHealthCheckerType = "TCP" ) -// HTTPHealthChecker defines the settings of http health check. -type HTTPHealthChecker struct { +// HTTPActiveHealthChecker defines the settings of http health check. +type HTTPActiveHealthChecker struct { // Path defines the HTTP path that will be requested during health checking. // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=1024 @@ -85,45 +147,39 @@ type HTTPHealthChecker struct { ExpectedStatuses []HTTPStatus `json:"expectedStatuses,omitempty" yaml:"expectedStatuses,omitempty"` // ExpectedResponse defines a list of HTTP expected responses to match. // +optional - ExpectedResponse *HealthCheckPayload `json:"expectedResponse,omitempty" yaml:"expectedResponse,omitempty"` + ExpectedResponse *ActiveHealthCheckPayload `json:"expectedResponse,omitempty" yaml:"expectedResponse,omitempty"` } -// TCPHealthChecker defines the settings of tcp health check. -type TCPHealthChecker struct { +// TCPActiveHealthChecker defines the settings of tcp health check. +type TCPActiveHealthChecker struct { // Send defines the request payload. // +optional - Send *HealthCheckPayload `json:"send,omitempty" yaml:"send,omitempty"` + Send *ActiveHealthCheckPayload `json:"send,omitempty" yaml:"send,omitempty"` // Receive defines the expected response payload. // +optional - Receive *HealthCheckPayload `json:"receive,omitempty" yaml:"receive,omitempty"` + Receive *ActiveHealthCheckPayload `json:"receive,omitempty" yaml:"receive,omitempty"` } -// HTTPStatus defines the http status code. -// +kubebuilder:validation:Minimum=100 -// +kubebuilder:validation:Maximum=600 -// +kubebuilder:validation:ExclusiveMaximum=true -type HTTPStatus int - -// HealthCheckPayloadType is the type of the payload. +// ActiveHealthCheckPayloadType is the type of the payload. // +kubebuilder:validation:Enum=Text;Binary -type HealthCheckPayloadType string +type ActiveHealthCheckPayloadType string const ( - // HealthCheckPayloadTypeText defines the Text type payload. - HealthCheckPayloadTypeText HealthCheckPayloadType = "Text" - // HealthCheckPayloadTypeBinary defines the Binary type payload. - HealthCheckPayloadTypeBinary HealthCheckPayloadType = "Binary" + // ActiveHealthCheckPayloadTypeText defines the Text type payload. + ActiveHealthCheckPayloadTypeText ActiveHealthCheckPayloadType = "Text" + // ActiveHealthCheckPayloadTypeBinary defines the Binary type payload. + ActiveHealthCheckPayloadTypeBinary ActiveHealthCheckPayloadType = "Binary" ) -// HealthCheckPayload defines the encoding of the payload bytes in the payload. +// ActiveHealthCheckPayload defines the encoding of the payload bytes in the payload. // +union // +kubebuilder:validation:XValidation:rule="self.type == 'Text' ? has(self.text) : !has(self.text)",message="If payload type is Text, text field needs to be set." // +kubebuilder:validation:XValidation:rule="self.type == 'Binary' ? has(self.binary) : !has(self.binary)",message="If payload type is Binary, binary field needs to be set." -type HealthCheckPayload struct { +type ActiveHealthCheckPayload struct { // Type defines the type of the payload. // +kubebuilder:validation:Enum=Text;Binary // +unionDiscriminator - Type HealthCheckPayloadType `json:"type" yaml:"type"` + Type ActiveHealthCheckPayloadType `json:"type" yaml:"type"` // Text payload in plain text. // +optional Text *string `json:"text,omitempty" yaml:"text,omitempty"` diff --git a/api/v1alpha1/jwt_types.go b/api/v1alpha1/jwt_types.go index 6700d28b854..43e22274338 100644 --- a/api/v1alpha1/jwt_types.go +++ b/api/v1alpha1/jwt_types.go @@ -88,10 +88,36 @@ type ClaimToHeader struct { } // JWTExtractor defines a custom JWT token extraction from HTTP request. +// If specified, Envoy will extract the JWT token from the listed extractors (headers, cookies, or params) and validate each of them. +// If any value extracted is found to be an invalid JWT, a 401 error will be returned. type JWTExtractor struct { + // Headers represents a list of HTTP request headers to extract the JWT token from. + // + // +optional + Headers []JWTHeaderExtractor `json:"headers,omitempty"` + // Cookies represents a list of cookie names to extract the JWT token from. - // If specified, Envoy will extract the JWT token from the listed cookies and validate each of them. - // If any cookie is found to be an invalid JWT, a 401 error will be returned. // + // +optional Cookies []string `json:"cookies,omitempty"` + + // Params represents a list of query parameters to extract the JWT token from. + // + // +optional + Params []string `json:"params,omitempty"` +} + +// JWTHeaderExtractor defines an HTTP header location to extract JWT token +type JWTHeaderExtractor struct { + // Name is the HTTP header name to retrieve the token + // + // +kubebuilder:validation:Required + Name string `json:"name"` + + // ValuePrefix is the prefix that should be stripped before extracting the token. + // The format would be used by Envoy like "{ValuePrefix}". + // For example, "Authorization: Bearer ", then the ValuePrefix="Bearer " with a space at the end. + // + // +optional + ValuePrefix *string `json:"valuePrefix,omitempty"` } diff --git a/api/v1alpha1/retry_types.go b/api/v1alpha1/retry_types.go new file mode 100644 index 00000000000..1752806e830 --- /dev/null +++ b/api/v1alpha1/retry_types.go @@ -0,0 +1,111 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// Retry defines the retry strategy to be applied. +type Retry struct { + // NumRetries is the number of retries to be attempted. Defaults to 2. + // + // +optional + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:default=2 + NumRetries *int32 `json:"numRetries,omitempty"` + + // RetryOn specifies the retry trigger condition. + // + // If not specified, the default is to retry on connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes(503). + // +optional + RetryOn *RetryOn `json:"retryOn,omitempty"` + + // PerRetry is the retry policy to be applied per retry attempt. + // + // +optional + PerRetry *PerRetryPolicy `json:"perRetry,omitempty"` +} + +type RetryOn struct { + // Triggers specifies the retry trigger condition(Http/Grpc). + // + // +optional + Triggers []TriggerEnum `json:"triggers,omitempty"` + + // HttpStatusCodes specifies the http status codes to be retried. + // + // +optional + HTTPStatusCodes []HTTPStatus `json:"httpStatusCodes,omitempty"` +} + +// TriggerEnum specifies the conditions that trigger retries. +// +kubebuilder:validation:Enum={"5xx","gateway-error","disconnect-reset","connect-failure","retriable-4xx","refused-stream","retriable-status-codes","cancelled","deadline-exceeded","internal","resource-exhausted","unavailable"} +type TriggerEnum string + +const ( + // HTTP events. + // For additional details, see https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/router_filter#x-envoy-retry-on + + // The upstream server responds with any 5xx response code, or does not respond at all (disconnect/reset/read timeout). + // Includes connect-failure and refused-stream. + Error5XX TriggerEnum = "5xx" + // The response is a gateway error (502,503 or 504). + GatewayError TriggerEnum = "gateway-error" + // The upstream server does not respond at all (disconnect/reset/read timeout.) + DisconnectRest TriggerEnum = "disconnect-reset" + // Connection failure to the upstream server (connect timeout, etc.). (Included in *5xx*) + ConnectFailure TriggerEnum = "connect-failure" + // The upstream server responds with a retriable 4xx response code. + // Currently, the only response code in this category is 409. + Retriable4XX TriggerEnum = "retriable-4xx" + // The upstream server resets the stream with a REFUSED_STREAM error code. + RefusedStream TriggerEnum = "refused-stream" + // The upstream server responds with any response code matching one defined in the RetriableStatusCodes. + RetriableStatusCodes TriggerEnum = "retriable-status-codes" + + // GRPC events, currently only supported for gRPC status codes in response headers. + // For additional details, see https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/router_filter#x-envoy-retry-grpc-on + + // The gRPC status code in the response headers is “cancelled”. + Cancelled TriggerEnum = "cancelled" + // The gRPC status code in the response headers is “deadline-exceeded”. + DeadlineExceeded TriggerEnum = "deadline-exceeded" + // The gRPC status code in the response headers is “internal”. + Internal TriggerEnum = "internal" + // The gRPC status code in the response headers is “resource-exhausted”. + ResourceExhausted TriggerEnum = "resource-exhausted" + // The gRPC status code in the response headers is “unavailable”. + Unavailable TriggerEnum = "unavailable" +) + +type PerRetryPolicy struct { + // Timeout is the timeout per retry attempt. + // + // +optional + // +kubebuilder:validation:Format=duration + Timeout *metav1.Duration `json:"timeout,omitempty"` + // Backoff is the backoff policy to be applied per retry attempt. gateway uses a fully jittered exponential + // back-off algorithm for retries. For additional details, + // see https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/router_filter#config-http-filters-router-x-envoy-max-retries + // + // +optional + BackOff *BackOffPolicy `json:"backOff,omitempty"` +} + +type BackOffPolicy struct { + // BaseInterval is the base interval between retries. + // + // +kubebuilder:validation:Format=duration + BaseInterval *metav1.Duration `json:"baseInterval,omitempty"` + // MaxInterval is the maximum interval between retries. This parameter is optional, but must be greater than or equal to the base_interval if set. + // The default is 10 times the base_interval + // + // +optional + // +kubebuilder:validation:Format=duration + MaxInterval *metav1.Duration `json:"maxInterval,omitempty"` + // we can add rate limited based backoff config here if we want to. +} diff --git a/api/v1alpha1/securitypolicy_types.go b/api/v1alpha1/securitypolicy_types.go index ab6bc313088..6d90536ae91 100644 --- a/api/v1alpha1/securitypolicy_types.go +++ b/api/v1alpha1/securitypolicy_types.go @@ -44,7 +44,6 @@ type SecurityPolicySpec struct { // is being attached to. // This Policy and the TargetRef MUST be in the same namespace // for this Policy to have effect and be applied to the Gateway. - // TargetRef TargetRef gwapiv1a2.PolicyTargetReferenceWithSectionName `json:"targetRef"` // CORS defines the configuration for Cross-Origin Resource Sharing (CORS). @@ -66,6 +65,11 @@ type SecurityPolicySpec struct { // // +optional OIDC *OIDC `json:"oidc,omitempty"` + + // ExtAuth defines the configuration for External Authorization. + // + // +optional + ExtAuth *ExtAuth `json:"extAuth,omitempty"` } // SecurityPolicyStatus defines the state of SecurityPolicy diff --git a/api/v1alpha1/shared_types.go b/api/v1alpha1/shared_types.go index a75f7af43cd..970c62ba6a1 100644 --- a/api/v1alpha1/shared_types.go +++ b/api/v1alpha1/shared_types.go @@ -19,7 +19,7 @@ const ( // DefaultDeploymentMemoryResourceRequests for deployment memory resource DefaultDeploymentMemoryResourceRequests = "512Mi" // DefaultEnvoyProxyImage is the default image used by envoyproxy - DefaultEnvoyProxyImage = "envoyproxy/envoy-dev:latest" + DefaultEnvoyProxyImage = "envoyproxy/envoy:distroless-dev" // DefaultRateLimitImage is the default image used by ratelimit. DefaultRateLimitImage = "envoyproxy/ratelimit:master" // HTTPProtocol is the common-used http protocol. @@ -210,6 +210,8 @@ const ( ) // KubernetesServiceSpec defines the desired state of the Kubernetes service resource. +// +kubebuilder:validation:XValidation:message="allocateLoadBalancerNodePorts can only be set for LoadBalancer type",rule="!has(self.allocateLoadBalancerNodePorts) || self.type == 'LoadBalancer'" +// +kubebuilder:validation:XValidation:message="loadBalancerIP can only be set for LoadBalancer type",rule="!has(self.loadBalancerIP) || self.type == 'LoadBalancer'" type KubernetesServiceSpec struct { // Annotations that should be appended to the service. // By default, no annotations are appended. @@ -243,6 +245,8 @@ type KubernetesServiceSpec struct { // may be ignored if the load balancer provider does not support this feature. // This field has been deprecated in Kubernetes, but it is still used for setting the IP Address in some cloud // providers such as GCP. + // + // +kubebuilder:validation:XValidation:message="loadBalancerIP must be a valid IPv4 address",rule="self.matches(r\"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$\")" // +optional LoadBalancerIP *string `json:"loadBalancerIP,omitempty"` @@ -328,16 +332,20 @@ const ( // KubernetesHorizontalPodAutoscalerSpec defines Kubernetes Horizontal Pod Autoscaler settings of Envoy Proxy Deployment. // See k8s.io.autoscaling.v2.HorizontalPodAutoScalerSpec. +// +// +kubebuilder:validation:XValidation:message="maxReplicas cannot be less than minReplicas",rule="!has(self.minReplicas) || self.maxReplicas >= self.minReplicas" type KubernetesHorizontalPodAutoscalerSpec struct { // minReplicas is the lower limit for the number of replicas to which the autoscaler // can scale down. It defaults to 1 replica. // + // +kubebuilder:validation:XValidation:message="minReplicas must be greater than 0",rule="self > 0" // +optional MinReplicas *int32 `json:"minReplicas,omitempty"` // maxReplicas is the upper limit for the number of replicas to which the autoscaler can scale up. // It cannot be less that minReplicas. // + // +kubebuilder:validation:XValidation:message="maxReplicas must be greater than 0",rule="self > 0" MaxReplicas *int32 `json:"maxReplicas"` // metrics contains the specifications for which to use to calculate the @@ -356,3 +364,9 @@ type KubernetesHorizontalPodAutoscalerSpec struct { // +optional Behavior *autoscalingv2.HorizontalPodAutoscalerBehavior `json:"behavior,omitempty"` } + +// HTTPStatus defines the http status code. +// +kubebuilder:validation:Minimum=100 +// +kubebuilder:validation:Maximum=600 +// +kubebuilder:validation:ExclusiveMaximum=true +type HTTPStatus int diff --git a/api/v1alpha1/timeout_types.go b/api/v1alpha1/timeout_types.go new file mode 100644 index 00000000000..78289c968fa --- /dev/null +++ b/api/v1alpha1/timeout_types.go @@ -0,0 +1,58 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package v1alpha1 + +import gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" + +// Timeout defines configuration for timeouts related to connections. +type Timeout struct { + // Timeout settings for TCP. + // + // +optional + TCP *TCPTimeout `json:"tcp,omitempty"` + + // Timeout settings for HTTP. + // + // +optional + HTTP *HTTPTimeout `json:"http,omitempty"` +} + +type TCPTimeout struct { + // The timeout for network connection establishment, including TCP and TLS handshakes. + // Default: 10 seconds. + // + // +optional + ConnectTimeout *gwapiv1.Duration `json:"connectTimeout,omitempty"` +} + +type HTTPTimeout struct { + // The idle timeout for an HTTP connection. Idle time is defined as a period in which there are no active requests in the connection. + // Default: 1 hour. + // + // +optional + ConnectionIdleTimeout *gwapiv1.Duration `json:"connectionIdleTimeout,omitempty"` + + // The maximum duration of an HTTP connection. + // Default: unlimited. + // + // +optional + MaxConnectionDuration *gwapiv1.Duration `json:"maxConnectionDuration,omitempty"` +} + +type ClientTimeout struct { + // Timeout settings for HTTP. + // + // +optional + HTTP *HTTPClientTimeout `json:"http,omitempty"` +} + +type HTTPClientTimeout struct { + // The duration envoy waits for the complete request reception. This timer starts upon request + // initiation and stops when either the last byte of the request is sent upstream or when the response begins. + // + // +optional + RequestReceivedTimeout *gwapiv1.Duration `json:"requestReceivedTimeout,omitempty"` +} diff --git a/api/v1alpha1/tls_types.go b/api/v1alpha1/tls_types.go index 250d1189f10..18729f0a68a 100644 --- a/api/v1alpha1/tls_types.go +++ b/api/v1alpha1/tls_types.go @@ -5,6 +5,10 @@ package v1alpha1 +import ( + gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" +) + // +kubebuilder:validation:XValidation:rule="has(self.minVersion) && self.minVersion == '1.3' ? !has(self.ciphers) : true", message="setting ciphers has no effect if the minimum possible TLS version is 1.3" // +kubebuilder:validation:XValidation:rule="has(self.minVersion) && has(self.maxVersion) ? {\"Auto\":0,\"1.0\":1,\"1.1\":2,\"1.2\":3,\"1.3\":4}[self.minVersion] <= {\"1.0\":1,\"1.1\":2,\"1.2\":3,\"1.3\":4,\"Auto\":5}[self.maxVersion] : !has(self.minVersion) && has(self.maxVersion) ? 3 <= {\"1.0\":1,\"1.1\":2,\"1.2\":3,\"1.3\":4,\"Auto\":5}[self.maxVersion] : true", message="minVersion must be smaller or equal to maxVersion" type TLSSettings struct { @@ -62,6 +66,11 @@ type TLSSettings struct { // // +optional ALPNProtocols []ALPNProtocol `json:"alpnProtocols,omitempty"` + + // ClientValidation specifies the configuration to validate the client + // initiating the TLS connection to the Gateway listener. + // +optional + ClientValidation *ClientValidationContext `json:"clientValidation,omitempty"` } // ALPNProtocol specifies the protocol to be negotiated using ALPN @@ -96,3 +105,24 @@ const ( // TLSv1.3 specifies TLS version 1.3 TLSv13 TLSVersion = "1.3" ) + +// ClientValidationContext holds configuration that can be used to validate the client initiating the TLS connection +// to the Gateway. +// By default, no client specific configuration is validated. +type ClientValidationContext struct { + // CACertificateRefs contains one or more references to + // Kubernetes objects that contain TLS certificates of + // the Certificate Authorities that can be used + // as a trust anchor to validate the certificates presented by the client. + // + // A single reference to a Kubernetes ConfigMap or a Kubernetes Secret, + // with the CA certificate in a key named `ca.crt` is currently supported. + // + // References to a resource in different namespace are invalid UNLESS there + // is a ReferenceGrant in the target namespace that allows the certificate + // to be attached. + // + // +kubebuilder:validation:MaxItems=8 + // +optional + CACertificateRefs []gwapiv1.SecretObjectReference `json:"caCertificateRefs,omitempty"` +} diff --git a/api/v1alpha1/validation/envoygateway_validate.go b/api/v1alpha1/validation/envoygateway_validate.go index 657cb9ee73d..629aae4ae6e 100644 --- a/api/v1alpha1/validation/envoygateway_validate.go +++ b/api/v1alpha1/validation/envoygateway_validate.go @@ -15,7 +15,7 @@ import ( "github.com/envoyproxy/gateway/api/v1alpha1" ) -// Validate validates the provided EnvoyGateway. +// ValidateEnvoyGateway validates the provided EnvoyGateway. func ValidateEnvoyGateway(eg *v1alpha1.EnvoyGateway) error { switch { case eg == nil: @@ -28,6 +28,20 @@ func ValidateEnvoyGateway(eg *v1alpha1.EnvoyGateway) error { return errors.New("provider is unspecified") case eg.Provider.Type != v1alpha1.ProviderTypeKubernetes: return fmt.Errorf("unsupported provider %v", eg.Provider.Type) + case eg.Provider.Kubernetes != nil && eg.Provider.Kubernetes.Watch != nil: + watch := eg.Provider.Kubernetes.Watch + switch watch.Type { + case v1alpha1.KubernetesWatchModeTypeNamespaces: + if len(watch.Namespaces) == 0 { + return errors.New("namespaces should be specified when envoy gateway watch mode is 'Namespaces'") + } + case v1alpha1.KubernetesWatchModeTypeNamespaceSelector: + if watch.NamespaceSelector == nil { + return errors.New("namespaceSelector should be specified when envoy gateway watch mode is 'NamespaceSelector'") + } + default: + return errors.New("envoy gateway watch mode invalid, should be 'Namespaces' or 'NamespaceSelector'") + } case eg.Logging != nil && len(eg.Logging.Level) != 0: level := eg.Logging.Level for component, logLevel := range level { diff --git a/api/v1alpha1/validation/envoygateway_validate_test.go b/api/v1alpha1/validation/envoygateway_validate_test.go index 1728cb8a058..e03fdeb3016 100644 --- a/api/v1alpha1/validation/envoygateway_validate_test.go +++ b/api/v1alpha1/validation/envoygateway_validate_test.go @@ -415,7 +415,8 @@ func TestValidateEnvoyGateway(t *testing.T) { }, }, expect: false, - }, { + }, + { name: "valid gateway metrics sink", eg: &v1alpha1.EnvoyGateway{ EnvoyGatewaySpec: v1alpha1.EnvoyGatewaySpec{ @@ -438,7 +439,8 @@ func TestValidateEnvoyGateway(t *testing.T) { }, }, expect: true, - }, { + }, + { name: "invalid gateway metrics sink", eg: &v1alpha1.EnvoyGateway{ EnvoyGatewaySpec: v1alpha1.EnvoyGatewaySpec{ @@ -457,6 +459,94 @@ func TestValidateEnvoyGateway(t *testing.T) { }, expect: false, }, + { + name: "invalid gateway watch mode", + eg: &v1alpha1.EnvoyGateway{ + EnvoyGatewaySpec: v1alpha1.EnvoyGatewaySpec{ + Gateway: v1alpha1.DefaultGateway(), + Provider: &v1alpha1.EnvoyGatewayProvider{ + Type: v1alpha1.ProviderTypeKubernetes, + Kubernetes: &v1alpha1.EnvoyGatewayKubernetesProvider{ + Watch: &v1alpha1.KubernetesWatchMode{ + Type: "foobar", + }, + }, + }, + }, + }, + expect: false, + }, + { + name: "happy namespaces must be set when watch mode is Namespaces", + eg: &v1alpha1.EnvoyGateway{ + EnvoyGatewaySpec: v1alpha1.EnvoyGatewaySpec{ + Gateway: v1alpha1.DefaultGateway(), + Provider: &v1alpha1.EnvoyGatewayProvider{ + Type: v1alpha1.ProviderTypeKubernetes, + Kubernetes: &v1alpha1.EnvoyGatewayKubernetesProvider{ + Watch: &v1alpha1.KubernetesWatchMode{ + Type: v1alpha1.KubernetesWatchModeTypeNamespaces, + Namespaces: []string{"foo"}, + }, + }, + }, + }, + }, + expect: true, + }, + { + name: "fail namespaces is not be set when watch mode is Namespaces", + eg: &v1alpha1.EnvoyGateway{ + EnvoyGatewaySpec: v1alpha1.EnvoyGatewaySpec{ + Gateway: v1alpha1.DefaultGateway(), + Provider: &v1alpha1.EnvoyGatewayProvider{ + Type: v1alpha1.ProviderTypeKubernetes, + Kubernetes: &v1alpha1.EnvoyGatewayKubernetesProvider{ + Watch: &v1alpha1.KubernetesWatchMode{ + Type: v1alpha1.KubernetesWatchModeTypeNamespaces, + NamespaceSelector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": ""}}, + }, + }, + }, + }, + }, + expect: false, + }, + { + name: "happy namespaceSelector must be set when watch mode is NamespaceSelector", + eg: &v1alpha1.EnvoyGateway{ + EnvoyGatewaySpec: v1alpha1.EnvoyGatewaySpec{ + Gateway: v1alpha1.DefaultGateway(), + Provider: &v1alpha1.EnvoyGatewayProvider{ + Type: v1alpha1.ProviderTypeKubernetes, + Kubernetes: &v1alpha1.EnvoyGatewayKubernetesProvider{ + Watch: &v1alpha1.KubernetesWatchMode{ + Type: v1alpha1.KubernetesWatchModeTypeNamespaceSelector, + NamespaceSelector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": ""}}, + }, + }, + }, + }, + }, + expect: true, + }, + { + name: "fail namespaceSelector is not be set when watch mode is NamespaceSelector", + eg: &v1alpha1.EnvoyGateway{ + EnvoyGatewaySpec: v1alpha1.EnvoyGatewaySpec{ + Gateway: v1alpha1.DefaultGateway(), + Provider: &v1alpha1.EnvoyGatewayProvider{ + Type: v1alpha1.ProviderTypeKubernetes, + Kubernetes: &v1alpha1.EnvoyGatewayKubernetesProvider{ + Watch: &v1alpha1.KubernetesWatchMode{ + Type: v1alpha1.KubernetesWatchModeTypeNamespaceSelector, + }, + }, + }, + }, + }, + expect: false, + }, } for _, tc := range testCases { @@ -474,22 +564,22 @@ func TestValidateEnvoyGateway(t *testing.T) { func TestEnvoyGateway(t *testing.T) { envoyGateway := v1alpha1.DefaultEnvoyGateway() - assert.True(t, envoyGateway.Provider != nil) - assert.True(t, envoyGateway.Gateway != nil) - assert.True(t, envoyGateway.Logging != nil) + assert.NotNil(t, envoyGateway.Provider) + assert.NotNil(t, envoyGateway.Gateway) + assert.NotNil(t, envoyGateway.Logging) envoyGateway.SetEnvoyGatewayDefaults() assert.Equal(t, envoyGateway.Logging, v1alpha1.DefaultEnvoyGatewayLogging()) logging := v1alpha1.DefaultEnvoyGatewayLogging() - assert.True(t, logging != nil) - assert.True(t, logging.Level[v1alpha1.LogComponentGatewayDefault] == v1alpha1.LogLevelInfo) + assert.NotNil(t, logging) + assert.Equal(t, v1alpha1.LogLevelInfo, logging.Level[v1alpha1.LogComponentGatewayDefault]) gatewayLogging := &v1alpha1.EnvoyGatewayLogging{ Level: logging.Level, } gatewayLogging.SetEnvoyGatewayLoggingDefaults() - assert.True(t, gatewayLogging != nil) - assert.True(t, gatewayLogging.Level[v1alpha1.LogComponentGatewayDefault] == v1alpha1.LogLevelInfo) + assert.NotNil(t, gatewayLogging) + assert.Equal(t, v1alpha1.LogLevelInfo, gatewayLogging.Level[v1alpha1.LogComponentGatewayDefault]) } func TestDefaultEnvoyGatewayLoggingLevel(t *testing.T) { @@ -553,17 +643,17 @@ func TestEnvoyGatewayProvider(t *testing.T) { TypeMeta: metav1.TypeMeta{}, EnvoyGatewaySpec: v1alpha1.EnvoyGatewaySpec{Provider: v1alpha1.DefaultEnvoyGatewayProvider()}, } - assert.True(t, envoyGateway.Provider != nil) + assert.NotNil(t, envoyGateway.Provider) envoyGatewayProvider := envoyGateway.GetEnvoyGatewayProvider() - assert.True(t, envoyGatewayProvider.Kubernetes == nil) + assert.Nil(t, envoyGatewayProvider.Kubernetes) assert.Equal(t, envoyGateway.Provider, envoyGatewayProvider) envoyGatewayProvider.Kubernetes = v1alpha1.DefaultEnvoyGatewayKubeProvider() assert.Equal(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment, v1alpha1.DefaultKubernetesDeployment(v1alpha1.DefaultRateLimitImage)) envoyGatewayProvider.Kubernetes = &v1alpha1.EnvoyGatewayKubernetesProvider{} - assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment == nil) + assert.Nil(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment) envoyGatewayProvider.Kubernetes = &v1alpha1.EnvoyGatewayKubernetesProvider{ RateLimitDeployment: &v1alpha1.KubernetesDeploymentSpec{ @@ -571,9 +661,9 @@ func TestEnvoyGatewayProvider(t *testing.T) { Pod: nil, Container: nil, }} - assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Replicas == nil) - assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Pod == nil) - assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container == nil) + assert.Nil(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Replicas) + assert.Nil(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Pod) + assert.Nil(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container) envoyGatewayKubeProvider := envoyGatewayProvider.GetEnvoyGatewayKubeProvider() envoyGatewayProvider.Kubernetes = &v1alpha1.EnvoyGatewayKubernetesProvider{ @@ -586,39 +676,39 @@ func TestEnvoyGatewayProvider(t *testing.T) { Image: nil, }, }} - assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container.Resources == nil) + assert.Nil(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container.Resources) envoyGatewayProvider.GetEnvoyGatewayKubeProvider() - assert.True(t, envoyGatewayProvider.Kubernetes != nil) + assert.NotNil(t, envoyGatewayProvider.Kubernetes) assert.Equal(t, envoyGatewayProvider.Kubernetes, envoyGatewayKubeProvider) - assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment != nil) + assert.NotNil(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment) assert.Equal(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment, v1alpha1.DefaultKubernetesDeployment(v1alpha1.DefaultRateLimitImage)) - assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Replicas != nil) + assert.NotNil(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Replicas) assert.Equal(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Replicas, v1alpha1.DefaultKubernetesDeploymentReplicas()) - assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Pod != nil) + assert.NotNil(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Pod) assert.Equal(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Pod, v1alpha1.DefaultKubernetesPod()) - assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container != nil) + assert.NotNil(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container) assert.Equal(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container, v1alpha1.DefaultKubernetesContainer(v1alpha1.DefaultRateLimitImage)) - assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container.Resources != nil) + assert.NotNil(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container.Resources) assert.Equal(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container.Resources, v1alpha1.DefaultResourceRequirements()) - assert.True(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container.Image != nil) + assert.NotNil(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container.Image) assert.Equal(t, envoyGatewayProvider.Kubernetes.RateLimitDeployment.Container.Image, v1alpha1.DefaultKubernetesContainerImage(v1alpha1.DefaultRateLimitImage)) } func TestEnvoyGatewayAdmin(t *testing.T) { // default envoygateway config admin should not be nil eg := v1alpha1.DefaultEnvoyGateway() - assert.True(t, eg.Admin != nil) + assert.NotNil(t, eg.Admin) // get default admin config from envoygateway // values should be set in default egAdmin := eg.GetEnvoyGatewayAdmin() - assert.True(t, egAdmin != nil) - assert.True(t, egAdmin.Address.Port == v1alpha1.GatewayAdminPort) - assert.True(t, egAdmin.Address.Host == v1alpha1.GatewayAdminHost) - assert.True(t, egAdmin.EnableDumpConfig == false) - assert.True(t, egAdmin.EnablePprof == false) + assert.NotNil(t, egAdmin) + assert.Equal(t, v1alpha1.GatewayAdminPort, egAdmin.Address.Port) + assert.Equal(t, v1alpha1.GatewayAdminHost, egAdmin.Address.Host) + assert.False(t, egAdmin.EnableDumpConfig) + assert.False(t, egAdmin.EnablePprof) // override the admin config // values should be updated @@ -631,34 +721,34 @@ func TestEnvoyGatewayAdmin(t *testing.T) { EnablePprof: true, } - assert.True(t, eg.GetEnvoyGatewayAdmin().Address.Port == 19010) - assert.True(t, eg.GetEnvoyGatewayAdmin().Address.Host == "0.0.0.0") - assert.True(t, eg.GetEnvoyGatewayAdmin().EnableDumpConfig == true) - assert.True(t, eg.GetEnvoyGatewayAdmin().EnablePprof == true) + assert.Equal(t, 19010, eg.GetEnvoyGatewayAdmin().Address.Port) + assert.Equal(t, "0.0.0.0", eg.GetEnvoyGatewayAdmin().Address.Host) + assert.True(t, eg.GetEnvoyGatewayAdmin().EnableDumpConfig) + assert.True(t, eg.GetEnvoyGatewayAdmin().EnablePprof) // set eg defaults when admin is nil // the admin should not be nil eg.Admin = nil eg.SetEnvoyGatewayDefaults() - assert.True(t, eg.Admin != nil) - assert.True(t, eg.Admin.Address.Port == v1alpha1.GatewayAdminPort) - assert.True(t, eg.Admin.Address.Host == v1alpha1.GatewayAdminHost) - assert.True(t, eg.Admin.EnableDumpConfig == false) - assert.True(t, eg.Admin.EnablePprof == false) + assert.NotNil(t, eg.Admin) + assert.Equal(t, v1alpha1.GatewayAdminPort, eg.Admin.Address.Port) + assert.Equal(t, v1alpha1.GatewayAdminHost, eg.Admin.Address.Host) + assert.False(t, eg.Admin.EnableDumpConfig) + assert.False(t, eg.Admin.EnablePprof) } func TestEnvoyGatewayTelemetry(t *testing.T) { // default envoygateway config telemetry should not be nil eg := v1alpha1.DefaultEnvoyGateway() - assert.True(t, eg.Telemetry != nil) + assert.NotNil(t, eg.Telemetry) // get default telemetry config from envoygateway // values should be set in default egTelemetry := eg.GetEnvoyGatewayTelemetry() - assert.True(t, egTelemetry != nil) - assert.True(t, egTelemetry.Metrics != nil) - assert.True(t, egTelemetry.Metrics.Prometheus.Disable == false) - assert.True(t, egTelemetry.Metrics.Sinks == nil) + assert.NotNil(t, egTelemetry) + assert.NotNil(t, egTelemetry.Metrics) + assert.False(t, egTelemetry.Metrics.Prometheus.Disable) + assert.Nil(t, egTelemetry.Metrics.Sinks) // override the telemetry config // values should be updated @@ -685,16 +775,16 @@ func TestEnvoyGatewayTelemetry(t *testing.T) { }, } - assert.True(t, eg.GetEnvoyGatewayTelemetry().Metrics.Prometheus.Disable == true) - assert.True(t, len(eg.GetEnvoyGatewayTelemetry().Metrics.Sinks) == 2) - assert.True(t, eg.GetEnvoyGatewayTelemetry().Metrics.Sinks[0].Type == v1alpha1.MetricSinkTypeOpenTelemetry) + assert.True(t, eg.GetEnvoyGatewayTelemetry().Metrics.Prometheus.Disable) + assert.Len(t, eg.GetEnvoyGatewayTelemetry().Metrics.Sinks, 2) + assert.Equal(t, v1alpha1.MetricSinkTypeOpenTelemetry, eg.GetEnvoyGatewayTelemetry().Metrics.Sinks[0].Type) // set eg defaults when telemetry is nil // the telemetry should not be nil eg.Telemetry = nil eg.SetEnvoyGatewayDefaults() - assert.True(t, eg.Telemetry != nil) - assert.True(t, eg.Telemetry.Metrics != nil) - assert.True(t, eg.Telemetry.Metrics.Prometheus.Disable == false) - assert.True(t, eg.Telemetry.Metrics.Sinks == nil) + assert.NotNil(t, eg.Telemetry) + assert.NotNil(t, eg.Telemetry.Metrics) + assert.False(t, eg.Telemetry.Metrics.Prometheus.Disable) + assert.Nil(t, eg.Telemetry.Metrics.Sinks) } diff --git a/api/v1alpha1/validation/envoyproxy_validate.go b/api/v1alpha1/validation/envoyproxy_validate.go index 6c608f0e0f7..a61973dcaaf 100644 --- a/api/v1alpha1/validation/envoyproxy_validate.go +++ b/api/v1alpha1/validation/envoyproxy_validate.go @@ -8,7 +8,7 @@ package validation import ( "errors" "fmt" - "net" + "net/netip" "reflect" bootstrapv3 "github.com/envoyproxy/go-control-plane/envoy/config/bootstrap/v3" @@ -103,7 +103,7 @@ func validateService(spec *egv1a1.EnvoyProxySpec) []error { errs = append(errs, fmt.Errorf("loadBalancerIP can only be set for %v type", egv1a1.ServiceTypeLoadBalancer)) } - if ip := net.ParseIP(*serviceLoadBalancerIP); ip == nil || ip.To4() == nil { + if ip, err := netip.ParseAddr(*serviceLoadBalancerIP); err != nil || !ip.Unmap().Is4() { errs = append(errs, fmt.Errorf("loadBalancerIP:%s is an invalid IPv4 address", *serviceLoadBalancerIP)) } } diff --git a/api/v1alpha1/validation/envoyproxy_validate_test.go b/api/v1alpha1/validation/envoyproxy_validate_test.go index 0a9fcde07b0..f13e8a921fb 100644 --- a/api/v1alpha1/validation/envoyproxy_validate_test.go +++ b/api/v1alpha1/validation/envoyproxy_validate_test.go @@ -469,33 +469,33 @@ func TestEnvoyProxyProvider(t *testing.T) { Provider: egv1a1.DefaultEnvoyProxyProvider(), }, } - assert.True(t, envoyProxy.Spec.Provider != nil) + assert.NotNil(t, envoyProxy.Spec.Provider) envoyProxyProvider := envoyProxy.GetEnvoyProxyProvider() - assert.True(t, envoyProxyProvider.Kubernetes == nil) + assert.Nil(t, envoyProxyProvider.Kubernetes) assert.True(t, reflect.DeepEqual(envoyProxy.Spec.Provider, envoyProxyProvider)) envoyProxyKubeProvider := envoyProxyProvider.GetEnvoyProxyKubeProvider() - assert.True(t, envoyProxyProvider.Kubernetes != nil) + assert.NotNil(t, envoyProxyProvider.Kubernetes) assert.True(t, reflect.DeepEqual(envoyProxyProvider.Kubernetes, envoyProxyKubeProvider)) envoyProxyProvider.GetEnvoyProxyKubeProvider() - assert.True(t, envoyProxyProvider.Kubernetes.EnvoyDeployment != nil) + assert.NotNil(t, envoyProxyProvider.Kubernetes.EnvoyDeployment) assert.Equal(t, envoyProxyProvider.Kubernetes.EnvoyDeployment, egv1a1.DefaultKubernetesDeployment(egv1a1.DefaultEnvoyProxyImage)) - assert.True(t, envoyProxyProvider.Kubernetes.EnvoyDeployment.Replicas != nil) + assert.NotNil(t, envoyProxyProvider.Kubernetes.EnvoyDeployment.Replicas) assert.Equal(t, envoyProxyProvider.Kubernetes.EnvoyDeployment.Replicas, egv1a1.DefaultKubernetesDeploymentReplicas()) - assert.True(t, envoyProxyProvider.Kubernetes.EnvoyDeployment.Pod != nil) + assert.NotNil(t, envoyProxyProvider.Kubernetes.EnvoyDeployment.Pod) assert.Equal(t, envoyProxyProvider.Kubernetes.EnvoyDeployment.Pod, egv1a1.DefaultKubernetesPod()) - assert.True(t, envoyProxyProvider.Kubernetes.EnvoyDeployment.Container != nil) + assert.NotNil(t, envoyProxyProvider.Kubernetes.EnvoyDeployment.Container) assert.Equal(t, envoyProxyProvider.Kubernetes.EnvoyDeployment.Container, egv1a1.DefaultKubernetesContainer(egv1a1.DefaultEnvoyProxyImage)) - assert.True(t, envoyProxyProvider.Kubernetes.EnvoyDeployment.Container.Resources != nil) + assert.NotNil(t, envoyProxyProvider.Kubernetes.EnvoyDeployment.Container.Resources) assert.Equal(t, envoyProxyProvider.Kubernetes.EnvoyDeployment.Container.Resources, egv1a1.DefaultResourceRequirements()) - assert.True(t, envoyProxyProvider.Kubernetes.EnvoyDeployment.Container.Image != nil) + assert.NotNil(t, envoyProxyProvider.Kubernetes.EnvoyDeployment.Container.Image) assert.Equal(t, envoyProxyProvider.Kubernetes.EnvoyDeployment.Container.Image, egv1a1.DefaultKubernetesContainerImage(egv1a1.DefaultEnvoyProxyImage)) - assert.True(t, envoyProxyProvider.Kubernetes.EnvoyService != nil) + assert.NotNil(t, envoyProxyProvider.Kubernetes.EnvoyService) assert.True(t, reflect.DeepEqual(envoyProxyProvider.Kubernetes.EnvoyService.Type, egv1a1.GetKubernetesServiceType(egv1a1.ServiceTypeLoadBalancer))) } diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 9ffe50b4f61..d38d710885d 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -13,11 +13,107 @@ import ( appsv1 "k8s.io/api/apps/v1" "k8s.io/api/autoscaling/v2" corev1 "k8s.io/api/core/v1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" apisv1 "sigs.k8s.io/gateway-api/apis/v1" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveHealthCheck) DeepCopyInto(out *ActiveHealthCheck) { + *out = *in + if in.Timeout != nil { + in, out := &in.Timeout, &out.Timeout + *out = new(v1.Duration) + **out = **in + } + if in.Interval != nil { + in, out := &in.Interval, &out.Interval + *out = new(v1.Duration) + **out = **in + } + if in.UnhealthyThreshold != nil { + in, out := &in.UnhealthyThreshold, &out.UnhealthyThreshold + *out = new(uint32) + **out = **in + } + if in.HealthyThreshold != nil { + in, out := &in.HealthyThreshold, &out.HealthyThreshold + *out = new(uint32) + **out = **in + } + if in.HTTP != nil { + in, out := &in.HTTP, &out.HTTP + *out = new(HTTPActiveHealthChecker) + (*in).DeepCopyInto(*out) + } + if in.TCP != nil { + in, out := &in.TCP, &out.TCP + *out = new(TCPActiveHealthChecker) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveHealthCheck. +func (in *ActiveHealthCheck) DeepCopy() *ActiveHealthCheck { + if in == nil { + return nil + } + out := new(ActiveHealthCheck) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveHealthCheckPayload) DeepCopyInto(out *ActiveHealthCheckPayload) { + *out = *in + if in.Text != nil { + in, out := &in.Text, &out.Text + *out = new(string) + **out = **in + } + if in.Binary != nil { + in, out := &in.Binary, &out.Binary + *out = make([]byte, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveHealthCheckPayload. +func (in *ActiveHealthCheckPayload) DeepCopy() *ActiveHealthCheckPayload { + if in == nil { + return nil + } + out := new(ActiveHealthCheckPayload) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackOffPolicy) DeepCopyInto(out *BackOffPolicy) { + *out = *in + if in.BaseInterval != nil { + in, out := &in.BaseInterval, &out.BaseInterval + *out = new(v1.Duration) + **out = **in + } + if in.MaxInterval != nil { + in, out := &in.MaxInterval, &out.MaxInterval + *out = new(v1.Duration) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackOffPolicy. +func (in *BackOffPolicy) DeepCopy() *BackOffPolicy { + if in == nil { + return nil + } + out := new(BackOffPolicy) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackendTrafficPolicy) DeepCopyInto(out *BackendTrafficPolicy) { *out = *in @@ -116,6 +212,27 @@ func (in *BackendTrafficPolicySpec) DeepCopyInto(out *BackendTrafficPolicySpec) *out = new(CircuitBreaker) (*in).DeepCopyInto(*out) } + if in.Retry != nil { + in, out := &in.Retry, &out.Retry + *out = new(Retry) + (*in).DeepCopyInto(*out) + } + if in.Timeout != nil { + in, out := &in.Timeout, &out.Timeout + *out = new(Timeout) + (*in).DeepCopyInto(*out) + } + if in.Compression != nil { + in, out := &in.Compression, &out.Compression + *out = make([]*Compression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(Compression) + (*in).DeepCopyInto(*out) + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTrafficPolicySpec. @@ -229,6 +346,11 @@ func (in *CircuitBreaker) DeepCopyInto(out *CircuitBreaker) { *out = new(int64) **out = **in } + if in.MaxRequestsPerConnection != nil { + in, out := &in.MaxRequestsPerConnection, &out.MaxRequestsPerConnection + *out = new(int64) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CircuitBreaker. @@ -256,6 +378,51 @@ func (in *ClaimToHeader) DeepCopy() *ClaimToHeader { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClientIPDetectionSettings) DeepCopyInto(out *ClientIPDetectionSettings) { + *out = *in + if in.XForwardedFor != nil { + in, out := &in.XForwardedFor, &out.XForwardedFor + *out = new(XForwardedForSettings) + (*in).DeepCopyInto(*out) + } + if in.CustomHeader != nil { + in, out := &in.CustomHeader, &out.CustomHeader + *out = new(CustomHeaderExtensionSettings) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClientIPDetectionSettings. +func (in *ClientIPDetectionSettings) DeepCopy() *ClientIPDetectionSettings { + if in == nil { + return nil + } + out := new(ClientIPDetectionSettings) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClientTimeout) DeepCopyInto(out *ClientTimeout) { + *out = *in + if in.HTTP != nil { + in, out := &in.HTTP, &out.HTTP + *out = new(HTTPClientTimeout) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClientTimeout. +func (in *ClientTimeout) DeepCopy() *ClientTimeout { + if in == nil { + return nil + } + out := new(ClientTimeout) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClientTrafficPolicy) DeepCopyInto(out *ClientTrafficPolicy) { *out = *in @@ -324,16 +491,16 @@ func (in *ClientTrafficPolicySpec) DeepCopyInto(out *ClientTrafficPolicySpec) { *out = new(TCPKeepalive) (*in).DeepCopyInto(*out) } - if in.SuppressEnvoyHeaders != nil { - in, out := &in.SuppressEnvoyHeaders, &out.SuppressEnvoyHeaders - *out = new(bool) - **out = **in - } if in.EnableProxyProtocol != nil { in, out := &in.EnableProxyProtocol, &out.EnableProxyProtocol *out = new(bool) **out = **in } + if in.ClientIPDetection != nil { + in, out := &in.ClientIPDetection, &out.ClientIPDetection + *out = new(ClientIPDetectionSettings) + (*in).DeepCopyInto(*out) + } if in.HTTP3 != nil { in, out := &in.HTTP3, &out.HTTP3 *out = new(HTTP3Settings) @@ -349,6 +516,21 @@ func (in *ClientTrafficPolicySpec) DeepCopyInto(out *ClientTrafficPolicySpec) { *out = new(PathSettings) (*in).DeepCopyInto(*out) } + if in.HTTP1 != nil { + in, out := &in.HTTP1, &out.HTTP1 + *out = new(HTTP1Settings) + (*in).DeepCopyInto(*out) + } + if in.Headers != nil { + in, out := &in.Headers, &out.Headers + *out = new(HeaderSettings) + (*in).DeepCopyInto(*out) + } + if in.Timeout != nil { + in, out := &in.Timeout, &out.Timeout + *out = new(ClientTimeout) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClientTrafficPolicySpec. @@ -383,6 +565,48 @@ func (in *ClientTrafficPolicyStatus) DeepCopy() *ClientTrafficPolicyStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClientValidationContext) DeepCopyInto(out *ClientValidationContext) { + *out = *in + if in.CACertificateRefs != nil { + in, out := &in.CACertificateRefs, &out.CACertificateRefs + *out = make([]apisv1.SecretObjectReference, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClientValidationContext. +func (in *ClientValidationContext) DeepCopy() *ClientValidationContext { + if in == nil { + return nil + } + out := new(ClientValidationContext) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Compression) DeepCopyInto(out *Compression) { + *out = *in + if in.Gzip != nil { + in, out := &in.Gzip, &out.Gzip + *out = new(GzipCompressor) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Compression. +func (in *Compression) DeepCopy() *Compression { + if in == nil { + return nil + } + out := new(Compression) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ConsistentHash) DeepCopyInto(out *ConsistentHash) { *out = *in @@ -398,6 +622,26 @@ func (in *ConsistentHash) DeepCopy() *ConsistentHash { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CustomHeaderExtensionSettings) DeepCopyInto(out *CustomHeaderExtensionSettings) { + *out = *in + if in.FailClosed != nil { + in, out := &in.FailClosed, &out.FailClosed + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomHeaderExtensionSettings. +func (in *CustomHeaderExtensionSettings) DeepCopy() *CustomHeaderExtensionSettings { + if in == nil { + return nil + } + out := new(CustomHeaderExtensionSettings) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CustomTag) DeepCopyInto(out *CustomTag) { *out = *in @@ -1087,6 +1331,11 @@ func (in *EnvoyProxySpec) DeepCopyInto(out *EnvoyProxySpec) { *out = new(int32) **out = **in } + if in.ExtraArgs != nil { + in, out := &in.ExtraArgs, &out.ExtraArgs + *out = make([]string, len(*in)) + copy(*out, *in) + } if in.MergeGateways != nil { in, out := &in.MergeGateways, &out.MergeGateways *out = new(bool) @@ -1119,6 +1368,36 @@ func (in *EnvoyProxyStatus) DeepCopy() *EnvoyProxyStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExtAuth) DeepCopyInto(out *ExtAuth) { + *out = *in + if in.GRPC != nil { + in, out := &in.GRPC, &out.GRPC + *out = new(GRPCExtAuthService) + (*in).DeepCopyInto(*out) + } + if in.HTTP != nil { + in, out := &in.HTTP, &out.HTTP + *out = new(HTTPExtAuthService) + (*in).DeepCopyInto(*out) + } + if in.HeadersToExtAuth != nil { + in, out := &in.HeadersToExtAuth, &out.HeadersToExtAuth + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtAuth. +func (in *ExtAuth) DeepCopy() *ExtAuth { + if in == nil { + return nil + } + out := new(ExtAuth) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ExtensionAPISettings) DeepCopyInto(out *ExtensionAPISettings) { *out = *in @@ -1315,6 +1594,22 @@ func (in *FileEnvoyProxyAccessLog) DeepCopy() *FileEnvoyProxyAccessLog { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GRPCExtAuthService) DeepCopyInto(out *GRPCExtAuthService) { + *out = *in + in.BackendRef.DeepCopyInto(&out.BackendRef) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCExtAuthService. +func (in *GRPCExtAuthService) DeepCopy() *GRPCExtAuthService { + if in == nil { + return nil + } + out := new(GRPCExtAuthService) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Gateway) DeepCopyInto(out *Gateway) { *out = *in @@ -1342,72 +1637,208 @@ func (in *GlobalRateLimit) DeepCopyInto(out *GlobalRateLimit) { } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GlobalRateLimit. -func (in *GlobalRateLimit) DeepCopy() *GlobalRateLimit { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GlobalRateLimit. +func (in *GlobalRateLimit) DeepCopy() *GlobalRateLimit { + if in == nil { + return nil + } + out := new(GlobalRateLimit) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GroupVersionKind) DeepCopyInto(out *GroupVersionKind) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GroupVersionKind. +func (in *GroupVersionKind) DeepCopy() *GroupVersionKind { + if in == nil { + return nil + } + out := new(GroupVersionKind) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GzipCompressor) DeepCopyInto(out *GzipCompressor) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GzipCompressor. +func (in *GzipCompressor) DeepCopy() *GzipCompressor { + if in == nil { + return nil + } + out := new(GzipCompressor) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTP10Settings) DeepCopyInto(out *HTTP10Settings) { + *out = *in + if in.UseDefaultHost != nil { + in, out := &in.UseDefaultHost, &out.UseDefaultHost + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTP10Settings. +func (in *HTTP10Settings) DeepCopy() *HTTP10Settings { + if in == nil { + return nil + } + out := new(HTTP10Settings) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTP1Settings) DeepCopyInto(out *HTTP1Settings) { + *out = *in + if in.EnableTrailers != nil { + in, out := &in.EnableTrailers, &out.EnableTrailers + *out = new(bool) + **out = **in + } + if in.PreserveHeaderCase != nil { + in, out := &in.PreserveHeaderCase, &out.PreserveHeaderCase + *out = new(bool) + **out = **in + } + if in.HTTP10 != nil { + in, out := &in.HTTP10, &out.HTTP10 + *out = new(HTTP10Settings) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTP1Settings. +func (in *HTTP1Settings) DeepCopy() *HTTP1Settings { + if in == nil { + return nil + } + out := new(HTTP1Settings) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTP3Settings) DeepCopyInto(out *HTTP3Settings) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTP3Settings. +func (in *HTTP3Settings) DeepCopy() *HTTP3Settings { + if in == nil { + return nil + } + out := new(HTTP3Settings) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPActiveHealthChecker) DeepCopyInto(out *HTTPActiveHealthChecker) { + *out = *in + if in.Method != nil { + in, out := &in.Method, &out.Method + *out = new(string) + **out = **in + } + if in.ExpectedStatuses != nil { + in, out := &in.ExpectedStatuses, &out.ExpectedStatuses + *out = make([]HTTPStatus, len(*in)) + copy(*out, *in) + } + if in.ExpectedResponse != nil { + in, out := &in.ExpectedResponse, &out.ExpectedResponse + *out = new(ActiveHealthCheckPayload) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPActiveHealthChecker. +func (in *HTTPActiveHealthChecker) DeepCopy() *HTTPActiveHealthChecker { if in == nil { return nil } - out := new(GlobalRateLimit) + out := new(HTTPActiveHealthChecker) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GroupVersionKind) DeepCopyInto(out *GroupVersionKind) { +func (in *HTTPClientTimeout) DeepCopyInto(out *HTTPClientTimeout) { *out = *in + if in.RequestReceivedTimeout != nil { + in, out := &in.RequestReceivedTimeout, &out.RequestReceivedTimeout + *out = new(apisv1.Duration) + **out = **in + } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GroupVersionKind. -func (in *GroupVersionKind) DeepCopy() *GroupVersionKind { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPClientTimeout. +func (in *HTTPClientTimeout) DeepCopy() *HTTPClientTimeout { if in == nil { return nil } - out := new(GroupVersionKind) + out := new(HTTPClientTimeout) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTP3Settings) DeepCopyInto(out *HTTP3Settings) { +func (in *HTTPExtAuthService) DeepCopyInto(out *HTTPExtAuthService) { *out = *in + in.BackendRef.DeepCopyInto(&out.BackendRef) + if in.Path != nil { + in, out := &in.Path, &out.Path + *out = new(string) + **out = **in + } + if in.HeadersToBackend != nil { + in, out := &in.HeadersToBackend, &out.HeadersToBackend + *out = make([]string, len(*in)) + copy(*out, *in) + } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTP3Settings. -func (in *HTTP3Settings) DeepCopy() *HTTP3Settings { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPExtAuthService. +func (in *HTTPExtAuthService) DeepCopy() *HTTPExtAuthService { if in == nil { return nil } - out := new(HTTP3Settings) + out := new(HTTPExtAuthService) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HTTPHealthChecker) DeepCopyInto(out *HTTPHealthChecker) { +func (in *HTTPTimeout) DeepCopyInto(out *HTTPTimeout) { *out = *in - if in.Method != nil { - in, out := &in.Method, &out.Method - *out = new(string) + if in.ConnectionIdleTimeout != nil { + in, out := &in.ConnectionIdleTimeout, &out.ConnectionIdleTimeout + *out = new(apisv1.Duration) **out = **in } - if in.ExpectedStatuses != nil { - in, out := &in.ExpectedStatuses, &out.ExpectedStatuses - *out = make([]HTTPStatus, len(*in)) - copy(*out, *in) - } - if in.ExpectedResponse != nil { - in, out := &in.ExpectedResponse, &out.ExpectedResponse - *out = new(HealthCheckPayload) - (*in).DeepCopyInto(*out) + if in.MaxConnectionDuration != nil { + in, out := &in.MaxConnectionDuration, &out.MaxConnectionDuration + *out = new(apisv1.Duration) + **out = **in } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPHealthChecker. -func (in *HTTPHealthChecker) DeepCopy() *HTTPHealthChecker { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPTimeout. +func (in *HTTPTimeout) DeepCopy() *HTTPTimeout { if in == nil { return nil } - out := new(HTTPHealthChecker) + out := new(HTTPTimeout) in.DeepCopyInto(out) return out } @@ -1438,71 +1869,46 @@ func (in *HeaderMatch) DeepCopy() *HeaderMatch { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HealthCheck) DeepCopyInto(out *HealthCheck) { +func (in *HeaderSettings) DeepCopyInto(out *HeaderSettings) { *out = *in - if in.Timeout != nil { - in, out := &in.Timeout, &out.Timeout - *out = new(v1.Duration) - **out = **in - } - if in.Interval != nil { - in, out := &in.Interval, &out.Interval - *out = new(v1.Duration) - **out = **in - } - if in.UnhealthyThreshold != nil { - in, out := &in.UnhealthyThreshold, &out.UnhealthyThreshold - *out = new(uint32) - **out = **in - } - if in.HealthyThreshold != nil { - in, out := &in.HealthyThreshold, &out.HealthyThreshold - *out = new(uint32) + if in.EnableEnvoyHeaders != nil { + in, out := &in.EnableEnvoyHeaders, &out.EnableEnvoyHeaders + *out = new(bool) **out = **in } - if in.HTTP != nil { - in, out := &in.HTTP, &out.HTTP - *out = new(HTTPHealthChecker) - (*in).DeepCopyInto(*out) - } - if in.TCP != nil { - in, out := &in.TCP, &out.TCP - *out = new(TCPHealthChecker) - (*in).DeepCopyInto(*out) - } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HealthCheck. -func (in *HealthCheck) DeepCopy() *HealthCheck { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HeaderSettings. +func (in *HeaderSettings) DeepCopy() *HeaderSettings { if in == nil { return nil } - out := new(HealthCheck) + out := new(HeaderSettings) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HealthCheckPayload) DeepCopyInto(out *HealthCheckPayload) { +func (in *HealthCheck) DeepCopyInto(out *HealthCheck) { *out = *in - if in.Text != nil { - in, out := &in.Text, &out.Text - *out = new(string) - **out = **in + if in.Active != nil { + in, out := &in.Active, &out.Active + *out = new(ActiveHealthCheck) + (*in).DeepCopyInto(*out) } - if in.Binary != nil { - in, out := &in.Binary, &out.Binary - *out = make([]byte, len(*in)) - copy(*out, *in) + if in.Passive != nil { + in, out := &in.Passive, &out.Passive + *out = new(PassiveHealthCheck) + (*in).DeepCopyInto(*out) } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HealthCheckPayload. -func (in *HealthCheckPayload) DeepCopy() *HealthCheckPayload { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HealthCheck. +func (in *HealthCheck) DeepCopy() *HealthCheck { if in == nil { return nil } - out := new(HealthCheckPayload) + out := new(HealthCheck) in.DeepCopyInto(out) return out } @@ -1510,7 +1916,16 @@ func (in *HealthCheckPayload) DeepCopy() *HealthCheckPayload { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *JSONPatchOperation) DeepCopyInto(out *JSONPatchOperation) { *out = *in - in.Value.DeepCopyInto(&out.Value) + if in.From != nil { + in, out := &in.From, &out.From + *out = new(string) + **out = **in + } + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = new(apiextensionsv1.JSON) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONPatchOperation. @@ -1548,11 +1963,23 @@ func (in *JWT) DeepCopy() *JWT { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *JWTExtractor) DeepCopyInto(out *JWTExtractor) { *out = *in + if in.Headers != nil { + in, out := &in.Headers, &out.Headers + *out = make([]JWTHeaderExtractor, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } if in.Cookies != nil { in, out := &in.Cookies, &out.Cookies *out = make([]string, len(*in)) copy(*out, *in) } + if in.Params != nil { + in, out := &in.Params, &out.Params + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JWTExtractor. @@ -1565,6 +1992,26 @@ func (in *JWTExtractor) DeepCopy() *JWTExtractor { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JWTHeaderExtractor) DeepCopyInto(out *JWTHeaderExtractor) { + *out = *in + if in.ValuePrefix != nil { + in, out := &in.ValuePrefix, &out.ValuePrefix + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JWTHeaderExtractor. +func (in *JWTHeaderExtractor) DeepCopy() *JWTHeaderExtractor { + if in == nil { + return nil + } + out := new(JWTHeaderExtractor) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *JWTProvider) DeepCopyInto(out *JWTProvider) { *out = *in @@ -1861,10 +2308,10 @@ func (in *KubernetesWatchMode) DeepCopyInto(out *KubernetesWatchMode) { *out = make([]string, len(*in)) copy(*out, *in) } - if in.NamespaceSelectors != nil { - in, out := &in.NamespaceSelectors, &out.NamespaceSelectors - *out = make([]string, len(*in)) - copy(*out, *in) + if in.NamespaceSelector != nil { + in, out := &in.NamespaceSelector, &out.NamespaceSelector + *out = new(v1.LabelSelector) + (*in).DeepCopyInto(*out) } } @@ -2019,6 +2466,56 @@ func (in *OpenTelemetryEnvoyProxyAccessLog) DeepCopy() *OpenTelemetryEnvoyProxyA return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PassiveHealthCheck) DeepCopyInto(out *PassiveHealthCheck) { + *out = *in + if in.SplitExternalLocalOriginErrors != nil { + in, out := &in.SplitExternalLocalOriginErrors, &out.SplitExternalLocalOriginErrors + *out = new(bool) + **out = **in + } + if in.Interval != nil { + in, out := &in.Interval, &out.Interval + *out = new(v1.Duration) + **out = **in + } + if in.ConsecutiveLocalOriginFailures != nil { + in, out := &in.ConsecutiveLocalOriginFailures, &out.ConsecutiveLocalOriginFailures + *out = new(uint32) + **out = **in + } + if in.ConsecutiveGatewayErrors != nil { + in, out := &in.ConsecutiveGatewayErrors, &out.ConsecutiveGatewayErrors + *out = new(uint32) + **out = **in + } + if in.Consecutive5xxErrors != nil { + in, out := &in.Consecutive5xxErrors, &out.Consecutive5xxErrors + *out = new(uint32) + **out = **in + } + if in.BaseEjectionTime != nil { + in, out := &in.BaseEjectionTime, &out.BaseEjectionTime + *out = new(v1.Duration) + **out = **in + } + if in.MaxEjectionPercent != nil { + in, out := &in.MaxEjectionPercent, &out.MaxEjectionPercent + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PassiveHealthCheck. +func (in *PassiveHealthCheck) DeepCopy() *PassiveHealthCheck { + if in == nil { + return nil + } + out := new(PassiveHealthCheck) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PathSettings) DeepCopyInto(out *PathSettings) { *out = *in @@ -2044,6 +2541,31 @@ func (in *PathSettings) DeepCopy() *PathSettings { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PerRetryPolicy) DeepCopyInto(out *PerRetryPolicy) { + *out = *in + if in.Timeout != nil { + in, out := &in.Timeout, &out.Timeout + *out = new(v1.Duration) + **out = **in + } + if in.BackOff != nil { + in, out := &in.BackOff, &out.BackOff + *out = new(BackOffPolicy) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PerRetryPolicy. +func (in *PerRetryPolicy) DeepCopy() *PerRetryPolicy { + if in == nil { + return nil + } + out := new(PerRetryPolicy) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProxyAccessLog) DeepCopyInto(out *ProxyAccessLog) { *out = *in @@ -2546,6 +3068,61 @@ func (in *RequestHeaderCustomTag) DeepCopy() *RequestHeaderCustomTag { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Retry) DeepCopyInto(out *Retry) { + *out = *in + if in.NumRetries != nil { + in, out := &in.NumRetries, &out.NumRetries + *out = new(int32) + **out = **in + } + if in.RetryOn != nil { + in, out := &in.RetryOn, &out.RetryOn + *out = new(RetryOn) + (*in).DeepCopyInto(*out) + } + if in.PerRetry != nil { + in, out := &in.PerRetry, &out.PerRetry + *out = new(PerRetryPolicy) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Retry. +func (in *Retry) DeepCopy() *Retry { + if in == nil { + return nil + } + out := new(Retry) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RetryOn) DeepCopyInto(out *RetryOn) { + *out = *in + if in.Triggers != nil { + in, out := &in.Triggers, &out.Triggers + *out = make([]TriggerEnum, len(*in)) + copy(*out, *in) + } + if in.HTTPStatusCodes != nil { + in, out := &in.HTTPStatusCodes, &out.HTTPStatusCodes + *out = make([]HTTPStatus, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RetryOn. +func (in *RetryOn) DeepCopy() *RetryOn { + if in == nil { + return nil + } + out := new(RetryOn) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SecurityPolicy) DeepCopyInto(out *SecurityPolicy) { *out = *in @@ -2629,6 +3206,11 @@ func (in *SecurityPolicySpec) DeepCopyInto(out *SecurityPolicySpec) { *out = new(OIDC) (*in).DeepCopyInto(*out) } + if in.ExtAuth != nil { + in, out := &in.ExtAuth, &out.ExtAuth + *out = new(ExtAuth) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityPolicySpec. @@ -2724,26 +3306,26 @@ func (in *StringMatch) DeepCopy() *StringMatch { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *TCPHealthChecker) DeepCopyInto(out *TCPHealthChecker) { +func (in *TCPActiveHealthChecker) DeepCopyInto(out *TCPActiveHealthChecker) { *out = *in if in.Send != nil { in, out := &in.Send, &out.Send - *out = new(HealthCheckPayload) + *out = new(ActiveHealthCheckPayload) (*in).DeepCopyInto(*out) } if in.Receive != nil { in, out := &in.Receive, &out.Receive - *out = new(HealthCheckPayload) + *out = new(ActiveHealthCheckPayload) (*in).DeepCopyInto(*out) } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPHealthChecker. -func (in *TCPHealthChecker) DeepCopy() *TCPHealthChecker { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPActiveHealthChecker. +func (in *TCPActiveHealthChecker) DeepCopy() *TCPActiveHealthChecker { if in == nil { return nil } - out := new(TCPHealthChecker) + out := new(TCPActiveHealthChecker) in.DeepCopyInto(out) return out } @@ -2778,6 +3360,26 @@ func (in *TCPKeepalive) DeepCopy() *TCPKeepalive { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TCPTimeout) DeepCopyInto(out *TCPTimeout) { + *out = *in + if in.ConnectTimeout != nil { + in, out := &in.ConnectTimeout, &out.ConnectTimeout + *out = new(apisv1.Duration) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPTimeout. +func (in *TCPTimeout) DeepCopy() *TCPTimeout { + if in == nil { + return nil + } + out := new(TCPTimeout) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TLSSettings) DeepCopyInto(out *TLSSettings) { *out = *in @@ -2811,6 +3413,11 @@ func (in *TLSSettings) DeepCopyInto(out *TLSSettings) { *out = make([]ALPNProtocol, len(*in)) copy(*out, *in) } + if in.ClientValidation != nil { + in, out := &in.ClientValidation, &out.ClientValidation + *out = new(ClientValidationContext) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSSettings. @@ -2823,6 +3430,31 @@ func (in *TLSSettings) DeepCopy() *TLSSettings { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Timeout) DeepCopyInto(out *Timeout) { + *out = *in + if in.TCP != nil { + in, out := &in.TCP, &out.TCP + *out = new(TCPTimeout) + (*in).DeepCopyInto(*out) + } + if in.HTTP != nil { + in, out := &in.HTTP, &out.HTTP + *out = new(HTTPTimeout) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Timeout. +func (in *Timeout) DeepCopy() *Timeout { + if in == nil { + return nil + } + out := new(Timeout) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TracingProvider) DeepCopyInto(out *TracingProvider) { *out = *in @@ -2862,3 +3494,23 @@ func (in *XDSTranslatorHooks) DeepCopy() *XDSTranslatorHooks { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *XForwardedForSettings) DeepCopyInto(out *XForwardedForSettings) { + *out = *in + if in.NumTrustedHops != nil { + in, out := &in.NumTrustedHops, &out.NumTrustedHops + *out = new(uint32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new XForwardedForSettings. +func (in *XForwardedForSettings) DeepCopy() *XForwardedForSettings { + if in == nil { + return nil + } + out := new(XForwardedForSettings) + in.DeepCopyInto(out) + return out +} diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml index 36e51bcf023..2ba4265aeec 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -27,7 +27,7 @@ spec: schema: openAPIV3Schema: description: BackendTrafficPolicy allows the user to configure the behavior - of the connection between the downstream client and Envoy Proxy listener. + of the connection between the Envoy Proxy listener and the backend service. properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -76,7 +76,34 @@ spec: maximum: 4294967295 minimum: 0 type: integer + maxRequestsPerConnection: + description: 'The maximum number of requests that Envoy will make + over a single connection to the referenced backend defined within + a xRoute rule. Default: unlimited.' + format: int64 + maximum: 4294967295 + minimum: 0 + type: integer type: object + compression: + description: The compression config for the http streams. + items: + description: Compression defines the config of enabling compression. + This can help reduce the bandwidth at the expense of higher CPU. + properties: + gzip: + description: The configuration for GZIP compressor. + type: object + type: + description: CompressorType defines the compressor type to use + for compression. + enum: + - Gzip + type: string + required: + - type + type: object + type: array faultInjection: description: FaultInjection defines the fault injection policy to be applied. This configuration can be used to inject delays and @@ -135,173 +162,230 @@ spec: description: HealthCheck allows gateway to perform active health checking on backends. properties: - healthyThreshold: - default: 1 - description: HealthyThreshold defines the number of healthy health - checks required before a backend host is marked healthy. - format: int32 - minimum: 1 - type: integer - http: - description: HTTP defines the configuration of http health checker. - It's required while the health checker type is HTTP. + active: + description: Active health check configuration properties: - expectedResponse: - description: ExpectedResponse defines a list of HTTP expected - responses to match. + healthyThreshold: + default: 1 + description: HealthyThreshold defines the number of healthy + health checks required before a backend host is marked healthy. + format: int32 + minimum: 1 + type: integer + http: + description: HTTP defines the configuration of http health + checker. It's required while the health checker type is + HTTP. properties: - binary: - description: Binary payload base64 encoded. - format: byte - type: string - text: - description: Text payload in plain text. + expectedResponse: + description: ExpectedResponse defines a list of HTTP expected + responses to match. + properties: + binary: + description: Binary payload base64 encoded. + format: byte + type: string + text: + description: Text payload in plain text. + type: string + type: + allOf: + - enum: + - Text + - Binary + - enum: + - Text + - Binary + description: Type defines the type of the payload. + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: If payload type is Text, text field needs to + be set. + rule: 'self.type == ''Text'' ? has(self.text) : !has(self.text)' + - message: If payload type is Binary, binary field needs + to be set. + rule: 'self.type == ''Binary'' ? has(self.binary) : + !has(self.binary)' + expectedStatuses: + description: ExpectedStatuses defines a list of HTTP response + statuses considered healthy. Defaults to 200 only + items: + description: HTTPStatus defines the http status code. + exclusiveMaximum: true + maximum: 600 + minimum: 100 + type: integer + type: array + method: + description: Method defines the HTTP method used for health + checking. Defaults to GET type: string - type: - allOf: - - enum: - - Text - - Binary - - enum: - - Text - - Binary - description: Type defines the type of the payload. + path: + description: Path defines the HTTP path that will be requested + during health checking. + maxLength: 1024 + minLength: 1 type: string required: - - type + - path type: object - x-kubernetes-validations: - - message: If payload type is Text, text field needs to be - set. - rule: 'self.type == ''Text'' ? has(self.text) : !has(self.text)' - - message: If payload type is Binary, binary field needs to - be set. - rule: 'self.type == ''Binary'' ? has(self.binary) : !has(self.binary)' - expectedStatuses: - description: ExpectedStatuses defines a list of HTTP response - statuses considered healthy. Defaults to 200 only - items: - description: HTTPStatus defines the http status code. - exclusiveMaximum: true - maximum: 600 - minimum: 100 - type: integer - type: array - method: - description: Method defines the HTTP method used for health - checking. Defaults to GET + interval: + default: 3s + description: Interval defines the time between active health + checks. + format: duration type: string - path: - description: Path defines the HTTP path that will be requested - during health checking. - maxLength: 1024 - minLength: 1 + tcp: + description: TCP defines the configuration of tcp health checker. + It's required while the health checker type is TCP. + properties: + receive: + description: Receive defines the expected response payload. + properties: + binary: + description: Binary payload base64 encoded. + format: byte + type: string + text: + description: Text payload in plain text. + type: string + type: + allOf: + - enum: + - Text + - Binary + - enum: + - Text + - Binary + description: Type defines the type of the payload. + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: If payload type is Text, text field needs to + be set. + rule: 'self.type == ''Text'' ? has(self.text) : !has(self.text)' + - message: If payload type is Binary, binary field needs + to be set. + rule: 'self.type == ''Binary'' ? has(self.binary) : + !has(self.binary)' + send: + description: Send defines the request payload. + properties: + binary: + description: Binary payload base64 encoded. + format: byte + type: string + text: + description: Text payload in plain text. + type: string + type: + allOf: + - enum: + - Text + - Binary + - enum: + - Text + - Binary + description: Type defines the type of the payload. + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: If payload type is Text, text field needs to + be set. + rule: 'self.type == ''Text'' ? has(self.text) : !has(self.text)' + - message: If payload type is Binary, binary field needs + to be set. + rule: 'self.type == ''Binary'' ? has(self.binary) : + !has(self.binary)' + type: object + timeout: + default: 1s + description: Timeout defines the time to wait for a health + check response. + format: duration + type: string + type: + allOf: + - enum: + - HTTP + - TCP + - enum: + - HTTP + - TCP + description: Type defines the type of health checker. type: string + unhealthyThreshold: + default: 3 + description: UnhealthyThreshold defines the number of unhealthy + health checks required before a backend host is marked unhealthy. + format: int32 + minimum: 1 + type: integer required: - - path + - type type: object - interval: - default: 3s - description: Interval defines the time between health checks. - format: duration - type: string - tcp: - description: TCP defines the configuration of tcp health checker. - It's required while the health checker type is TCP. + x-kubernetes-validations: + - message: If Health Checker type is HTTP, http field needs to + be set. + rule: 'self.type == ''HTTP'' ? has(self.http) : !has(self.http)' + - message: If Health Checker type is TCP, tcp field needs to be + set. + rule: 'self.type == ''TCP'' ? has(self.tcp) : !has(self.tcp)' + passive: + description: Passive passive check configuration properties: - receive: - description: Receive defines the expected response payload. - properties: - binary: - description: Binary payload base64 encoded. - format: byte - type: string - text: - description: Text payload in plain text. - type: string - type: - allOf: - - enum: - - Text - - Binary - - enum: - - Text - - Binary - description: Type defines the type of the payload. - type: string - required: - - type - type: object - x-kubernetes-validations: - - message: If payload type is Text, text field needs to be - set. - rule: 'self.type == ''Text'' ? has(self.text) : !has(self.text)' - - message: If payload type is Binary, binary field needs to - be set. - rule: 'self.type == ''Binary'' ? has(self.binary) : !has(self.binary)' - send: - description: Send defines the request payload. - properties: - binary: - description: Binary payload base64 encoded. - format: byte - type: string - text: - description: Text payload in plain text. - type: string - type: - allOf: - - enum: - - Text - - Binary - - enum: - - Text - - Binary - description: Type defines the type of the payload. - type: string - required: - - type - type: object - x-kubernetes-validations: - - message: If payload type is Text, text field needs to be - set. - rule: 'self.type == ''Text'' ? has(self.text) : !has(self.text)' - - message: If payload type is Binary, binary field needs to - be set. - rule: 'self.type == ''Binary'' ? has(self.binary) : !has(self.binary)' + baseEjectionTime: + default: 30s + description: BaseEjectionTime defines the base duration for + which a host will be ejected on consecutive failures. + format: duration + type: string + consecutive5XxErrors: + default: 5 + description: Consecutive5xxErrors sets the number of consecutive + 5xx errors triggering ejection. + format: int32 + type: integer + consecutiveGatewayErrors: + default: 0 + description: ConsecutiveGatewayErrors sets the number of consecutive + gateway errors triggering ejection. + format: int32 + type: integer + consecutiveLocalOriginFailures: + default: 5 + description: ConsecutiveLocalOriginFailures sets the number + of consecutive local origin failures triggering ejection. + Parameter takes effect only when split_external_local_origin_errors + is set to true. + format: int32 + type: integer + interval: + default: 3s + description: Interval defines the time between passive health + checks. + format: duration + type: string + maxEjectionPercent: + default: 10 + description: MaxEjectionPercent sets the maximum percentage + of hosts in a cluster that can be ejected. + format: int32 + type: integer + splitExternalLocalOriginErrors: + default: false + description: SplitExternalLocalOriginErrors enables splitting + of errors between external and local origin. + type: boolean type: object - timeout: - default: 1s - description: Timeout defines the time to wait for a health check - response. - format: duration - type: string - type: - allOf: - - enum: - - HTTP - - TCP - - enum: - - HTTP - - TCP - description: Type defines the type of health checker. - type: string - unhealthyThreshold: - default: 3 - description: UnhealthyThreshold defines the number of unhealthy - health checks required before a backend host is marked unhealthy. - format: int32 - minimum: 1 - type: integer - required: - - type type: object - x-kubernetes-validations: - - message: If Health Checker type is HTTP, http field needs to be - set. - rule: 'self.type == ''HTTP'' ? has(self.http) : !has(self.http)' - - message: If Health Checker type is TCP, tcp field needs to be set. - rule: 'self.type == ''TCP'' ? has(self.tcp) : !has(self.tcp)' loadBalancer: description: LoadBalancer policy to apply when routing traffic from the gateway to the backend endpoints @@ -656,6 +740,82 @@ spec: required: - type type: object + retry: + description: Retry provides more advanced usage, allowing users to + customize the number of retries, retry fallback strategy, and retry + triggering conditions. If not set, retry will be disabled. + properties: + numRetries: + default: 2 + description: NumRetries is the number of retries to be attempted. + Defaults to 2. + format: int32 + minimum: 0 + type: integer + perRetry: + description: PerRetry is the retry policy to be applied per retry + attempt. + properties: + backOff: + description: Backoff is the backoff policy to be applied per + retry attempt. gateway uses a fully jittered exponential + back-off algorithm for retries. For additional details, + see https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/router_filter#config-http-filters-router-x-envoy-max-retries + properties: + baseInterval: + description: BaseInterval is the base interval between + retries. + format: duration + type: string + maxInterval: + description: MaxInterval is the maximum interval between + retries. This parameter is optional, but must be greater + than or equal to the base_interval if set. The default + is 10 times the base_interval + format: duration + type: string + type: object + timeout: + description: Timeout is the timeout per retry attempt. + format: duration + type: string + type: object + retryOn: + description: "RetryOn specifies the retry trigger condition. \n + If not specified, the default is to retry on connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes(503)." + properties: + httpStatusCodes: + description: HttpStatusCodes specifies the http status codes + to be retried. + items: + description: HTTPStatus defines the http status code. + exclusiveMaximum: true + maximum: 600 + minimum: 100 + type: integer + type: array + triggers: + description: Triggers specifies the retry trigger condition(Http/Grpc). + items: + description: TriggerEnum specifies the conditions that trigger + retries. + enum: + - 5xx + - gateway-error + - disconnect-reset + - connect-failure + - retriable-4xx + - refused-stream + - retriable-status-codes + - cancelled + - deadline-exceeded + - internal + - resource-exhausted + - unavailable + type: string + type: array + type: object + type: object targetRef: description: targetRef is the name of the resource this policy is being attached to. This Policy and the TargetRef MUST be in the @@ -734,6 +894,34 @@ spec: format: int32 type: integer type: object + timeout: + description: Timeout settings for the backend connections. + properties: + http: + description: Timeout settings for HTTP. + properties: + connectionIdleTimeout: + description: 'The idle timeout for an HTTP connection. Idle + time is defined as a period in which there are no active + requests in the connection. Default: 1 hour.' + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + maxConnectionDuration: + description: 'The maximum duration of an HTTP connection. + Default: unlimited.' + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + type: object + tcp: + description: Timeout settings for TCP. + properties: + connectTimeout: + description: 'The timeout for network connection establishment, + including TCP and TLS handshakes. Default: 10 seconds.' + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + type: object + type: object required: - targetRef type: object diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml index 7267fb6c874..83141a9c569 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml @@ -44,12 +44,90 @@ spec: spec: description: Spec defines the desired state of ClientTrafficPolicy. properties: + clientIPDetection: + description: ClientIPDetectionSettings provides configuration for + determining the original client IP address for requests. + properties: + customHeader: + description: CustomHeader provides configuration for determining + the client IP address for a request based on a trusted custom + HTTP header. This uses the the custom_header original IP detection + extension. Refer to https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/http/original_ip_detection/custom_header/v3/custom_header.proto + for more details. + properties: + failClosed: + description: FailClosed is a switch used to control the flow + of traffic when client IP detection fails. If set to true, + the listener will respond with 403 Forbidden when the client + IP address cannot be determined. + type: boolean + name: + description: Name of the header containing the original downstream + remote address, if present. + maxLength: 255 + minLength: 1 + pattern: ^[A-Za-z0-9-]+$ + type: string + required: + - name + type: object + xForwardedFor: + description: XForwardedForSettings provides configuration for + using X-Forwarded-For headers for determining the client IP + address. + properties: + numTrustedHops: + description: NumTrustedHops controls the number of additional + ingress proxy hops from the right side of XFF HTTP headers + to trust when determining the origin client's IP address. + Refer to https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers#x-forwarded-for + for more details. + format: int32 + type: integer + type: object + type: object + x-kubernetes-validations: + - message: customHeader cannot be used in conjunction with xForwardedFor + rule: '!(has(self.xForwardedFor) && has(self.customHeader))' enableProxyProtocol: description: EnableProxyProtocol interprets the ProxyProtocol header and adds the Client Address into the X-Forwarded-For header. Note Proxy Protocol must be present when this field is set, else the connection is closed. type: boolean + headers: + description: HeaderSettings provides configuration for header management. + properties: + enableEnvoyHeaders: + description: EnableEnvoyHeaders configures Envoy Proxy to add + the "X-Envoy-" headers to requests and responses. + type: boolean + type: object + http1: + description: HTTP1 provides HTTP/1 configuration on the listener. + properties: + enableTrailers: + description: EnableTrailers defines if HTTP/1 trailers should + be proxied by Envoy. + type: boolean + http10: + description: HTTP10 turns on support for HTTP/1.0 and HTTP/0.9 + requests. + properties: + useDefaultHost: + description: UseDefaultHost defines if the HTTP/1.0 request + is missing the Host header, then the hostname associated + with the listener should be injected into the request. If + this is not set and an HTTP/1.0 request arrives without + a host, then it will be rejected. + type: boolean + type: object + preserveHeaderCase: + description: PreserveHeaderCase defines if Envoy should preserve + the letter case of headers. By default, Envoy will lowercase + all the headers. + type: boolean + type: object http3: description: HTTP3 provides HTTP/3 configuration on the listener. type: object @@ -74,11 +152,6 @@ spec: - UnescapeAndRedirect type: string type: object - suppressEnvoyHeaders: - description: SuppressEnvoyHeaders configures the Envoy Router filter - to suppress the "x-envoy-' headers from both requests and responses. - By default these headers are added to both requests and responses. - type: boolean targetRef: description: TargetRef is the name of the Gateway resource this policy is being attached to. This Policy and the TargetRef MUST be in the @@ -157,6 +230,21 @@ spec: format: int32 type: integer type: object + timeout: + description: Timeout settings for the client connections. + properties: + http: + description: Timeout settings for HTTP. + properties: + requestReceivedTimeout: + description: The duration envoy waits for the complete request + reception. This timer starts upon request initiation and + stops when either the last byte of the request is sent upstream + or when the response begins. + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + type: object + type: object tls: description: TLS settings configure TLS termination settings with the downstream client. @@ -187,6 +275,68 @@ spec: items: type: string type: array + clientValidation: + description: ClientValidation specifies the configuration to validate + the client initiating the TLS connection to the Gateway listener. + properties: + caCertificateRefs: + description: "CACertificateRefs contains one or more references + to Kubernetes objects that contain TLS certificates of the + Certificate Authorities that can be used as a trust anchor + to validate the certificates presented by the client. \n + A single reference to a Kubernetes ConfigMap or a Kubernetes + Secret, with the CA certificate in a key named `ca.crt` + is currently supported. \n References to a resource in different + namespace are invalid UNLESS there is a ReferenceGrant in + the target namespace that allows the certificate to be attached." + items: + description: "SecretObjectReference identifies an API object + including its namespace, defaulting to Secret. \n The + API object must be valid in the cluster; the Group and + Kind must be registered in the cluster for this reference + to be valid. \n References to objects with invalid Group + and Kind are not valid, and must be rejected by the implementation, + with appropriate Conditions set on the containing object." + properties: + group: + default: "" + description: Group is the group of the referent. For + example, "gateway.networking.k8s.io". When unspecified + or empty string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Secret + description: Kind is kind of the referent. For example + "Secret". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referenced + object. When unspecified, the local namespace is inferred. + \n Note that when a namespace different than the local + namespace is specified, a ReferenceGrant object is + required in the referent namespace to allow that namespace's + owner to accept the reference. See the ReferenceGrant + documentation for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - name + type: object + maxItems: 8 + type: array + type: object ecdhCurves: description: 'ECDHCurves specifies the set of supported ECDH curves. In non-FIPS Envoy Proxy builds the default curves are: - X25519 diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoypatchpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoypatchpolicies.yaml index 339564310e5..55590b7d7f0 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoypatchpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoypatchpolicies.yaml @@ -56,6 +56,12 @@ spec: operation: description: Patch defines the JSON Patch Operation properties: + from: + description: From is the source location of the value to + be copied or moved. Only valid for move or copy operations + Refer to https://datatracker.ietf.org/doc/html/rfc6901 + for more details. + type: string op: description: Op is the type of operation to perform enum: @@ -73,11 +79,11 @@ spec: type: string value: description: Value is the new value of the path location. + The value is only used by the `add` and `replace` operations. x-kubernetes-preserve-unknown-fields: true required: - op - path - - value type: object type: description: Type is the typed URL of the Envoy xDS Resource @@ -86,6 +92,7 @@ spec: - type.googleapis.com/envoy.config.route.v3.RouteConfiguration - type.googleapis.com/envoy.config.cluster.v3.Cluster - type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment + - type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret type: string required: - name diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml index e22f535aecf..abb86ce60dd 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -71,6 +71,14 @@ spec: If unset, it defaults to the number of cpuset threads on the platform. format: int32 type: integer + extraArgs: + description: 'ExtraArgs defines additional command line options that + are provided to Envoy. More info: https://www.envoyproxy.io/docs/envoy/latest/operations/cli#command-line-options + Note: some command line options are used internally(e.g. --log-level) + so they cannot be provided here.' + items: + type: string + type: array logging: default: level: @@ -5973,6 +5981,9 @@ spec: cannot be less that minReplicas. format: int32 type: integer + x-kubernetes-validations: + - message: maxReplicas must be greater than 0 + rule: self > 0 metrics: description: metrics contains the specifications for which to use to calculate the desired replica count (the maximum @@ -6508,14 +6519,13 @@ spec: It defaults to 1 replica. format: int32 type: integer + x-kubernetes-validations: + - message: minReplicas must be greater than 0 + rule: self > 0 required: - maxReplicas type: object x-kubernetes-validations: - - message: minReplicas must be greater than 0 - rule: '!has(self.minReplicas) || self.minReplicas > 0' - - message: maxReplicas must be greater than 0 - rule: '!has(self.maxReplicas) || self.maxReplicas > 0' - message: maxReplicas cannot be less than minReplicas rule: '!has(self.minReplicas) || self.maxReplicas >= self.minReplicas' envoyService: @@ -6566,6 +6576,9 @@ spec: but it is still used for setting the IP Address in some cloud providers such as GCP. type: string + x-kubernetes-validations: + - message: loadBalancerIP must be a valid IPv4 address + rule: self.matches(r"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$") type: default: LoadBalancer description: Type determines how the Service is exposed. @@ -6590,8 +6603,6 @@ spec: - message: loadBalancerIP can only be set for LoadBalancer type rule: '!has(self.loadBalancerIP) || self.type == ''LoadBalancer''' - - message: loadBalancerIP must be a valid IPv4 address - rule: '!has(self.loadBalancerIP) || self.loadBalancerIP.matches(r"^(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4})")' type: object type: description: Type is the type of resource provider to use. A resource diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml index ae3a0489de0..7feb835b938 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -125,14 +125,16 @@ spec: items: description: "Origin is defined by the scheme (protocol), hostname (domain), and port of the URL used to access it. The hostname - can be “precise” which is just the domain name or “wildcard” + can be \"precise\" which is just the domain name or \"wildcard\" which is a domain name prefixed with a single wildcard label - such as “*.example.com”. \n For example, the following are - valid origins: - https://foo.example.com - https://*.example.com - - http://foo.example.com:8080 - http://*.example.com:8080" + such as \"*.example.com\". In addition to that a single wildcard + (with or without scheme) can be configured to match any origin. + \n For example, the following are valid origins: - https://foo.example.com + - https://*.example.com - http://foo.example.com:8080 - http://*.example.com:8080 + - https://*" maxLength: 253 minLength: 1 - pattern: ^https?:\/\/(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*(:[0-9]+)?$ + pattern: ^(\*|https?:\/\/(\*|(\*\.)?(([\w-]+\.?)+)?[\w-]+)(:\d{1,5})?)$ type: string minItems: 1 type: array @@ -147,6 +149,213 @@ spec: request can be cached. type: string type: object + extAuth: + description: ExtAuth defines the configuration for External Authorization. + properties: + grpc: + description: GRPC defines the gRPC External Authorization service. + Either GRPCService or HTTPService must be specified, and only + one of them can be provided. + properties: + backendRef: + description: BackendRef references a Kubernetes object that + represents the backend server to which the authorization + request will be sent. Only service Kind is supported for + now. + properties: + group: + default: "" + description: Group is the group of the referent. For example, + "gateway.networking.k8s.io". When unspecified or empty + string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: "Kind is the Kubernetes resource kind of + the referent. For example \"Service\". \n Defaults to + \"Service\" when not specified. \n ExternalName services + can refer to CNAME DNS records that may live outside + of the cluster and as such are difficult to reason about + in terms of conformance. They also may not be safe to + forward to (see CVE-2021-25740 for more information). + Implementations SHOULD NOT support ExternalName Services. + \n Support: Core (Services with a type other than ExternalName) + \n Support: Implementation-specific (Services with type + ExternalName)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the backend. + When unspecified, the local namespace is inferred. \n + Note that when a namespace different than the local + namespace is specified, a ReferenceGrant object is required + in the referent namespace to allow that namespace's + owner to accept the reference. See the ReferenceGrant + documentation for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port number + to use for this resource. Port is required when the + referent is a Kubernetes Service. In this case, the + port number is the service port number, not the target + port. For other resources, destination port might be + derived from the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' + required: + - backendRef + type: object + headersToExtAuth: + description: 'HeadersToExtAuth defines the client request headers + that will be included in the request to the external authorization + service. Note: If not specified, the default behavior for gRPC + and HTTP external authorization services is different due to + backward compatibility reasons. All headers will be included + in the check request to a gRPC authorization server. Only the + following headers will be included in the check request to an + HTTP authorization server: Host, Method, Path, Content-Length, + and Authorization. And these headers will always be included + to the check request to an HTTP authorization server by default, + no matter whether they are specified in HeadersToExtAuth or + not.' + items: + type: string + type: array + http: + description: HTTP defines the HTTP External Authorization service. + Either GRPCService or HTTPService must be specified, and only + one of them can be provided. + properties: + backendRef: + description: BackendRef references a Kubernetes object that + represents the backend server to which the authorization + request will be sent. Only service Kind is supported for + now. + properties: + group: + default: "" + description: Group is the group of the referent. For example, + "gateway.networking.k8s.io". When unspecified or empty + string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: "Kind is the Kubernetes resource kind of + the referent. For example \"Service\". \n Defaults to + \"Service\" when not specified. \n ExternalName services + can refer to CNAME DNS records that may live outside + of the cluster and as such are difficult to reason about + in terms of conformance. They also may not be safe to + forward to (see CVE-2021-25740 for more information). + Implementations SHOULD NOT support ExternalName Services. + \n Support: Core (Services with a type other than ExternalName) + \n Support: Implementation-specific (Services with type + ExternalName)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the backend. + When unspecified, the local namespace is inferred. \n + Note that when a namespace different than the local + namespace is specified, a ReferenceGrant object is required + in the referent namespace to allow that namespace's + owner to accept the reference. See the ReferenceGrant + documentation for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port number + to use for this resource. Port is required when the + referent is a Kubernetes Service. In this case, the + port number is the service port number, not the target + port. For other resources, destination port might be + derived from the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') + ? has(self.port) : true' + headersToBackend: + description: HeadersToBackend are the authorization response + headers that will be added to the original client request + before sending it to the backend server. Note that coexisting + headers will be overridden. If not specified, no authorization + response headers will be added to the original client request. + items: + type: string + type: array + path: + description: Path is the path of the HTTP External Authorization + service. If path is specified, the authorization request + will be sent to that path, or else the authorization request + will be sent to the root path. + type: string + required: + - backendRef + type: object + type: object + x-kubernetes-validations: + - message: one of grpc or http must be specified + rule: (has(self.grpc) || has(self.http)) + - message: only one of grpc or http can be specified + rule: (has(self.grpc) && !has(self.http)) || (!has(self.grpc) && + has(self.http)) + - message: group is invalid, only the core API group (specified by + omitting the group field or setting it to an empty string) is + supported + rule: 'has(self.grpc) ? (!has(self.grpc.backendRef.group) || self.grpc.backendRef.group + == "") : true' + - message: kind is invalid, only Service (specified by omitting the + kind field or setting it to 'Service') is supported + rule: 'has(self.grpc) ? (!has(self.grpc.backendRef.kind) || self.grpc.backendRef.kind + == ''Service'') : true' + - message: group is invalid, only the core API group (specified by + omitting the group field or setting it to an empty string) is + supported + rule: 'has(self.http) ? (!has(self.http.backendRef.group) || self.http.backendRef.group + == "") : true' + - message: kind is invalid, only Service (specified by omitting the + kind field or setting it to 'Service') is supported + rule: 'has(self.http) ? (!has(self.http.backendRef.kind) || self.http.backendRef.kind + == ''Service'') : true' jwt: description: JWT defines the configuration for JSON Web Token (JWT) authentication. @@ -202,10 +411,36 @@ spec: properties: cookies: description: Cookies represents a list of cookie names - to extract the JWT token from. If specified, Envoy - will extract the JWT token from the listed cookies - and validate each of them. If any cookie is found - to be an invalid JWT, a 401 error will be returned. + to extract the JWT token from. + items: + type: string + type: array + headers: + description: Headers represents a list of HTTP request + headers to extract the JWT token from. + items: + description: JWTHeaderExtractor defines an HTTP header + location to extract JWT token + properties: + name: + description: Name is the HTTP header name to retrieve + the token + type: string + valuePrefix: + description: 'ValuePrefix is the prefix that should + be stripped before extracting the token. The + format would be used by Envoy like "{ValuePrefix}". + For example, "Authorization: Bearer ", + then the ValuePrefix="Bearer " with a space + at the end.' + type: string + required: + - name + type: object + type: array + params: + description: Params represents a list of query parameters + to extract the JWT token from. items: type: string type: array @@ -349,7 +584,7 @@ spec: description: TargetRef is the name of the Gateway resource this policy is being attached to. This Policy and the TargetRef MUST be in the same namespace for this Policy to have effect and be applied to - the Gateway. TargetRef + the Gateway. properties: group: description: Group is the group of the target resource. diff --git a/charts/gateway-helm/templates/_rbac.tpl b/charts/gateway-helm/templates/_rbac.tpl index c009b66a33b..9c80ff3a868 100644 --- a/charts/gateway-helm/templates/_rbac.tpl +++ b/charts/gateway-helm/templates/_rbac.tpl @@ -29,6 +29,7 @@ Namespaced apiGroups: - "" resources: +- configmaps - secrets - services verbs: @@ -71,8 +72,6 @@ resources: verbs: - get - list -- patch -- update - watch {{- end }} @@ -96,15 +95,12 @@ resources: - grpcroutes - httproutes - referencegrants -- referencepolicies - tcproutes - tlsroutes - udproutes verbs: - get - list -- patch -- update - watch {{- end }} diff --git a/charts/gateway-helm/templates/certgen.yaml b/charts/gateway-helm/templates/certgen.yaml index 3a228b7959f..bea4792f242 100644 --- a/charts/gateway-helm/templates/certgen.yaml +++ b/charts/gateway-helm/templates/certgen.yaml @@ -34,6 +34,10 @@ spec: image: {{ .Values.deployment.envoyGateway.image.repository }}:{{ .Values.deployment.envoyGateway.image.tag | default .Chart.AppVersion }} imagePullPolicy: {{ .Values.deployment.envoyGateway.imagePullPolicy }} name: envoy-gateway-certgen + {{- with .Values.certgen.job.resources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} {{- with .Values.deployment.envoyGateway.imagePullSecrets }} imagePullSecrets: {{- toYaml . | nindent 8 }} diff --git a/charts/gateway-helm/templates/proxy-rbac.yaml b/charts/gateway-helm/templates/proxy-rbac.yaml deleted file mode 100644 index 0ed136a7c86..00000000000 --- a/charts/gateway-helm/templates/proxy-rbac.yaml +++ /dev/null @@ -1,34 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ include "eg.fullname" . }}-proxy-role - labels: - {{- include "eg.labels" . | nindent 4 }} -rules: -- apiGroups: - - authentication.k8s.io - resources: - - tokenreviews - verbs: - - create -- apiGroups: - - authorization.k8s.io - resources: - - subjectaccessreviews - verbs: - - create ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ include "eg.fullname" . }}-proxy-rolebinding - labels: - {{- include "eg.labels" . | nindent 4 }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: '{{ include "eg.fullname" . }}-proxy-role' -subjects: -- kind: ServiceAccount - name: 'envoy-gateway' - namespace: '{{ .Release.Namespace }}' diff --git a/charts/gateway-helm/values.tmpl.yaml b/charts/gateway-helm/values.tmpl.yaml index ea6e7125a9c..fb9c1ae4ebe 100644 --- a/charts/gateway-helm/values.tmpl.yaml +++ b/charts/gateway-helm/values.tmpl.yaml @@ -49,6 +49,7 @@ kubernetesClusterDomain: cluster.local certgen: job: annotations: {} + resources: {} ttlSecondsAfterFinished: 0 rbac: annotations: {} diff --git a/go.mod b/go.mod index 8e4150fa20b..03c3b870e4f 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,11 @@ module github.com/envoyproxy/gateway go 1.21 require ( - github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 + github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 github.com/davecgh/go-spew v1.1.1 github.com/envoyproxy/go-control-plane v0.12.0 github.com/envoyproxy/ratelimit v1.4.1-0.20230427142404-e2a87f41d3a7 - github.com/evanphx/json-patch/v5 v5.7.0 + github.com/evanphx/json-patch/v5 v5.9.0 github.com/go-logfmt/logfmt v0.6.0 github.com/go-logr/logr v1.4.1 github.com/go-logr/zapr v1.3.0 @@ -15,35 +15,34 @@ require ( github.com/golang/protobuf v1.5.3 github.com/google/go-cmp v0.6.0 github.com/grafana/tempo v1.5.0 - github.com/miekg/dns v1.1.57 + github.com/miekg/dns v1.1.58 github.com/prometheus/client_golang v1.18.0 - github.com/prometheus/common v0.45.0 + github.com/prometheus/common v0.47.0 github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.4 github.com/telepresenceio/watchable v0.0.0-20220726211108-9bb86f92afa7 - github.com/tetratelabs/multierror v1.1.1 - github.com/tsaarni/certyaml v0.9.2 - go.opentelemetry.io/otel v1.21.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.44.0 - go.opentelemetry.io/otel/exporters/prometheus v0.44.0 - go.opentelemetry.io/otel/metric v1.21.0 - go.opentelemetry.io/otel/sdk/metric v1.21.0 - go.opentelemetry.io/proto/otlp v1.0.0 + github.com/tsaarni/certyaml v0.9.3 + go.opentelemetry.io/otel v1.23.1 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.23.1 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.23.1 + go.opentelemetry.io/otel/exporters/prometheus v0.45.0 + go.opentelemetry.io/otel/metric v1.23.1 + go.opentelemetry.io/otel/sdk/metric v1.23.1 + go.opentelemetry.io/proto/otlp v1.1.0 go.uber.org/zap v1.26.0 golang.org/x/exp v0.0.0-20231006140011-7918f672742d - google.golang.org/grpc v1.60.1 + google.golang.org/grpc v1.61.1 google.golang.org/protobuf v1.32.0 gopkg.in/yaml.v3 v3.0.1 - k8s.io/api v0.29.0 - k8s.io/apiextensions-apiserver v0.29.0 - k8s.io/apimachinery v0.29.0 - k8s.io/cli-runtime v0.29.0 - k8s.io/client-go v0.29.0 - k8s.io/kubectl v0.29.0 + k8s.io/api v0.29.2 + k8s.io/apiextensions-apiserver v0.29.2 + k8s.io/apimachinery v0.29.2 + k8s.io/cli-runtime v0.29.2 + k8s.io/client-go v0.29.2 + k8s.io/kubectl v0.29.2 k8s.io/utils v0.0.0-20230726121419-3b25d923346b - sigs.k8s.io/controller-runtime v0.16.3 + sigs.k8s.io/controller-runtime v0.17.2 sigs.k8s.io/gateway-api v1.0.0 sigs.k8s.io/mcs-api v0.1.0 sigs.k8s.io/yaml v1.4.0 @@ -62,7 +61,7 @@ require ( github.com/evanphx/json-patch v5.7.0+incompatible // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect + github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect github.com/go-errors/errors v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.20.0 // indirect @@ -73,11 +72,10 @@ require ( github.com/google/gnostic-models v0.6.8 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/google/uuid v1.3.1 // indirect + github.com/google/uuid v1.4.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect @@ -86,7 +84,6 @@ require ( github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/lyft/gostats v0.4.1 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/moby/spdystream v0.2.0 // indirect github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect @@ -104,27 +101,27 @@ require ( github.com/sirupsen/logrus v1.9.0 // indirect github.com/tsaarni/x500dn v1.0.0 // indirect github.com/xlab/treeprint v1.2.0 // indirect - go.opentelemetry.io/otel/sdk v1.21.0 // indirect - go.opentelemetry.io/otel/trace v1.21.0 // indirect + go.opentelemetry.io/otel/sdk v1.23.1 // indirect + go.opentelemetry.io/otel/trace v1.23.1 // indirect go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/mod v0.13.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/oauth2 v0.13.0 // indirect - golang.org/x/sync v0.4.0 // indirect - golang.org/x/sys v0.15.0 // indirect - golang.org/x/term v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/oauth2 v0.16.0 // indirect + golang.org/x/sync v0.6.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/term v0.16.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.14.0 // indirect + golang.org/x/tools v0.17.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 // indirect + google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/component-base v0.29.0 // indirect + k8s.io/component-base v0.29.2 // indirect k8s.io/klog/v2 v2.110.1 // indirect k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect diff --git a/go.sum b/go.sum index fc768bce099..25bd45172f1 100644 --- a/go.sum +++ b/go.sum @@ -51,8 +51,8 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbinPNFs5gPSBOsJtx3wTT94VBY= +github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -105,8 +105,8 @@ github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI= github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.0.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= -github.com/evanphx/json-patch/v5 v5.7.0 h1:nJqP7uwL84RJInrohHfW0Fx3awjbm8qZeFv0nW9SYGc= -github.com/evanphx/json-patch/v5 v5.7.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= +github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -118,8 +118,8 @@ github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2H github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= -github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A= -github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= +github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA= +github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -198,8 +198,6 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= -github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= @@ -249,8 +247,8 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= @@ -270,10 +268,8 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= @@ -335,10 +331,8 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= -github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= -github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= +github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4= +github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= @@ -371,15 +365,15 @@ github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= -github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= +github.com/onsi/ginkgo/v2 v2.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY= +github.com/onsi/ginkgo/v2 v2.14.0/go.mod h1:JkUdW7JkN0V6rFvsHcJ478egV3XH9NxpD27Hal/PhZw= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= -github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= +github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= @@ -406,8 +400,8 @@ github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= -github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/common v0.47.0 h1:p5Cz0FNHo7SnWOmWmoRozVcjEp0bIVU8cV7OShpjL1k= +github.com/prometheus/common v0.47.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -467,13 +461,11 @@ github.com/telepresenceio/telepresence/rpc/v2 v2.6.8 h1:q5V85LBT9bA/c4YPa/kMvJGy github.com/telepresenceio/telepresence/rpc/v2 v2.6.8/go.mod h1:VlgfRoXaW6Tl8IZbHmMWhITne8HY09/wOFtABHGj3ic= github.com/telepresenceio/watchable v0.0.0-20220726211108-9bb86f92afa7 h1:GMw3nEaOVyi+tNiGko5kAeRtoiEIpXNHmISyZ7fpw14= github.com/telepresenceio/watchable v0.0.0-20220726211108-9bb86f92afa7/go.mod h1:ihJ97e2gsd8GuzFF/I3B1qcik3XZLpXjumQifXi8Slg= -github.com/tetratelabs/multierror v1.1.1 h1:84JfJvfmnYC5y4877Ag3c4PkCUmQwq6sGI6iRfBATKI= -github.com/tetratelabs/multierror v1.1.1/go.mod h1:hAyQ/XifPOPdb0x3GsowbjsjCPgT9Fsxjety9TxmuGY= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tsaarni/certyaml v0.9.2 h1:LoRTuajwjJ1CHAJiMv5cpOtwQ05207Oqe6cT9D7WDaQ= -github.com/tsaarni/certyaml v0.9.2/go.mod h1:s+ErAC1wZ32r1ihSULvR7HXedKKN5HZasdb8Cj8gT9E= +github.com/tsaarni/certyaml v0.9.3 h1:m8HHbuUzWVUOmv8IQU9HgVZZ8r5ICExKm++54DJKCs0= +github.com/tsaarni/certyaml v0.9.3/go.mod h1:hhuU1qYr5re488geArUP4gZWqMUMqGlj4HA2qUyGYLk= github.com/tsaarni/x500dn v1.0.0 h1:LvaWTkqRpse4VHBhB5uwf3wytokK4vF9IOyNAEyiA+U= github.com/tsaarni/x500dn v1.0.0/go.mod h1:QaHa3EcUKC4dfCAZmj8+ZRGLKukWgpGv9H3oOCsAbcE= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= @@ -494,30 +486,30 @@ go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qL go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= -go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0 h1:jd0+5t/YynESZqsSyPz+7PAFdEop0dlN0+PkyHYo8oI= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0/go.mod h1:U707O40ee1FpQGyhvqnzmCJm1Wh6OX6GGBVn0E6Uyyk= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.44.0 h1:bflGWrfYyuulcdxf14V6n9+CoQcu5SAAdHmDPAJnlps= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.44.0/go.mod h1:qcTO4xHAxZLaLxPd60TdE88rxtItPHgHWqOhOGRr0as= -go.opentelemetry.io/otel/exporters/prometheus v0.44.0 h1:08qeJgaPC0YEBu2PQMbqU3rogTlyzpjhCI2b58Yn00w= -go.opentelemetry.io/otel/exporters/prometheus v0.44.0/go.mod h1:ERL2uIeBtg4TxZdojHUwzZfIFlUIjZtxubT5p4h1Gjg= -go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= -go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= -go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= -go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= -go.opentelemetry.io/otel/sdk/metric v1.21.0 h1:smhI5oD714d6jHE6Tie36fPx4WDFIg+Y6RfAY4ICcR0= -go.opentelemetry.io/otel/sdk/metric v1.21.0/go.mod h1:FJ8RAsoPGv/wYMgBdUJXOm+6pzFY3YdljnXtv1SBE8Q= -go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= -go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.opentelemetry.io/otel v1.23.1 h1:Za4UzOqJYS+MUczKI320AtqZHZb7EqxO00jAHE0jmQY= +go.opentelemetry.io/otel v1.23.1/go.mod h1:Td0134eafDLcTS4y+zQ26GE8u3dEuRBiBCTUIRHaikA= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.23.1 h1:ZqRWZJGHXV/1yCcEEVJ6/Uz2JtM79DNS8OZYa3vVY/A= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.23.1/go.mod h1:D7ynngPWlGJrqyGSDOdscuv7uqttfCE3jcBvffDv9y4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.23.1 h1:q/Nj5/2TZRIt6PderQ9oU0M00fzoe8UZuINGw6ETGTw= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.23.1/go.mod h1:DTE9yAu6r08jU3xa68GiSeI7oRcSEQ2RpKbbQGO+dWM= +go.opentelemetry.io/otel/exporters/prometheus v0.45.0 h1:BeIK2KGho0oCWa7LxEGSqfDZbs7Fpv/Viz+FS4P8CXE= +go.opentelemetry.io/otel/exporters/prometheus v0.45.0/go.mod h1:UVJZPLnfDSvHj+eJuZE+E1GjIBD267mEMfAAHJdghWg= +go.opentelemetry.io/otel/metric v1.23.1 h1:PQJmqJ9u2QaJLBOELl1cxIdPcpbwzbkjfEyelTl2rlo= +go.opentelemetry.io/otel/metric v1.23.1/go.mod h1:mpG2QPlAfnK8yNhNJAxDZruU9Y1/HubbC+KyH8FaCWI= +go.opentelemetry.io/otel/sdk v1.23.1 h1:O7JmZw0h76if63LQdsBMKQDWNb5oEcOThG9IrxscV+E= +go.opentelemetry.io/otel/sdk v1.23.1/go.mod h1:LzdEVR5am1uKOOwfBWFef2DCi1nu3SA8XQxx2IerWFk= +go.opentelemetry.io/otel/sdk/metric v1.23.1 h1:T9/8WsYg+ZqIpMWwdISVVrlGb/N0Jr1OHjR/alpKwzg= +go.opentelemetry.io/otel/sdk/metric v1.23.1/go.mod h1:8WX6WnNtHCgUruJ4TJ+UssQjMtpxkpX0zveQC8JG/E0= +go.opentelemetry.io/otel/trace v1.23.1 h1:4LrmmEd8AU2rFvU1zegmvqW7+kWarxtNOPyeL6HmYY8= +go.opentelemetry.io/otel/trace v1.23.1/go.mod h1:4IpnpJFwr1mo/6HL8XIPJaE9y0+u1KcVmuW7dwFSVrI= +go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= +go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= -go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= @@ -545,8 +537,8 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -570,13 +562,13 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= -golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= +golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= +golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -585,8 +577,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -617,13 +609,13 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -631,8 +623,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -655,8 +647,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= -golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= +golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -675,12 +667,12 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0= -google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97/go.mod h1:t1VqOqqvce95G3hIDCT5FeO3YUc6Q4Oe24L/+rNMxRk= -google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU= -google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY= +google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 h1:YJ5pD9rF8o9Qtta0Cmy9rdBwkSjrTCT6XTiUQVOtIos= +google.golang.org/genproto v0.0.0-20231212172506-995d672761c0/go.mod h1:l/k7rMz0vFTBPy+tFSGvXEd3z+BcoG1k7EHbqm+YBsY= +google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 h1:rcS6EyEaoCO52hQDupoSfrxI3R6C2Tq741is7X8OvnM= +google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 h1:6G8oQ016D88m1xAKljMlBOOGWDZkes4kMhgGFlf8WcQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= @@ -688,8 +680,8 @@ google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= -google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/grpc v1.61.1 h1:kLAiWrZs7YeDM6MumDe7m3y4aM6wacLzM1Y/wiLP9XY= +google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -736,30 +728,30 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78= k8s.io/api v0.18.4/go.mod h1:lOIQAKYgai1+vz9J7YcDZwC26Z0zQewYOGWdyIPUUQ4= -k8s.io/api v0.29.0 h1:NiCdQMY1QOp1H8lfRyeEf8eOwV6+0xA6XEE44ohDX2A= -k8s.io/api v0.29.0/go.mod h1:sdVmXoz2Bo/cb77Pxi71IPTSErEW32xa4aXwKH7gfBA= +k8s.io/api v0.29.2 h1:hBC7B9+MU+ptchxEqTNW2DkUosJpp1P+Wn6YncZ474A= +k8s.io/api v0.29.2/go.mod h1:sdIaaKuU7P44aoyyLlikSLayT6Vb7bvJNCX105xZXY0= k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY= k8s.io/apiextensions-apiserver v0.18.4/go.mod h1:NYeyeYq4SIpFlPxSAB6jHPIdvu3hL0pc36wuRChybio= -k8s.io/apiextensions-apiserver v0.29.0 h1:0VuspFG7Hj+SxyF/Z/2T0uFbI5gb5LRgEyUVE3Q4lV0= -k8s.io/apiextensions-apiserver v0.29.0/go.mod h1:TKmpy3bTS0mr9pylH0nOt/QzQRrW7/h7yLdRForMZwc= +k8s.io/apiextensions-apiserver v0.29.2 h1:UK3xB5lOWSnhaCk0RFZ0LUacPZz9RY4wi/yt2Iu+btg= +k8s.io/apiextensions-apiserver v0.29.2/go.mod h1:aLfYjpA5p3OwtqNXQFkhJ56TB+spV8Gc4wfMhUA3/b8= k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= k8s.io/apimachinery v0.18.4/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= -k8s.io/apimachinery v0.29.0 h1:+ACVktwyicPz0oc6MTMLwa2Pw3ouLAfAon1wPLtG48o= -k8s.io/apimachinery v0.29.0/go.mod h1:eVBxQ/cwiJxH58eK/jd/vAk4mrxmVlnpBH5J2GbMeis= +k8s.io/apimachinery v0.29.2 h1:EWGpfJ856oj11C52NRCHuU7rFDwxev48z+6DSlGNsV8= +k8s.io/apimachinery v0.29.2/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU= k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw= k8s.io/apiserver v0.18.4/go.mod h1:q+zoFct5ABNnYkGIaGQ3bcbUNdmPyOCoEBcg51LChY8= -k8s.io/cli-runtime v0.29.0 h1:q2kC3cex4rOBLfPOnMSzV2BIrrQlx97gxHJs21KxKS4= -k8s.io/cli-runtime v0.29.0/go.mod h1:VKudXp3X7wR45L+nER85YUzOQIru28HQpXr0mTdeCrk= +k8s.io/cli-runtime v0.29.2 h1:smfsOcT4QujeghsNjECKN3lwyX9AwcFU0nvJ7sFN3ro= +k8s.io/cli-runtime v0.29.2/go.mod h1:KLisYYfoqeNfO+MkTWvpqIyb1wpJmmFJhioA0xd4MW8= k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU= k8s.io/client-go v0.18.4/go.mod h1:f5sXwL4yAZRkAtzOxRWUhA/N8XzGCb+nPZI8PfobZ9g= -k8s.io/client-go v0.29.0 h1:KmlDtFcrdUzOYrBhXHgKw5ycWzc3ryPX5mQe0SkG3y8= -k8s.io/client-go v0.29.0/go.mod h1:yLkXH4HKMAywcrD82KMSmfYg2DlE8mepPR4JGSo5n38= +k8s.io/client-go v0.29.2 h1:FEg85el1TeZp+/vYJM7hkDlSTFZ+c5nnK44DJ4FyoRg= +k8s.io/client-go v0.29.2/go.mod h1:knlvFZE58VpqbQpJNbCbctTVXcd35mMyAAwBdpt4jrA= k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc= k8s.io/code-generator v0.18.4/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c= k8s.io/component-base v0.18.2/go.mod h1:kqLlMuhJNHQ9lz8Z7V5bxUUtjFZnrypArGl58gmDfUM= k8s.io/component-base v0.18.4/go.mod h1:7jr/Ef5PGmKwQhyAz/pjByxJbC58mhKAhiaDu0vXfPk= -k8s.io/component-base v0.29.0 h1:T7rjd5wvLnPBV1vC4zWd/iWRbV8Mdxs+nGaoaFzGw3s= -k8s.io/component-base v0.29.0/go.mod h1:sADonFTQ9Zc9yFLghpDpmNXEdHyQmFIGbiuZbqAXQ1M= +k8s.io/component-base v0.29.2 h1:lpiLyuvPA9yV1aQwGLENYyK7n/8t6l3nn3zAtFTJYe8= +k8s.io/component-base v0.29.2/go.mod h1:BfB3SLrefbZXiBfbM+2H1dlat21Uewg/5qtKOl8degM= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= @@ -772,16 +764,16 @@ k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= -k8s.io/kubectl v0.29.0 h1:Oqi48gXjikDhrBF67AYuZRTcJV4lg2l42GmvsP7FmYI= -k8s.io/kubectl v0.29.0/go.mod h1:0jMjGWIcMIQzmUaMgAzhSELv5WtHo2a8pq67DtviAJs= +k8s.io/kubectl v0.29.2 h1:uaDYaBhumvkwz0S2XHt36fK0v5IdNgL7HyUniwb2IUo= +k8s.io/kubectl v0.29.2/go.mod h1:BhizuYBGcKaHWyq+G7txGw2fXg576QbPrrnQdQDZgqI= k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0= sigs.k8s.io/controller-runtime v0.6.1/go.mod h1:XRYBPdbf5XJu9kpS84VJiZ7h/u1hF3gEORz0efEja7A= -sigs.k8s.io/controller-runtime v0.16.3 h1:2TuvuokmfXvDUamSx1SuAOO3eTyye+47mJCigwG62c4= -sigs.k8s.io/controller-runtime v0.16.3/go.mod h1:j7bialYoSn142nv9sCOJmQgDXQXxnroFU4VnX/brVJ0= +sigs.k8s.io/controller-runtime v0.17.2 h1:FwHwD1CTUemg0pW2otk7/U5/i5m2ymzvOXdbeGOUvw0= +sigs.k8s.io/controller-runtime v0.17.2/go.mod h1:+MngTvIQQQhfXtwfdGw/UOQ/aIaqsYywfCINOtwMO/s= sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI= sigs.k8s.io/gateway-api v1.0.0 h1:iPTStSv41+d9p0xFydll6d7f7MOBGuqXM6p2/zVYMAs= sigs.k8s.io/gateway-api v1.0.0/go.mod h1:4cUgr0Lnp5FZ0Cdq8FdRwCvpiWws7LVhLHGIudLlf4c= diff --git a/internal/admin/server_test.go b/internal/admin/server_test.go index 199ac95853b..f5227080d4c 100644 --- a/internal/admin/server_test.go +++ b/internal/admin/server_test.go @@ -8,7 +8,7 @@ package admin import ( "testing" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/envoygateway/config" @@ -21,5 +21,5 @@ func TestInitAdminServer(t *testing.T) { }, } err := Init(svrConfig) - assert.NoError(t, err) + require.NoError(t, err) } diff --git a/internal/cmd/egctl/config.go b/internal/cmd/egctl/config.go index 09b405b7cae..83fafa69c70 100644 --- a/internal/cmd/egctl/config.go +++ b/internal/cmd/egctl/config.go @@ -8,13 +8,13 @@ package egctl import ( "context" "encoding/json" + "errors" "fmt" "io" "net/http" "sync" adminv3 "github.com/envoyproxy/go-control-plane/envoy/admin/v3" - "github.com/tetratelabs/multierror" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/reflect/protoreflect" corev1 "k8s.io/api/core/v1" @@ -81,12 +81,12 @@ func retrieveConfigDump(args []string, includeEds bool, configType envoyConfigTy go func() { fw, err := portForwarder(cli, pod) if err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) return } if err := fw.Start(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) return } defer fw.Stop() @@ -94,7 +94,7 @@ func retrieveConfigDump(args []string, includeEds bool, configType envoyConfigTy configDump, err := extractConfigDump(fw, includeEds, configType) if err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) return } diff --git a/internal/cmd/egctl/config_test.go b/internal/cmd/egctl/config_test.go index 3dd6f65957d..47a70c19fde 100644 --- a/internal/cmd/egctl/config_test.go +++ b/internal/cmd/egctl/config_test.go @@ -81,11 +81,11 @@ func (fw *fakePortForwarder) Address() string { func TestExtractAllConfigDump(t *testing.T) { input, err := readInputConfig("in.all.json") - assert.NoError(t, err) + require.NoError(t, err) fw, err := newFakePortForwarder(input) - assert.NoError(t, err) + require.NoError(t, err) err = fw.Start() - assert.NoError(t, err) + require.NoError(t, err) cases := []struct { output string @@ -105,15 +105,15 @@ func TestExtractAllConfigDump(t *testing.T) { for _, tc := range cases { t.Run(tc.expected, func(t *testing.T) { configDump, err := extractConfigDump(fw, true, AllEnvoyConfigType) - assert.NoError(t, err) + require.NoError(t, err) aggregated := sampleAggregatedConfigDump(configDump) got, err := marshalEnvoyProxyConfig(aggregated, tc.output) - assert.NoError(t, err) + require.NoError(t, err) if *overrideTestData { require.NoError(t, file.Write(string(got), filepath.Join("testdata", "config", "out", tc.expected))) } out, err := readOutputConfig(tc.expected) - assert.NoError(t, err) + require.NoError(t, err) if tc.output == "yaml" { assert.YAMLEq(t, string(out), string(got)) } else { @@ -127,11 +127,11 @@ func TestExtractAllConfigDump(t *testing.T) { func TestExtractSubResourcesConfigDump(t *testing.T) { input, err := readInputConfig("in.all.json") - assert.NoError(t, err) + require.NoError(t, err) fw, err := newFakePortForwarder(input) - assert.NoError(t, err) + require.NoError(t, err) err = fw.Start() - assert.NoError(t, err) + require.NoError(t, err) cases := []struct { output string @@ -190,15 +190,15 @@ func TestExtractSubResourcesConfigDump(t *testing.T) { for _, tc := range cases { t.Run(tc.expected, func(t *testing.T) { configDump, err := extractConfigDump(fw, false, tc.resourceType) - assert.NoError(t, err) + require.NoError(t, err) aggregated := sampleAggregatedConfigDump(configDump) got, err := marshalEnvoyProxyConfig(aggregated, tc.output) - assert.NoError(t, err) + require.NoError(t, err) if *overrideTestData { require.NoError(t, file.Write(string(got), filepath.Join("testdata", "config", "out", tc.expected))) } out, err := readOutputConfig(tc.expected) - assert.NoError(t, err) + require.NoError(t, err) if tc.output == "yaml" { assert.YAMLEq(t, string(out), string(got)) } else { @@ -239,7 +239,7 @@ func TestLabelSelectorBadInput(t *testing.T) { t.Run(tc.name, func(t *testing.T) { labelSelectors = tc.labels _, err := retrieveConfigDump(tc.args, false, AllEnvoyConfigType) - assert.True(t, err != nil, "error not found") + require.Error(t, err, "error not found") }) } } diff --git a/internal/cmd/egctl/envoy_stats.go b/internal/cmd/egctl/envoy_stats.go index 8df0dec5ba7..527529c9cbf 100644 --- a/internal/cmd/egctl/envoy_stats.go +++ b/internal/cmd/egctl/envoy_stats.go @@ -7,13 +7,13 @@ package egctl import ( "encoding/json" + "errors" "fmt" "io" "net/http" "sync" "github.com/spf13/cobra" - "github.com/tetratelabs/multierror" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/yaml" @@ -74,7 +74,7 @@ func newEnvoyStatsCmd() *cobra.Command { go func(pod types.NamespacedName) { stats[pod.Namespace+"/"+pod.Name], err = setupEnvoyServerStatsConfig(kubeClient, pod.Name, pod.Namespace, outputFormat) if err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } wg.Done() }(pod) @@ -87,7 +87,7 @@ func newEnvoyStatsCmd() *cobra.Command { go func(pod types.NamespacedName) { stats[pod.Namespace+"/"+pod.Name], err = setupEnvoyClusterStatsConfig(kubeClient, pod.Name, pod.Namespace, outputFormat) if err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } wg.Done() }(pod) diff --git a/internal/cmd/egctl/experimental.go b/internal/cmd/egctl/experimental.go index 7fb744fb8de..e22dc3e6ca6 100644 --- a/internal/cmd/egctl/experimental.go +++ b/internal/cmd/egctl/experimental.go @@ -22,8 +22,9 @@ func newExperimentalCommand() *cobra.Command { `, } - experimentalCommand.AddCommand(NewTranslateCommand()) - experimentalCommand.AddCommand(statsCommand()) + experimentalCommand.AddCommand(newTranslateCommand()) + experimentalCommand.AddCommand(newStatsCommand()) + experimentalCommand.AddCommand(newStatusCommand()) return experimentalCommand } diff --git a/internal/cmd/egctl/stats.go b/internal/cmd/egctl/stats.go index a1633872178..bf9554be86b 100644 --- a/internal/cmd/egctl/stats.go +++ b/internal/cmd/egctl/stats.go @@ -9,7 +9,7 @@ import ( "github.com/spf13/cobra" ) -func statsCommand() *cobra.Command { +func newStatsCommand() *cobra.Command { c := &cobra.Command{ Use: "stats", Long: "Retrieve statistics from envoy proxy.", diff --git a/internal/cmd/egctl/status.go b/internal/cmd/egctl/status.go new file mode 100644 index 00000000000..3a23b36afe4 --- /dev/null +++ b/internal/cmd/egctl/status.go @@ -0,0 +1,385 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package egctl + +import ( + "context" + "fmt" + "io" + "os" + "reflect" + "strconv" + "strings" + "text/tabwriter" + + "github.com/spf13/cobra" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + gwv1 "sigs.k8s.io/gateway-api/apis/v1" + gwv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" +) + +// supportedTypes list all the resource types that status command supports. +var supportedTypes = []string{ + "GatewayClass", "Gateway", "HTTPRoute", "GRPCRoute", + "TLSRoute", "TCPRoute", "UDPRoute", "BackendTLSPolicy", + "BackendTrafficPolicy", "ClientTrafficPolicy", "EnvoyPatchPolicy", "SecurityPolicy", +} + +func newStatusCommand() *cobra.Command { + var ( + quiet, verbose, allNamespaces bool + resourceType, namespace string + ) + + statusCommand := &cobra.Command{ + Use: "status", + Short: "Show the summary of the status of resources in Envoy Gateway", + Example: ` # Show the status of gatewayclass resources under default namespace. + egctl x status gatewayclass + + # Show the status of gateway resources with less information under default namespace. + egctl x status gateway -q + + # Show the status of gateway resources with details under default namespace. + egctl x status gateway -v + + # Show the status of httproute resources with details under a specific namespace. + egctl x status httproute -v -n foobar + + # Show the status of httproute resources under all namespaces. + egctl x status httproute -A + + # Show the status of all resources under all namespaces. + egctl x status all -A + `, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + k8sClient, err := newK8sClient() + if err != nil { + return err + } + + switch { + case len(args) == 1: + resourceType = args[0] + case len(args) > 1: + return fmt.Errorf("unknown args: %s", strings.Join(args[1:], ",")) + default: + return fmt.Errorf("invalid args: must specific a resources type") + } + + if resourceType == "all" { + for _, rt := range supportedTypes { + if err = runStatus(ctx, k8sClient, rt, namespace, quiet, verbose, allNamespaces, true, true); err != nil { + return err + } + } + return nil + } else { + return runStatus(ctx, k8sClient, resourceType, namespace, quiet, verbose, allNamespaces, false, false) + } + }, + } + + statusCommand.PersistentFlags().BoolVarP(&quiet, "quiet", "q", false, "Show the first status of resources only") + statusCommand.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Show the status of resources with details") + statusCommand.PersistentFlags().BoolVarP(&allNamespaces, "all-namespaces", "A", false, "Get the status of resources from all namespaces") + statusCommand.PersistentFlags().StringVarP(&namespace, "namespace", "n", "default", "Specific a namespace to get the status of resources") + + return statusCommand +} + +func newStatusTableWriter(out io.Writer) *tabwriter.Writer { + return tabwriter.NewWriter(out, 10, 0, 3, ' ', 0) +} + +func writeStatusTable(table *tabwriter.Writer, headers []string, bodies [][]string) { + fmt.Fprintln(table, strings.Join(headers, "\t")) + for _, body := range bodies { + fmt.Fprintln(table, strings.Join(body, "\t")) + } +} + +// runStatus find and write the summary table of status for a specific resource type. +func runStatus(ctx context.Context, cli client.Client, resourceType, namespace string, quiet, verbose, allNamespaces, ignoreEmpty, typedName bool) error { + var ( + resourcesList client.ObjectList + table = newStatusTableWriter(os.Stdout) + ) + + if allNamespaces { + namespace = "" + } + + switch strings.ToLower(resourceType) { + case "gc", "gatewayclass": + gc := gwv1.GatewayClassList{} + if err := cli.List(ctx, &gc, client.InNamespace(namespace)); err != nil { + return err + } + resourcesList = &gc + + case "gtw", "gateway": + gtw := gwv1.GatewayList{} + if err := cli.List(ctx, >w, client.InNamespace(namespace)); err != nil { + return err + } + resourcesList = >w + + case "httproute": + httproute := gwv1.HTTPRouteList{} + if err := cli.List(ctx, &httproute, client.InNamespace(namespace)); err != nil { + return err + } + resourcesList = &httproute + + case "grpcroute": + grpcroute := gwv1a2.GRPCRouteList{} + if err := cli.List(ctx, &grpcroute, client.InNamespace(namespace)); err != nil { + return err + } + resourcesList = &grpcroute + + case "tcproute": + tcproute := gwv1a2.TCPRouteList{} + if err := cli.List(ctx, &tcproute, client.InNamespace(namespace)); err != nil { + return err + } + resourcesList = &tcproute + + case "udproute": + udproute := gwv1a2.UDPRouteList{} + if err := cli.List(ctx, &udproute, client.InNamespace(namespace)); err != nil { + return err + } + resourcesList = &udproute + + case "tlsroute": + tlsroute := gwv1a2.TLSRouteList{} + if err := cli.List(ctx, &tlsroute, client.InNamespace(namespace)); err != nil { + return err + } + resourcesList = &tlsroute + + case "btlspolicy", "backendtlspolicy": + btlspolicy := gwv1a2.BackendTLSPolicyList{} + if err := cli.List(ctx, &btlspolicy, client.InNamespace(namespace)); err != nil { + return err + } + resourcesList = &btlspolicy + + case "btp", "backendtrafficpolicy": + btp := egv1a1.BackendTrafficPolicyList{} + if err := cli.List(ctx, &btp, client.InNamespace(namespace)); err != nil { + return err + } + resourcesList = &btp + + case "ctp", "clienttrafficpolicy": + ctp := egv1a1.ClientTrafficPolicyList{} + if err := cli.List(ctx, &ctp, client.InNamespace(namespace)); err != nil { + return err + } + resourcesList = &ctp + + case "epp", "envoypatchpolicy": + epp := egv1a1.EnvoyPatchPolicyList{} + if err := cli.List(ctx, &epp, client.InNamespace(namespace)); err != nil { + return err + } + resourcesList = &epp + + case "sp", "securitypolicy": + sp := egv1a1.SecurityPolicyList{} + if err := cli.List(ctx, &sp, client.InNamespace(namespace)); err != nil { + return err + } + resourcesList = &sp + + default: + return fmt.Errorf("unknown resource type: %s, supported types are: %s", resourceType, strings.Join(supportedTypes, ",")) + } + + namespaced, err := cli.IsObjectNamespaced(resourcesList) + if err != nil { + return err + } + + needNamespaceHeader := allNamespaces && namespaced + headers := fetchStatusHeaders(verbose, needNamespaceHeader) + bodies, err := fetchStatusBodies(resourcesList, resourceType, quiet, verbose, needNamespaceHeader, typedName) + if err != nil { + return err + } + + if ignoreEmpty && len(bodies) == 0 { + return nil + } + + writeStatusTable(table, headers, bodies) + if err = table.Flush(); err != nil { + return err + } + + // Separate tables by newline if there are multiple tables. + if ignoreEmpty && typedName { + fmt.Print("\n") + } + + return nil +} + +func fetchStatusHeaders(verbose, needNamespace bool) []string { + headers := []string{"NAME", "TYPE", "STATUS", "REASON"} + + if needNamespace { + headers = append([]string{"NAMESPACE"}, headers...) + } + if verbose { + headers = append(headers, []string{"MESSAGE", "OBSERVED GENERATION", "LAST TRANSITION TIME"}...) + } + + return headers +} + +func fetchStatusBodies(resourcesList client.ObjectList, resourceType string, quiet, verbose, needNamespace, typedName bool) ([][]string, error) { + v := reflect.ValueOf(resourcesList).Elem() + + itemsField := v.FieldByName("Items") + if !itemsField.IsValid() { + return nil, fmt.Errorf("failed to load `.Items` field from %s", resourceType) + } + + var body [][]string + for i := 0; i < itemsField.Len(); i++ { + item := itemsField.Index(i) + + // There's no need to check whether Name, Namespace and Kind field is valid, + // since all the objects in ObjectList are implemented k8s Object interface. + var name, namespace string + nameField := item.FieldByName("Name") + if typedName { + kindField := item.FieldByName("Kind") + name = strings.ToLower(kindField.String()) + "/" + nameField.String() + } else { + name = nameField.String() + } + + if needNamespace { + namespaceField := item.FieldByName("Namespace") + namespace = namespaceField.String() + } + + statusField := item.FieldByName("Status") + if !statusField.IsValid() { + return nil, fmt.Errorf("failed to find `.Items[i].Status` field from %s", resourceType) + } + + // Different resources store the conditions at different position. + switch strings.ToLower(resourceType) { + case "httproute", "grpcroute", "tlsroute", "tcproute", "udproute": + // Scrape conditions from `Resource.Status.Parents[i].Conditions` field + parentsField := statusField.FieldByName("Parents") + if !parentsField.IsValid() { + return nil, fmt.Errorf("failed to find `.Items[i].Status.Parents` field from %s", resourceType) + } + + for j := 0; j < parentsField.Len(); j++ { + parentItem := parentsField.Index(j) + rows, err := fetchConditionsField(parentItem, resourceType, name, namespace, quiet, verbose, needNamespace) + if err != nil { + return nil, err + } + + body = append(body, rows...) + } + + case "btlspolicy", "backendtlspolicy": + // Scrape conditions from `Resource.Status.Ancestors[i].Conditions` field + ancestorsField := statusField.FieldByName("Ancestors") + if !ancestorsField.IsValid() { + return nil, fmt.Errorf("failed to find `.Items[i].Status.Ancestors` field from %s", resourceType) + } + + for j := 0; j < ancestorsField.Len(); j++ { + ancestorItem := ancestorsField.Index(j) + rows, err := fetchConditionsField(ancestorItem, resourceType, name, namespace, quiet, verbose, needNamespace) + if err != nil { + return nil, err + } + + body = append(body, rows...) + } + + default: + // Scrape conditions from `Resource.Status.Conditions` field + rows, err := fetchConditionsField(statusField, resourceType, name, namespace, quiet, verbose, needNamespace) + if err != nil { + return nil, err + } + + body = append(body, rows...) + } + } + + return body, nil +} + +func fetchConditionsField(parent reflect.Value, resourceType, name, namespace string, quiet, verbose, needNamespace bool) ([][]string, error) { + conditionsField := parent.FieldByName("Conditions") + if !conditionsField.IsValid() { + return nil, fmt.Errorf("failed to find `Conditions` field for %s", resourceType) + } + + conditions, ok := conditionsField.Interface().([]metav1.Condition) + if !ok { + return nil, fmt.Errorf("failed to convert `Conditions` field to type `[]metav1.Condition`") + } + + rows := fetchConditions(conditions, name, namespace, quiet, verbose, needNamespace) + return rows, nil +} + +func fetchConditions(conditions []metav1.Condition, name, namespace string, quiet, verbose, needNamespace bool) [][]string { + var rows [][]string + + // Sort in descending order by time of each condition. + for i := len(conditions) - 1; i >= 0; i-- { + if i < len(conditions)-1 { + name, namespace = "", "" + } + + row := fetchCondition(conditions[i], name, namespace, verbose, needNamespace) + rows = append(rows, row) + + if quiet { + break + } + } + + return rows +} + +func fetchCondition(condition metav1.Condition, name, namespace string, verbose, needNamespace bool) []string { + row := []string{name, condition.Type, string(condition.Status), condition.Reason} + + // Write conditions corresponding to its headers. + if needNamespace { + row = append([]string{namespace}, row...) + } + if verbose { + row = append(row, []string{ + condition.Message, + strconv.FormatInt(condition.ObservedGeneration, 10), + condition.LastTransitionTime.String(), + }...) + } + + return row +} diff --git a/internal/cmd/egctl/status_test.go b/internal/cmd/egctl/status_test.go new file mode 100644 index 00000000000..ad1fd80b8bc --- /dev/null +++ b/internal/cmd/egctl/status_test.go @@ -0,0 +1,591 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package egctl + +import ( + "bytes" + "testing" + "time" + + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + gwv1 "sigs.k8s.io/gateway-api/apis/v1" + gwv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" +) + +func TestWriteStatus(t *testing.T) { + testTime := time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC) + + testCases := []struct { + name string + resourceNamespaced bool + resourceList client.ObjectList + resourceType string + namespace string + quiet bool + verbose bool + allNamespaces bool + typedName bool + outputs string + expect bool + }{ + { + name: "egctl x status gc -v, but no resources", + resourceList: &gwv1.GatewayClassList{}, + resourceNamespaced: false, + resourceType: "gatewayclass", + quiet: false, + verbose: true, + allNamespaces: false, + typedName: false, + outputs: `NAME TYPE STATUS REASON MESSAGE OBSERVED GENERATION LAST TRANSITION TIME +`, + expect: true, + }, + { + name: "egctl x status gc", + resourceList: &gwv1.GatewayClassList{ + Items: []gwv1.GatewayClass{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "gc", + }, + Status: gwv1.GatewayClassStatus{ + Conditions: []metav1.Condition{ + { + Type: "foobar1", + Status: metav1.ConditionStatus("test-status-1"), + ObservedGeneration: 123456, + LastTransitionTime: metav1.NewTime(testTime), + Reason: "test reason 1", + Message: "test message 1", + }, + { + Type: "foobar2", + Status: metav1.ConditionStatus("test-status-2"), + ObservedGeneration: 123457, + LastTransitionTime: metav1.NewTime(testTime.Add(1 * time.Hour)), + Reason: "test reason 2", + Message: "test message 2", + }, + }, + }, + }, + }, + }, + resourceNamespaced: false, + resourceType: "gatewayclass", + quiet: false, + verbose: false, + allNamespaces: false, + typedName: false, + outputs: `NAME TYPE STATUS REASON +gc foobar2 test-status-2 test reason 2 + foobar1 test-status-1 test reason 1 +`, + expect: true, + }, + { + name: "egctl x status gc -v", + resourceList: &gwv1.GatewayClassList{ + Items: []gwv1.GatewayClass{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "gc", + }, + Status: gwv1.GatewayClassStatus{ + Conditions: []metav1.Condition{ + { + Type: "foobar1", + Status: metav1.ConditionStatus("test-status-1"), + ObservedGeneration: 123456, + LastTransitionTime: metav1.NewTime(testTime), + Reason: "test reason 1", + Message: "test message 1", + }, + { + Type: "foobar2", + Status: metav1.ConditionStatus("test-status-2"), + ObservedGeneration: 123457, + LastTransitionTime: metav1.NewTime(testTime.Add(1 * time.Hour)), + Reason: "test reason 2", + Message: "test message 2", + }, + }, + }, + }, + }, + }, + resourceNamespaced: false, + resourceType: "gatewayclass", + quiet: false, + verbose: true, + allNamespaces: false, + typedName: false, + outputs: `NAME TYPE STATUS REASON MESSAGE OBSERVED GENERATION LAST TRANSITION TIME +gc foobar2 test-status-2 test reason 2 test message 2 123457 2024-01-01 01:00:00 +0000 UTC + foobar1 test-status-1 test reason 1 test message 1 123456 2024-01-01 00:00:00 +0000 UTC +`, + expect: true, + }, + { + name: "egctl x status gc -v -q", + resourceList: &gwv1.GatewayClassList{ + Items: []gwv1.GatewayClass{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "gc", + }, + Status: gwv1.GatewayClassStatus{ + Conditions: []metav1.Condition{ + { + Type: "foobar1", + Status: metav1.ConditionStatus("test-status-1"), + ObservedGeneration: 123456, + LastTransitionTime: metav1.NewTime(testTime), + Reason: "test reason 1", + Message: "test message 1", + }, + { + Type: "foobar2", + Status: metav1.ConditionStatus("test-status-2"), + ObservedGeneration: 123457, + LastTransitionTime: metav1.NewTime(testTime.Add(1 * time.Hour)), + Reason: "test reason 2", + Message: "test message 2", + }, + }, + }, + }, + }, + }, + resourceNamespaced: false, + resourceType: "gatewayclass", + quiet: true, + verbose: true, + allNamespaces: false, + typedName: false, + outputs: `NAME TYPE STATUS REASON MESSAGE OBSERVED GENERATION LAST TRANSITION TIME +gc foobar2 test-status-2 test reason 2 test message 2 123457 2024-01-01 01:00:00 +0000 UTC +`, + expect: true, + }, + { + name: "egctl x status gtw -v -A, no resources", + resourceList: &gwv1.GatewayList{}, + resourceNamespaced: true, + resourceType: "gateway", + quiet: false, + verbose: true, + allNamespaces: true, + typedName: false, + outputs: `NAMESPACE NAME TYPE STATUS REASON MESSAGE OBSERVED GENERATION LAST TRANSITION TIME +`, + expect: true, + }, + { + name: "egctl x status gtw -v -A", + resourceList: &gwv1.GatewayList{ + Items: []gwv1.Gateway{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "gtw", + Namespace: "default", + }, + Status: gwv1.GatewayStatus{ + Conditions: []metav1.Condition{ + { + Type: "foobar1", + Status: metav1.ConditionStatus("test-status-1"), + ObservedGeneration: 123456, + LastTransitionTime: metav1.NewTime(testTime), + Reason: "test reason 1", + Message: "test message 1", + }, + { + Type: "foobar2", + Status: metav1.ConditionStatus("test-status-2"), + ObservedGeneration: 123457, + LastTransitionTime: metav1.NewTime(testTime.Add(1 * time.Hour)), + Reason: "test reason 2", + Message: "test message 2", + }, + }, + }, + }, + }, + }, + resourceNamespaced: true, + resourceType: "gateway", + quiet: false, + verbose: true, + allNamespaces: true, + typedName: false, + outputs: `NAMESPACE NAME TYPE STATUS REASON MESSAGE OBSERVED GENERATION LAST TRANSITION TIME +default gtw foobar2 test-status-2 test reason 2 test message 2 123457 2024-01-01 01:00:00 +0000 UTC + foobar1 test-status-1 test reason 1 test message 1 123456 2024-01-01 00:00:00 +0000 UTC +`, + expect: true, + }, + { + name: "egctl x status gtw -v -q -A", + resourceList: &gwv1.GatewayList{ + Items: []gwv1.Gateway{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "gtw1", + Namespace: "default1", + }, + Status: gwv1.GatewayStatus{ + Conditions: []metav1.Condition{ + { + Type: "foobar1", + Status: metav1.ConditionStatus("test-status-1"), + ObservedGeneration: 123456, + LastTransitionTime: metav1.NewTime(testTime), + Reason: "test reason 1", + Message: "test message 1", + }, + { + Type: "foobar2", + Status: metav1.ConditionStatus("test-status-2"), + ObservedGeneration: 123457, + LastTransitionTime: metav1.NewTime(testTime.Add(1 * time.Hour)), + Reason: "test reason 2", + Message: "test message 2", + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "gtw2", + Namespace: "default2", + }, + Status: gwv1.GatewayStatus{ + Conditions: []metav1.Condition{ + { + Type: "foobar3", + Status: metav1.ConditionStatus("test-status-3"), + ObservedGeneration: 123458, + LastTransitionTime: metav1.NewTime(testTime.Add(2 * time.Hour)), + Reason: "test reason 3", + Message: "test message 3", + }, + { + Type: "foobar4", + Status: metav1.ConditionStatus("test-status-4"), + ObservedGeneration: 123459, + LastTransitionTime: metav1.NewTime(testTime.Add(3 * time.Hour)), + Reason: "test reason 4", + Message: "test message 4", + }, + }, + }, + }, + }, + }, + resourceNamespaced: true, + resourceType: "gateway", + quiet: true, + verbose: true, + allNamespaces: true, + typedName: false, + outputs: `NAMESPACE NAME TYPE STATUS REASON MESSAGE OBSERVED GENERATION LAST TRANSITION TIME +default1 gtw1 foobar2 test-status-2 test reason 2 test message 2 123457 2024-01-01 01:00:00 +0000 UTC +default2 gtw2 foobar4 test-status-4 test reason 4 test message 4 123459 2024-01-01 03:00:00 +0000 UTC +`, + expect: true, + }, + { + name: "egctl x status httproute -A", + resourceList: &gwv1.HTTPRouteList{ + Items: []gwv1.HTTPRoute{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "http1", + Namespace: "default1", + }, + Status: gwv1.HTTPRouteStatus{ + RouteStatus: gwv1.RouteStatus{ + Parents: []gwv1.RouteParentStatus{ + { + Conditions: []metav1.Condition{ + { + Type: "foobar1", + Status: metav1.ConditionStatus("test-status-1"), + ObservedGeneration: 123456, + LastTransitionTime: metav1.NewTime(testTime), + Reason: "test reason 1", + Message: "test message 1", + }, + { + Type: "foobar2", + Status: metav1.ConditionStatus("test-status-2"), + ObservedGeneration: 123457, + LastTransitionTime: metav1.NewTime(testTime.Add(1 * time.Hour)), + Reason: "test reason 2", + Message: "test message 2", + }, + }, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "http2", + Namespace: "default2", + }, + Status: gwv1.HTTPRouteStatus{ + RouteStatus: gwv1.RouteStatus{ + Parents: []gwv1.RouteParentStatus{ + { + Conditions: []metav1.Condition{ + { + Type: "foobar3", + Status: metav1.ConditionStatus("test-status-3"), + ObservedGeneration: 123458, + LastTransitionTime: metav1.NewTime(testTime.Add(2 * time.Hour)), + Reason: "test reason 3", + Message: "test message 3", + }, + { + Type: "foobar4", + Status: metav1.ConditionStatus("test-status-4"), + ObservedGeneration: 123459, + LastTransitionTime: metav1.NewTime(testTime.Add(3 * time.Hour)), + Reason: "test reason 4", + Message: "test message 4", + }, + }, + }, + }, + }, + }, + }, + }, + }, + resourceNamespaced: true, + resourceType: "httproute", + quiet: false, + verbose: false, + allNamespaces: true, + typedName: false, + outputs: `NAMESPACE NAME TYPE STATUS REASON +default1 http1 foobar2 test-status-2 test reason 2 + foobar1 test-status-1 test reason 1 +default2 http2 foobar4 test-status-4 test reason 4 + foobar3 test-status-3 test reason 3 +`, + expect: true, + }, + { + name: "egctl x status httproute -q -n default1", + resourceList: &gwv1.HTTPRouteList{ + Items: []gwv1.HTTPRoute{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "http1", + Namespace: "default1", + }, + Status: gwv1.HTTPRouteStatus{ + RouteStatus: gwv1.RouteStatus{ + Parents: []gwv1.RouteParentStatus{ + { + Conditions: []metav1.Condition{ + { + Type: "foobar1", + Status: metav1.ConditionStatus("test-status-1"), + ObservedGeneration: 123456, + LastTransitionTime: metav1.NewTime(testTime), + Reason: "test reason 1", + Message: "test message 1", + }, + { + Type: "foobar2", + Status: metav1.ConditionStatus("test-status-2"), + ObservedGeneration: 123457, + LastTransitionTime: metav1.NewTime(testTime.Add(1 * time.Hour)), + Reason: "test reason 2", + Message: "test message 2", + }, + }, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "http2", + Namespace: "default2", + }, + Status: gwv1.HTTPRouteStatus{ + RouteStatus: gwv1.RouteStatus{ + Parents: []gwv1.RouteParentStatus{ + { + Conditions: []metav1.Condition{ + { + Type: "foobar3", + Status: metav1.ConditionStatus("test-status-3"), + ObservedGeneration: 123458, + LastTransitionTime: metav1.NewTime(testTime.Add(2 * time.Hour)), + Reason: "test reason 3", + Message: "test message 3", + }, + { + Type: "foobar4", + Status: metav1.ConditionStatus("test-status-4"), + ObservedGeneration: 123459, + LastTransitionTime: metav1.NewTime(testTime.Add(3 * time.Hour)), + Reason: "test reason 4", + Message: "test message 4", + }, + }, + }, + }, + }, + }, + }, + }, + }, + resourceNamespaced: true, + resourceType: "httproute", + quiet: true, + verbose: false, + allNamespaces: false, + typedName: false, + namespace: "default1", + outputs: `NAME TYPE STATUS REASON +http1 foobar2 test-status-2 test reason 2 +http2 foobar4 test-status-4 test reason 4 +`, + expect: true, + }, + { + name: "egctl x status btlspolicy", + resourceList: &gwv1a2.BackendTLSPolicyList{ + Items: []gwv1a2.BackendTLSPolicy{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "btls", + Namespace: "default", + }, + Status: gwv1a2.PolicyStatus{ + Ancestors: []gwv1a2.PolicyAncestorStatus{ + { + Conditions: []metav1.Condition{ + { + Type: "foobar1", + Status: metav1.ConditionStatus("test-status-1"), + ObservedGeneration: 123456, + LastTransitionTime: metav1.NewTime(testTime), + Reason: "test reason 1", + Message: "test message 1", + }, + { + Type: "foobar2", + Status: metav1.ConditionStatus("test-status-2"), + ObservedGeneration: 123457, + LastTransitionTime: metav1.NewTime(testTime.Add(1 * time.Hour)), + Reason: "test reason 2", + Message: "test message 2", + }, + }, + }, + }, + }, + }, + }, + }, + resourceNamespaced: true, + resourceType: "btlspolicy", + quiet: false, + verbose: false, + allNamespaces: false, + typedName: false, + outputs: `NAME TYPE STATUS REASON +btls foobar2 test-status-2 test reason 2 + foobar1 test-status-1 test reason 1 +`, + expect: true, + }, + { + name: "egctl x status envoypatchpolicy with typed name", + resourceList: &egv1a1.EnvoyPatchPolicyList{ + Items: []egv1a1.EnvoyPatchPolicy{ + { + TypeMeta: metav1.TypeMeta{ + Kind: "EnvoyPatchPolicy", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "epp", + Namespace: "default", + }, + Status: egv1a1.EnvoyPatchPolicyStatus{ + Conditions: []metav1.Condition{ + { + Type: "foobar1", + Status: metav1.ConditionStatus("test-status-1"), + ObservedGeneration: 123456, + LastTransitionTime: metav1.NewTime(testTime), + Reason: "test reason 1", + Message: "test message 1", + }, + { + Type: "foobar2", + Status: metav1.ConditionStatus("test-status-2"), + ObservedGeneration: 123457, + LastTransitionTime: metav1.NewTime(testTime.Add(1 * time.Hour)), + Reason: "test reason 2", + Message: "test message 2", + }, + }, + }, + }, + }, + }, + resourceNamespaced: true, + resourceType: "envoypatchpolicy", + quiet: false, + verbose: false, + allNamespaces: false, + typedName: true, + outputs: `NAME TYPE STATUS REASON +envoypatchpolicy/epp foobar2 test-status-2 test reason 2 + foobar1 test-status-1 test reason 1 +`, + expect: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + var out bytes.Buffer + tab := newStatusTableWriter(&out) + + needNamespace := tc.allNamespaces && tc.resourceNamespaced + headers := fetchStatusHeaders(tc.verbose, needNamespace) + bodies, err := fetchStatusBodies(tc.resourceList, tc.resourceType, tc.quiet, tc.verbose, needNamespace, tc.typedName) + if tc.expect { + require.NoError(t, err) + + writeStatusTable(tab, headers, bodies) + err = tab.Flush() + require.NoError(t, err) + + require.Equal(t, tc.outputs, out.String()) + } else { + require.EqualError(t, err, tc.outputs) + } + }) + } +} 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 c11c272db86..92a71a6ac1c 100644 --- a/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml @@ -22,6 +22,8 @@ envoyProxy: - 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 @@ -504,6 +506,8 @@ xds: - name: global_config staticLayer: envoy.restart_features.use_eds_cache_for_ads: true + re2.max_program_size.error_level: 4294967295 + re2.max_program_size.warn_level: 1000 staticResources: clusters: - connectTimeout: 0.250s @@ -799,6 +803,7 @@ xds: - 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 @@ -807,6 +812,7 @@ xds: ads: {} resourceApiVersion: V3 routeConfigName: default/eg/http + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket @@ -865,6 +871,7 @@ xds: - 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 @@ -873,6 +880,7 @@ xds: ads: {} resourceApiVersion: V3 routeConfigName: default/eg/grpc + serverHeaderTransformation: PASS_THROUGH statPrefix: http useRemoteAddress: true name: default/eg/grpc diff --git a/internal/cmd/egctl/testdata/translate/out/envoy-patch-policy.all.yaml b/internal/cmd/egctl/testdata/translate/out/envoy-patch-policy.all.yaml index edac1862cfb..c31c5d146f3 100644 --- a/internal/cmd/egctl/testdata/translate/out/envoy-patch-policy.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/envoy-patch-policy.all.yaml @@ -32,6 +32,8 @@ xds: - name: global_config staticLayer: envoy.restart_features.use_eds_cache_for_ads: true + re2.max_program_size.error_level: 4294967295 + re2.max_program_size.warn_level: 1000 staticResources: clusters: - connectTimeout: 0.250s @@ -197,6 +199,7 @@ xds: - 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 @@ -205,6 +208,7 @@ xds: ads: {} resourceApiVersion: V3 routeConfigName: default/eg/http + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.json b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.json index 9de218a8d83..bd7a401d957 100644 --- a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.json +++ b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.json @@ -49,7 +49,9 @@ { "name": "global_config", "staticLayer": { - "envoy.restart_features.use_eds_cache_for_ads": true + "envoy.restart_features.use_eds_cache_for_ads": true, + "re2.max_program_size.error_level": 4294967295, + "re2.max_program_size.warn_level": 1000 } } ] @@ -551,7 +553,8 @@ { "name": "envoy.filters.http.router", "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router", + "suppressEnvoyHeaders": true } } ], @@ -565,6 +568,7 @@ }, "routeConfigName": "default/eg/http" }, + "serverHeaderTransformation": "PASS_THROUGH", "statPrefix": "http", "upgradeConfigs": [ { @@ -658,7 +662,8 @@ { "name": "envoy.filters.http.router", "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router", + "suppressEnvoyHeaders": true } } ], @@ -672,6 +677,7 @@ }, "routeConfigName": "default/eg/grpc" }, + "serverHeaderTransformation": "PASS_THROUGH", "statPrefix": "http", "useRemoteAddress": true } diff --git a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.yaml b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.yaml index f6f6822b0a5..ed5c71ea602 100644 --- a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.yaml @@ -32,6 +32,8 @@ xds: - name: global_config staticLayer: envoy.restart_features.use_eds_cache_for_ads: true + re2.max_program_size.error_level: 4294967295 + re2.max_program_size.warn_level: 1000 staticResources: clusters: - connectTimeout: 0.250s @@ -327,6 +329,7 @@ xds: - 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 @@ -335,6 +338,7 @@ xds: ads: {} resourceApiVersion: V3 routeConfigName: default/eg/http + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket @@ -393,6 +397,7 @@ xds: - 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 @@ -401,6 +406,7 @@ xds: ads: {} resourceApiVersion: V3 routeConfigName: default/eg/grpc + serverHeaderTransformation: PASS_THROUGH statPrefix: http useRemoteAddress: true name: default/eg/grpc diff --git a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.bootstrap.yaml b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.bootstrap.yaml index 2e32692abbb..33562f700f5 100644 --- a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.bootstrap.yaml +++ b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.bootstrap.yaml @@ -31,6 +31,8 @@ xds: - name: global_config staticLayer: envoy.restart_features.use_eds_cache_for_ads: true + re2.max_program_size.error_level: 4294967295 + re2.max_program_size.warn_level: 1000 staticResources: clusters: - connectTimeout: 0.250s diff --git a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.listener.yaml b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.listener.yaml index ae7fce949cf..bc904a54906 100644 --- a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.listener.yaml +++ b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.listener.yaml @@ -46,6 +46,7 @@ xds: - 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 @@ -54,6 +55,7 @@ xds: ads: {} resourceApiVersion: V3 routeConfigName: default/eg/http + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket @@ -112,6 +114,7 @@ xds: - 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 @@ -120,6 +123,7 @@ xds: ads: {} resourceApiVersion: V3 routeConfigName: default/eg/grpc + serverHeaderTransformation: PASS_THROUGH statPrefix: http useRemoteAddress: true name: default/eg/grpc diff --git a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.json b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.json index c35f2931369..c776a2f53b3 100644 --- a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.json +++ b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.json @@ -49,7 +49,9 @@ { "name": "global_config", "staticLayer": { - "envoy.restart_features.use_eds_cache_for_ads": true + "envoy.restart_features.use_eds_cache_for_ads": true, + "re2.max_program_size.error_level": 4294967295, + "re2.max_program_size.warn_level": 1000 } } ] @@ -327,7 +329,8 @@ "filename": "/etc/ssl/certs/ca-certificates.crt" } } - } + }, + "sni": "raw.githubusercontent.com" } }, "type": "STRICT_DNS" @@ -410,7 +413,7 @@ "cacheDuration": "300s", "httpUri": { "cluster": "raw_githubusercontent_com_443", - "timeout": "5s", + "timeout": "10s", "uri": "https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/jwks.json" }, "retryPolicy": {} @@ -427,7 +430,8 @@ { "name": "envoy.filters.http.router", "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router", + "suppressEnvoyHeaders": true } } ], @@ -441,6 +445,7 @@ }, "routeConfigName": "envoy-gateway-system/eg/http" }, + "serverHeaderTransformation": "PASS_THROUGH", "statPrefix": "http", "upgradeConfigs": [ { diff --git a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.yaml b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.yaml index 91b08a8cd7b..94acbe31904 100644 --- a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.yaml @@ -32,6 +32,8 @@ xds: - name: global_config staticLayer: envoy.restart_features.use_eds_cache_for_ads: true + re2.max_program_size.error_level: 4294967295 + re2.max_program_size.warn_level: 1000 staticResources: clusters: - connectTimeout: 0.250s @@ -189,6 +191,7 @@ xds: validationContext: trustedCa: filename: /etc/ssl/certs/ca-certificates.crt + sni: raw.githubusercontent.com type: STRICT_DNS - '@type': type.googleapis.com/envoy.admin.v3.ListenersConfigDump dynamicListeners: @@ -244,7 +247,7 @@ xds: cacheDuration: 300s httpUri: cluster: raw_githubusercontent_com_443 - timeout: 5s + timeout: 10s uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/jwks.json retryPolicy: {} requirementMap: @@ -253,6 +256,7 @@ xds: - 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 @@ -261,6 +265,7 @@ xds: ads: {} resourceApiVersion: V3 routeConfigName: envoy-gateway-system/eg/http + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.bootstrap.yaml b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.bootstrap.yaml index df95cda5c56..1d64ba4ebfb 100644 --- a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.bootstrap.yaml +++ b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.bootstrap.yaml @@ -31,6 +31,8 @@ xds: - name: global_config staticLayer: envoy.restart_features.use_eds_cache_for_ads: true + re2.max_program_size.error_level: 4294967295 + re2.max_program_size.warn_level: 1000 staticResources: clusters: - connectTimeout: 0.250s diff --git a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.cluster.yaml b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.cluster.yaml index 47f144cbe20..ea64bf8d0f9 100644 --- a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.cluster.yaml +++ b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.cluster.yaml @@ -51,4 +51,5 @@ xds: validationContext: trustedCa: filename: /etc/ssl/certs/ca-certificates.crt + sni: raw.githubusercontent.com type: STRICT_DNS diff --git a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.listener.yaml b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.listener.yaml index 7c8a353b83c..acc9e8afdee 100644 --- a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.listener.yaml +++ b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.listener.yaml @@ -54,7 +54,7 @@ xds: cacheDuration: 300s httpUri: cluster: raw_githubusercontent_com_443 - timeout: 5s + timeout: 10s uri: https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/jwks.json retryPolicy: {} requirementMap: @@ -63,6 +63,7 @@ xds: - 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 @@ -71,6 +72,7 @@ xds: ads: {} resourceApiVersion: V3 routeConfigName: envoy-gateway-system/eg/http + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/cmd/egctl/translate.go b/internal/cmd/egctl/translate.go index 47ab944f424..a97c83261b7 100644 --- a/internal/cmd/egctl/translate.go +++ b/internal/cmd/egctl/translate.go @@ -52,7 +52,7 @@ type TranslationResult struct { Xds map[string]interface{} `json:"xds,omitempty"` } -func NewTranslateCommand() *cobra.Command { +func newTranslateCommand() *cobra.Command { var ( inFile, inType, output, resourceType string addMissingResources bool @@ -265,6 +265,7 @@ func translateGatewayAPIToGatewayAPI(resources *gatewayapi.Resources) (gatewayap GatewayClassName: gwapiv1.ObjectName(resources.GatewayClass.Name), GlobalRateLimitEnabled: true, EndpointRoutingDisabled: true, + EnvoyPatchPolicyEnabled: true, } gRes := gTranslator.Translate(resources) // Update the status of the GatewayClass based on EnvoyProxy validation @@ -296,6 +297,7 @@ func translateGatewayAPIToXds(dnsDomain string, resourceType string, resources * GatewayClassName: gwapiv1.ObjectName(resources.GatewayClass.Name), GlobalRateLimitEnabled: true, EndpointRoutingDisabled: true, + EnvoyPatchPolicyEnabled: true, } gRes := gTranslator.Translate(resources) diff --git a/internal/cmd/egctl/translate_test.go b/internal/cmd/egctl/translate_test.go index d9cd598174a..11ac62c95a0 100644 --- a/internal/cmd/egctl/translate_test.go +++ b/internal/cmd/egctl/translate_test.go @@ -18,7 +18,6 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/yaml" @@ -285,7 +284,7 @@ func TestTranslate(t *testing.T) { t.Run(tc.name+"|"+tc.resourceType, func(t *testing.T) { b := bytes.NewBufferString("") - root := NewTranslateCommand() + root := newTranslateCommand() root.SetOut(b) root.SetErr(b) args := []string{ @@ -318,14 +317,14 @@ func TestTranslate(t *testing.T) { root.SetArgs(args) if tc.expect { - assert.NoError(t, root.ExecuteContext(context.Background())) + require.NoError(t, root.ExecuteContext(context.Background())) } else { - assert.Error(t, root.ExecuteContext(context.Background())) + require.Error(t, root.ExecuteContext(context.Background())) return } out, err := io.ReadAll(b) - assert.NoError(t, err) + require.NoError(t, err) got := &TranslationResult{} mustUnmarshal(t, out, got) var fn string diff --git a/internal/cmd/egctl/utils.go b/internal/cmd/egctl/utils.go index f1029247ae3..254ebb94603 100644 --- a/internal/cmd/egctl/utils.go +++ b/internal/cmd/egctl/utils.go @@ -10,6 +10,14 @@ import ( adminv3 "github.com/envoyproxy/go-control-plane/envoy/admin/v3" "google.golang.org/protobuf/reflect/protoreflect" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/config" + gwv1 "sigs.k8s.io/gateway-api/apis/v1" + gwv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + gwv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" + + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" ) type envoyConfigType string @@ -26,34 +34,34 @@ var ( func findXDSResourceFromConfigDump(resourceType envoyConfigType, globalConfigs *adminv3.ConfigDump) (protoreflect.ProtoMessage, error) { switch resourceType { case BootstrapEnvoyConfigType: - for _, config := range globalConfigs.Configs { - if config.GetTypeUrl() == "type.googleapis.com/envoy.admin.v3.BootstrapConfigDump" { - return config, nil + for _, cfg := range globalConfigs.Configs { + if cfg.GetTypeUrl() == "type.googleapis.com/envoy.admin.v3.BootstrapConfigDump" { + return cfg, nil } } case EndpointEnvoyConfigType: - for _, config := range globalConfigs.Configs { - if config.GetTypeUrl() == "type.googleapis.com/envoy.admin.v3.EndpointsConfigDump" { - return config, nil + for _, cfg := range globalConfigs.Configs { + if cfg.GetTypeUrl() == "type.googleapis.com/envoy.admin.v3.EndpointsConfigDump" { + return cfg, nil } } case ClusterEnvoyConfigType: - for _, config := range globalConfigs.Configs { - if config.GetTypeUrl() == "type.googleapis.com/envoy.admin.v3.ClustersConfigDump" { - return config, nil + for _, cfg := range globalConfigs.Configs { + if cfg.GetTypeUrl() == "type.googleapis.com/envoy.admin.v3.ClustersConfigDump" { + return cfg, nil } } case ListenerEnvoyConfigType: - for _, config := range globalConfigs.Configs { - if config.GetTypeUrl() == "type.googleapis.com/envoy.admin.v3.ListenersConfigDump" { - return config, nil + for _, cfg := range globalConfigs.Configs { + if cfg.GetTypeUrl() == "type.googleapis.com/envoy.admin.v3.ListenersConfigDump" { + return cfg, nil } } case RouteEnvoyConfigType: - for _, config := range globalConfigs.Configs { - if config.GetTypeUrl() == "type.googleapis.com/envoy.admin.v3.RoutesConfigDump" { - return config, nil + for _, cfg := range globalConfigs.Configs { + if cfg.GetTypeUrl() == "type.googleapis.com/envoy.admin.v3.RoutesConfigDump" { + return cfg, nil } } case AllEnvoyConfigType: @@ -64,3 +72,37 @@ func findXDSResourceFromConfigDump(resourceType envoyConfigType, globalConfigs * return nil, fmt.Errorf("unknown resourceType %s", resourceType) } + +// newGatewayScheme creates scheme for K8s Gateway API and Envoy Gateway. +func newGatewayScheme() (*runtime.Scheme, error) { + scheme := runtime.NewScheme() + + if err := gwv1.AddToScheme(scheme); err != nil { + return nil, err + } + if err := gwv1b1.AddToScheme(scheme); err != nil { + return nil, err + } + if err := gwv1a2.AddToScheme(scheme); err != nil { + return nil, err + } + if err := egv1a1.AddToScheme(scheme); err != nil { + return nil, err + } + + return scheme, nil +} + +func newK8sClient() (client.Client, error) { + scheme, err := newGatewayScheme() + if err != nil { + return nil, fmt.Errorf("failed to load gateway shceme: %w", err) + } + + cli, err := client.New(config.GetConfigOrDie(), client.Options{Scheme: scheme}) + if err != nil { + return nil, fmt.Errorf("failed to initialize Kubernetes client: %w", err) + } + + return cli, nil +} diff --git a/internal/cmd/server_test.go b/internal/cmd/server_test.go index 2dde218d1b2..b6608445e3d 100644 --- a/internal/cmd/server_test.go +++ b/internal/cmd/server_test.go @@ -10,6 +10,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) var ( @@ -54,18 +55,18 @@ func TestGetConfigValidate(t *testing.T) { test := test t.Run(test.name, func(t *testing.T) { file, err := os.CreateTemp("", "config") - assert.NoError(t, err) + require.NoError(t, err) defer os.Remove(file.Name()) _, err = file.Write([]byte(test.input)) - assert.NoError(t, err) + require.NoError(t, err) _, err = getConfigByPath(file.Name()) if test.errors == nil { - assert.NoError(t, err) + require.NoError(t, err) } else { for _, e := range test.errors { - assert.ErrorContains(t, err, e) + require.ErrorContains(t, err, e) } } }) diff --git a/internal/crypto/certgen_test.go b/internal/crypto/certgen_test.go index 0b9c8d91028..24e4a18ca79 100644 --- a/internal/crypto/certgen_test.go +++ b/internal/crypto/certgen_test.go @@ -12,7 +12,6 @@ import ( "testing" "time" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/envoyproxy/gateway/internal/envoygateway/config" @@ -44,10 +43,10 @@ func TestGenerateCerts(t *testing.T) { currentTime := time.Now() err = verifyCert(got.EnvoyGatewayCertificate, roots, tc.wantEnvoyGatewayDNSName, currentTime) - assert.NoErrorf(t, err, "Validating %s failed", name) + require.NoErrorf(t, err, "Validating %s failed", name) err = verifyCert(got.EnvoyCertificate, roots, tc.wantEnvoyDNSName, currentTime) - assert.NoErrorf(t, err, "Validating %s failed", name) + require.NoErrorf(t, err, "Validating %s failed", name) }) } @@ -126,7 +125,7 @@ func TestGeneratedValidKubeCerts(t *testing.T) { tc := tests[i] t.Run(tc.name, func(t *testing.T) { err := verifyCert(tc.cert, roots, tc.dnsName, now) - assert.NoErrorf(t, err, "Validating %s failed", tc.name) + require.NoErrorf(t, err, "Validating %s failed", tc.name) }) } diff --git a/internal/envoygateway/config/decoder_test.go b/internal/envoygateway/config/decoder_test.go index 80fdc461ff8..875f7bebcd5 100644 --- a/internal/envoygateway/config/decoder_test.go +++ b/internal/envoygateway/config/decoder_test.go @@ -271,9 +271,21 @@ func TestDecode(t *testing.T) { Type: v1alpha1.ProviderTypeKubernetes, Kubernetes: &v1alpha1.EnvoyGatewayKubernetesProvider{ Watch: &v1alpha1.KubernetesWatchMode{ - Type: v1alpha1.KubernetesWatchModeTypeNamespaceSelectors, - NamespaceSelectors: []string{ - "label-a", + Type: v1alpha1.KubernetesWatchModeTypeNamespaceSelector, + NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"label-a": "foo"}, + MatchExpressions: []metav1.LabelSelectorRequirement{ + { + Key: "tier", + Operator: metav1.LabelSelectorOpIn, + Values: []string{"cache"}, + }, + { + Key: "environment", + Operator: metav1.LabelSelectorOpNotIn, + Values: []string{"dev"}, + }, + }, }, }, }, @@ -321,7 +333,7 @@ func TestDecode(t *testing.T) { require.NoError(t, err) require.Equal(t, tc.out, eg) } else { - require.Equal(t, !reflect.DeepEqual(tc.out, eg) || err != nil, true) + require.True(t, !reflect.DeepEqual(tc.out, eg) || err != nil) } }) } diff --git a/internal/envoygateway/config/testdata/decoder/in/gateway-nsselector-watch.yaml b/internal/envoygateway/config/testdata/decoder/in/gateway-nsselector-watch.yaml index 4bc7369f6ae..1f46b413d72 100644 --- a/internal/envoygateway/config/testdata/decoder/in/gateway-nsselector-watch.yaml +++ b/internal/envoygateway/config/testdata/decoder/in/gateway-nsselector-watch.yaml @@ -6,6 +6,16 @@ provider: type: Kubernetes kubernetes: watch: - type: NamespaceSelectors - namespaceSelectors: - - label-a + type: NamespaceSelector + namespaceSelector: + matchLabels: + label-a: foo + matchExpressions: + - key: tier + operator: In + values: + - cache + - key: environment + operator: NotIn + values: + - dev diff --git a/internal/gatewayapi/backendtrafficpolicy.go b/internal/gatewayapi/backendtrafficpolicy.go index e7975c308ec..d5d71b1fd38 100644 --- a/internal/gatewayapi/backendtrafficpolicy.go +++ b/internal/gatewayapi/backendtrafficpolicy.go @@ -12,6 +12,7 @@ import ( "net" "sort" "strings" + "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -248,6 +249,8 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen hc *ir.HealthCheck cb *ir.CircuitBreaker fi *ir.FaultInjection + to *ir.Timeout + ka *ir.TCPKeepalive ) // Build IR @@ -270,6 +273,9 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen if policy.Spec.FaultInjection != nil { fi = t.buildFaultInjection(policy) } + if policy.Spec.TCPKeepalive != nil { + ka = t.buildTCPKeepAlive(policy) + } // Apply IR to all relevant routes prefix := irRoutePrefix(route) for _, ir := range xdsIR { @@ -283,6 +289,13 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen r.HealthCheck = hc r.CircuitBreaker = cb r.FaultInjection = fi + r.TCPKeepalive = ka + + // some timeout setting originate from the route + if policy.Spec.Timeout != nil { + to = t.buildTimeout(policy, r) + r.Timeout = to + } } } } @@ -298,6 +311,8 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back hc *ir.HealthCheck cb *ir.CircuitBreaker fi *ir.FaultInjection + ct *ir.Timeout + ka *ir.TCPKeepalive ) // Build IR @@ -319,6 +334,9 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back if policy.Spec.FaultInjection != nil { fi = t.buildFaultInjection(policy) } + if policy.Spec.TCPKeepalive != nil { + ka = t.buildTCPKeepAlive(policy) + } // Apply IR to all the routes within the specific Gateway // If the feature is already set, then skip it, since it must be have @@ -348,6 +366,16 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back if r.FaultInjection == nil { r.FaultInjection = fi } + if r.TCPKeepalive == nil { + r.TCPKeepalive = ka + } + + if policy.Spec.Timeout != nil { + ct = t.buildTimeout(policy, r) + if r.Timeout == nil { + r.Timeout = ct + } + } } } @@ -674,25 +702,57 @@ func (t *Translator) buildHealthCheck(policy *egv1a1.BackendTrafficPolicy) *ir.H if policy.Spec.HealthCheck == nil { return nil } + irhc := &ir.HealthCheck{} + if policy.Spec.HealthCheck.Passive != nil { + irhc.Passive = t.buildPassiveHealthCheck(policy) + } + if policy.Spec.HealthCheck.Active != nil { + irhc.Active = t.buildActiveHealthCheck(policy) + } + return irhc +} + +func (t *Translator) buildPassiveHealthCheck(policy *egv1a1.BackendTrafficPolicy) *ir.OutlierDetection { + if policy.Spec.HealthCheck == nil || policy.Spec.HealthCheck.Passive == nil { + return nil + } - hc := policy.Spec.HealthCheck - irHC := &ir.HealthCheck{ + hc := policy.Spec.HealthCheck.Passive + irOD := &ir.OutlierDetection{ + Interval: hc.Interval, + SplitExternalLocalOriginErrors: hc.SplitExternalLocalOriginErrors, + ConsecutiveLocalOriginFailures: hc.ConsecutiveLocalOriginFailures, + ConsecutiveGatewayErrors: hc.ConsecutiveGatewayErrors, + Consecutive5xxErrors: hc.Consecutive5xxErrors, + BaseEjectionTime: hc.BaseEjectionTime, + MaxEjectionPercent: hc.MaxEjectionPercent, + } + return irOD +} + +func (t *Translator) buildActiveHealthCheck(policy *egv1a1.BackendTrafficPolicy) *ir.ActiveHealthCheck { + if policy.Spec.HealthCheck == nil || policy.Spec.HealthCheck.Active == nil { + return nil + } + + hc := policy.Spec.HealthCheck.Active + irHC := &ir.ActiveHealthCheck{ Timeout: hc.Timeout, Interval: hc.Interval, UnhealthyThreshold: hc.UnhealthyThreshold, HealthyThreshold: hc.HealthyThreshold, } switch hc.Type { - case egv1a1.HealthCheckerTypeHTTP: - irHC.HTTP = t.buildHTTPHealthChecker(hc.HTTP) - case egv1a1.HealthCheckerTypeTCP: - irHC.TCP = t.buildTCPHealthChecker(hc.TCP) + case egv1a1.ActiveHealthCheckerTypeHTTP: + irHC.HTTP = t.buildHTTPActiveHealthChecker(hc.HTTP) + case egv1a1.ActiveHealthCheckerTypeTCP: + irHC.TCP = t.buildTCPActiveHealthChecker(hc.TCP) } return irHC } -func (t *Translator) buildHTTPHealthChecker(h *egv1a1.HTTPHealthChecker) *ir.HTTPHealthChecker { +func (t *Translator) buildHTTPActiveHealthChecker(h *egv1a1.HTTPActiveHealthChecker) *ir.HTTPHealthChecker { if h == nil { return nil } @@ -716,32 +776,32 @@ func (t *Translator) buildHTTPHealthChecker(h *egv1a1.HTTPHealthChecker) *ir.HTT } irHTTP.ExpectedStatuses = irStatuses - irHTTP.ExpectedResponse = translateHealthCheckPayload(h.ExpectedResponse) + irHTTP.ExpectedResponse = translateActiveHealthCheckPayload(h.ExpectedResponse) return irHTTP } -func (t *Translator) buildTCPHealthChecker(h *egv1a1.TCPHealthChecker) *ir.TCPHealthChecker { +func (t *Translator) buildTCPActiveHealthChecker(h *egv1a1.TCPActiveHealthChecker) *ir.TCPHealthChecker { if h == nil { return nil } irTCP := &ir.TCPHealthChecker{ - Send: translateHealthCheckPayload(h.Send), - Receive: translateHealthCheckPayload(h.Receive), + Send: translateActiveHealthCheckPayload(h.Send), + Receive: translateActiveHealthCheckPayload(h.Receive), } return irTCP } -func translateHealthCheckPayload(p *egv1a1.HealthCheckPayload) *ir.HealthCheckPayload { +func translateActiveHealthCheckPayload(p *egv1a1.ActiveHealthCheckPayload) *ir.HealthCheckPayload { if p == nil { return nil } irPayload := &ir.HealthCheckPayload{} switch p.Type { - case egv1a1.HealthCheckPayloadTypeText: + case egv1a1.ActiveHealthCheckPayloadTypeText: irPayload.Text = p.Text - case egv1a1.HealthCheckPayloadTypeBinary: + case egv1a1.ActiveHealthCheckPayloadTypeBinary: irPayload.Binary = make([]byte, len(p.Binary)) copy(irPayload.Binary, p.Binary) } @@ -776,7 +836,7 @@ func (t *Translator) buildCircuitBreaker(policy *egv1a1.BackendTrafficPolicy) *i if ui32, ok := int64ToUint32(*pcb.MaxConnections); ok { cb.MaxConnections = &ui32 } else { - setCircuitBreakerPolicyErrorCondition(policy, fmt.Sprintf("invalid MaxConnections value %d", *pcb.MaxConnections)) + setBackendTrafficPolicyTranslationErrorCondition(policy, "Circuit Breaker", fmt.Sprintf("invalid MaxConnections value %d", *pcb.MaxConnections)) return nil } } @@ -785,7 +845,7 @@ func (t *Translator) buildCircuitBreaker(policy *egv1a1.BackendTrafficPolicy) *i if ui32, ok := int64ToUint32(*pcb.MaxParallelRequests); ok { cb.MaxParallelRequests = &ui32 } else { - setCircuitBreakerPolicyErrorCondition(policy, fmt.Sprintf("invalid MaxParallelRequests value %d", *pcb.MaxParallelRequests)) + setBackendTrafficPolicyTranslationErrorCondition(policy, "Circuit Breaker", fmt.Sprintf("invalid MaxParallelRequests value %d", *pcb.MaxParallelRequests)) return nil } } @@ -794,7 +854,7 @@ func (t *Translator) buildCircuitBreaker(policy *egv1a1.BackendTrafficPolicy) *i if ui32, ok := int64ToUint32(*pcb.MaxPendingRequests); ok { cb.MaxPendingRequests = &ui32 } else { - setCircuitBreakerPolicyErrorCondition(policy, fmt.Sprintf("invalid MaxPendingRequests value %d", *pcb.MaxPendingRequests)) + setBackendTrafficPolicyTranslationErrorCondition(policy, "Circuit Breaker", fmt.Sprintf("invalid MaxPendingRequests value %d", *pcb.MaxPendingRequests)) return nil } } @@ -803,8 +863,86 @@ func (t *Translator) buildCircuitBreaker(policy *egv1a1.BackendTrafficPolicy) *i return cb } -func setCircuitBreakerPolicyErrorCondition(policy *egv1a1.BackendTrafficPolicy, errMsg string) { - message := fmt.Sprintf("Unable to translate Circuit Breaker: %s", errMsg) +func (t *Translator) buildTimeout(policy *egv1a1.BackendTrafficPolicy, r *ir.HTTPRoute) *ir.Timeout { + var tto *ir.TCPTimeout + var hto *ir.HTTPTimeout + terr := false + + pto := policy.Spec.Timeout + + if pto.TCP != nil && pto.TCP.ConnectTimeout != nil { + d, err := time.ParseDuration(string(*pto.TCP.ConnectTimeout)) + if err != nil { + setBackendTrafficPolicyTranslationErrorCondition(policy, "TCP Timeout", fmt.Sprintf("invalid ConnectTimeout value %s", *pto.TCP.ConnectTimeout)) + terr = true + } else { + tto = &ir.TCPTimeout{ + ConnectTimeout: ptr.To(metav1.Duration{Duration: d}), + } + } + } + + if pto.HTTP != nil { + var cit *metav1.Duration + var mcd *metav1.Duration + + if pto.HTTP.ConnectionIdleTimeout != nil { + d, err := time.ParseDuration(string(*pto.HTTP.ConnectionIdleTimeout)) + if err != nil { + setBackendTrafficPolicyTranslationErrorCondition(policy, "HTTP Timeout", fmt.Sprintf("invalid ConnectionIdleTimeout value %s", *pto.HTTP.ConnectionIdleTimeout)) + terr = true + } else { + cit = ptr.To(metav1.Duration{Duration: d}) + } + } + + if pto.HTTP.MaxConnectionDuration != nil { + d, err := time.ParseDuration(string(*pto.HTTP.MaxConnectionDuration)) + if err != nil { + setBackendTrafficPolicyTranslationErrorCondition(policy, "HTTP Timeout", fmt.Sprintf("invalid MaxConnectionDuration value %s", *pto.HTTP.MaxConnectionDuration)) + terr = true + } else { + mcd = ptr.To(metav1.Duration{Duration: d}) + } + } + + hto = &ir.HTTPTimeout{ + ConnectionIdleTimeout: cit, + MaxConnectionDuration: mcd, + } + } + + // if backendtrafficpolicy is not translatable, return the original timeout if it's initialized + if terr { + if r.Timeout != nil { + return r.Timeout.DeepCopy() + } + } else { + // http request timeout is translated during the gateway-api route resource translation + // merge route timeout setting with backendtrafficpolicy timeout settings + if r.Timeout != nil && r.Timeout.HTTP != nil && r.Timeout.HTTP.RequestTimeout != nil { + if hto == nil { + hto = &ir.HTTPTimeout{ + RequestTimeout: r.Timeout.HTTP.RequestTimeout, + } + } else { + hto.RequestTimeout = r.Timeout.HTTP.RequestTimeout + } + } + + if hto != nil || tto != nil { + return &ir.Timeout{ + TCP: tto, + HTTP: hto, + } + } + } + + return nil +} + +func setBackendTrafficPolicyTranslationErrorCondition(policy *egv1a1.BackendTrafficPolicy, field, errMsg string) { + message := fmt.Sprintf("Unable to translate %s: %s", field, errMsg) status.SetBackendTrafficPolicyCondition(policy, gwv1a2.PolicyConditionAccepted, metav1.ConditionFalse, @@ -846,3 +984,35 @@ func (t *Translator) buildFaultInjection(policy *egv1a1.BackendTrafficPolicy) *i } return fi } + +func (t *Translator) buildTCPKeepAlive(policy *egv1a1.BackendTrafficPolicy) *ir.TCPKeepalive { + var ka *ir.TCPKeepalive + if policy.Spec.TCPKeepalive != nil { + pka := policy.Spec.TCPKeepalive + ka = &ir.TCPKeepalive{} + + if pka.Probes != nil { + ka.Probes = pka.Probes + } + + if pka.IdleTime != nil { + d, err := time.ParseDuration(string(*pka.IdleTime)) + if err != nil { + setBackendTrafficPolicyTranslationErrorCondition(policy, "TCP Keep Alive", fmt.Sprintf("invalid IdleTime value %s", *pka.IdleTime)) + return nil + } + ka.IdleTime = ptr.To(uint32(d.Seconds())) + } + + if pka.Interval != nil { + d, err := time.ParseDuration(string(*pka.Interval)) + if err != nil { + setBackendTrafficPolicyTranslationErrorCondition(policy, "TCP Keep Alive", fmt.Sprintf("invalid Interval value %s", *pka.Interval)) + return nil + } + ka.Interval = ptr.To(uint32(d.Seconds())) + } + + } + return ka +} diff --git a/internal/gatewayapi/clienttrafficpolicy.go b/internal/gatewayapi/clienttrafficpolicy.go index 7804a74f99f..5bd81cabf95 100644 --- a/internal/gatewayapi/clienttrafficpolicy.go +++ b/internal/gatewayapi/clienttrafficpolicy.go @@ -8,6 +8,7 @@ package gatewayapi import ( "fmt" "sort" + "strings" "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -31,11 +32,12 @@ func hasSectionName(policy *egv1a1.ClientTrafficPolicy) bool { return policy.Spec.TargetRef.SectionName != nil } -func (t *Translator) ProcessClientTrafficPolicies(clientTrafficPolicies []*egv1a1.ClientTrafficPolicy, +func (t *Translator) ProcessClientTrafficPolicies(resources *Resources, gateways []*GatewayContext, xdsIR XdsIRMap, infraIR InfraIRMap) []*egv1a1.ClientTrafficPolicy { var res []*egv1a1.ClientTrafficPolicy + clientTrafficPolicies := resources.ClientTrafficPolicies // Sort based on timestamp sort.Slice(clientTrafficPolicies, func(i, j int) bool { return clientTrafficPolicies[i].CreationTimestamp.Before(&(clientTrafficPolicies[j].CreationTimestamp)) @@ -89,19 +91,29 @@ func (t *Translator) ProcessClientTrafficPolicies(clientTrafficPolicies []*egv1a policyMap[key].Insert(section) // Translate for listener matching section name + var err error for _, l := range gateway.listeners { if string(l.Name) == section { - t.translateClientTrafficPolicyForListener(&policy.Spec, l, xdsIR, infraIR) + err = t.translateClientTrafficPolicyForListener(policy, l, xdsIR, infraIR, resources) break } } - // Set Accepted=True - status.SetClientTrafficPolicyCondition(policy, - gwv1a2.PolicyConditionAccepted, - metav1.ConditionTrue, - gwv1a2.PolicyReasonAccepted, - "ClientTrafficPolicy has been accepted.", - ) + if err != nil { + status.SetClientTrafficPolicyCondition(policy, + gwv1a2.PolicyConditionAccepted, + metav1.ConditionFalse, + gwv1a2.PolicyReasonInvalid, + status.Error2ConditionMsg(err), + ) + } else { + // Set Accepted=True + status.SetClientTrafficPolicyCondition(policy, + gwv1a2.PolicyConditionAccepted, + metav1.ConditionTrue, + gwv1a2.PolicyReasonAccepted, + "ClientTrafficPolicy has been accepted.", + ) + } } } @@ -162,22 +174,32 @@ func (t *Translator) ProcessClientTrafficPolicies(clientTrafficPolicies []*egv1a policyMap[key].Insert(AllSections) // Translate sections that have not yet been targeted + var err error for _, l := range gateway.listeners { // Skip if section has already been targeted if s != nil && s.Has(string(l.Name)) { continue } - t.translateClientTrafficPolicyForListener(&policy.Spec, l, xdsIR, infraIR) + err = t.translateClientTrafficPolicyForListener(policy, l, xdsIR, infraIR, resources) } - // Set Accepted=True - status.SetClientTrafficPolicyCondition(policy, - gwv1a2.PolicyConditionAccepted, - metav1.ConditionTrue, - gwv1a2.PolicyReasonAccepted, - "ClientTrafficPolicy has been accepted.", - ) + if err != nil { + status.SetClientTrafficPolicyCondition(policy, + gwv1a2.PolicyConditionAccepted, + metav1.ConditionFalse, + gwv1a2.PolicyReasonInvalid, + status.Error2ConditionMsg(err), + ) + } else { + // Set Accepted=True + status.SetClientTrafficPolicyCondition(policy, + gwv1a2.PolicyConditionAccepted, + metav1.ConditionTrue, + gwv1a2.PolicyReasonAccepted, + "ClientTrafficPolicy has been accepted.", + ) + } } } @@ -265,9 +287,10 @@ func resolveCTPolicyTargetRef(policy *egv1a1.ClientTrafficPolicy, gateways []*Ga return gateway } -func (t *Translator) translateClientTrafficPolicyForListener(policySpec *egv1a1.ClientTrafficPolicySpec, l *ListenerContext, xdsIR XdsIRMap, infraIR InfraIRMap) { +func (t *Translator) translateClientTrafficPolicyForListener(policy *egv1a1.ClientTrafficPolicy, l *ListenerContext, + xdsIR XdsIRMap, infraIR InfraIRMap, resources *Resources) error { // Find IR - irKey := irStringKey(l.gateway.Namespace, l.gateway.Name) + irKey := t.getIRKey(l.gateway) // It must exist since we've already finished processing the gateways gwXdsIR := xdsIR[irKey] @@ -287,19 +310,32 @@ func (t *Translator) translateClientTrafficPolicyForListener(policySpec *egv1a1. // IR must exist since we're past validation if httpIR != nil { // Translate TCPKeepalive - translateListenerTCPKeepalive(policySpec.TCPKeepalive, httpIR) + translateListenerTCPKeepalive(policy.Spec.TCPKeepalive, httpIR) // Translate Proxy Protocol - translateListenerProxyProtocol(policySpec.EnableProxyProtocol, httpIR) + translateListenerProxyProtocol(policy.Spec.EnableProxyProtocol, httpIR) + + // Translate Client IP Detection + translateClientIPDetection(policy.Spec.ClientIPDetection, httpIR) - // Translate Suppress Envoy Headers - translateListenerSuppressEnvoyHeaders(policySpec.SuppressEnvoyHeaders, httpIR) + // Translate Header Settings + translateListenerHeaderSettings(policy.Spec.Headers, httpIR) // Translate Path Settings - translatePathSettings(policySpec.Path, httpIR) + translatePathSettings(policy.Spec.Path, httpIR) + + // Translate Client Timeout Settings + if err := translateClientTimeout(policy.Spec.Timeout, httpIR); err != nil { + return err + } + + // Translate HTTP1 Settings + if err := translateHTTP1Settings(policy.Spec.HTTP1, httpIR); err != nil { + return err + } // enable http3 if set and TLS is enabled - if httpIR.TLS != nil && policySpec.HTTP3 != nil { + if httpIR.TLS != nil && policy.Spec.HTTP3 != nil { httpIR.HTTP3 = &ir.HTTP3Settings{} var proxyListenerIR *ir.ProxyListener for _, proxyListener := range infraIR[irKey].Proxy.Listeners { @@ -314,8 +350,11 @@ func (t *Translator) translateClientTrafficPolicyForListener(policySpec *egv1a1. } // Translate TLS parameters - translateListenerTLSParameters(policySpec.TLS, httpIR) + if err := t.translateListenerTLSParameters(policy, httpIR, resources); err != nil { + return err + } } + return nil } func translateListenerTCPKeepalive(tcpKeepAlive *egv1a1.TCPKeepalive, httpIR *ir.HTTPListener) { @@ -361,6 +400,35 @@ func translatePathSettings(pathSettings *egv1a1.PathSettings, httpIR *ir.HTTPLis } } +func translateClientTimeout(clientTimeout *egv1a1.ClientTimeout, httpIR *ir.HTTPListener) error { + if clientTimeout == nil { + return nil + } + + if clientTimeout.HTTP != nil { + if clientTimeout.HTTP.RequestReceivedTimeout != nil { + d, err := time.ParseDuration(string(*clientTimeout.HTTP.RequestReceivedTimeout)) + if err != nil { + return err + } + switch { + case httpIR.Timeout == nil: + httpIR.Timeout = &ir.ClientTimeout{} + fallthrough + + case httpIR.Timeout.HTTP == nil: + httpIR.Timeout.HTTP = &ir.HTTPClientTimeout{} + } + + httpIR.Timeout.HTTP.RequestReceivedTimeout = &metav1.Duration{ + Duration: d, + } + } + } + + return nil +} + func translateListenerProxyProtocol(enableProxyProtocol *bool, httpIR *ir.HTTPListener) { // Return early if not set if enableProxyProtocol == nil { @@ -372,19 +440,67 @@ func translateListenerProxyProtocol(enableProxyProtocol *bool, httpIR *ir.HTTPLi } } -func translateListenerSuppressEnvoyHeaders(suppressEnvoyHeaders *bool, httpIR *ir.HTTPListener) { - if suppressEnvoyHeaders != nil { - httpIR.SuppressEnvoyHeaders = *suppressEnvoyHeaders +func translateClientIPDetection(clientIPDetection *egv1a1.ClientIPDetectionSettings, httpIR *ir.HTTPListener) { + // Return early if not set + if clientIPDetection == nil { + return } + + httpIR.ClientIPDetection = (*ir.ClientIPDetectionSettings)(clientIPDetection) } -func translateListenerTLSParameters(tlsParams *egv1a1.TLSSettings, httpIR *ir.HTTPListener) { +func translateListenerHeaderSettings(headerSettings *egv1a1.HeaderSettings, httpIR *ir.HTTPListener) { + if headerSettings == nil { + return + } + httpIR.Headers = &ir.HeaderSettings{ + EnableEnvoyHeaders: ptr.Deref(headerSettings.EnableEnvoyHeaders, false), + } +} + +func translateHTTP1Settings(http1Settings *egv1a1.HTTP1Settings, httpIR *ir.HTTPListener) error { + if http1Settings == nil { + return nil + } + httpIR.HTTP1 = &ir.HTTP1Settings{ + EnableTrailers: ptr.Deref(http1Settings.EnableTrailers, false), + PreserveHeaderCase: ptr.Deref(http1Settings.PreserveHeaderCase, false), + } + if http1Settings.HTTP10 != nil { + var defaultHost *string + if ptr.Deref(http1Settings.HTTP10.UseDefaultHost, false) { + for _, hostname := range httpIR.Hostnames { + if !strings.Contains(hostname, "*") { + // make linter happy + theHost := hostname + defaultHost = &theHost + break + } + } + if defaultHost == nil { + return fmt.Errorf("can't set http10 default host on listener with only wildcard hostnames") + } + } + // If useDefaultHost was set, then defaultHost will have the hostname to use. + // If no good hostname was found, an error would have been returned. + httpIR.HTTP1.HTTP10 = &ir.HTTP10Settings{ + DefaultHost: defaultHost, + } + } + return nil +} + +func (t *Translator) translateListenerTLSParameters(policy *egv1a1.ClientTrafficPolicy, + httpIR *ir.HTTPListener, resources *Resources) error { // Return if this listener isn't a TLS listener. There has to be // at least one certificate defined, which would cause httpIR to // have a TLS structure. if httpIR.TLS == nil { - return + return nil } + + tlsParams := policy.Spec.TLS + // Make sure that the negotiated TLS protocol version is as expected if TLS is used, // regardless of if TLS parameters were used in the ClientTrafficPolicy or not httpIR.TLS.MinVersion = ptr.To(ir.TLSv12) @@ -399,10 +515,12 @@ func translateListenerTLSParameters(tlsParams *egv1a1.TLSSettings, httpIR *ir.HT httpIR.TLS.ALPNProtocols[i] = string(tlsParams.ALPNProtocols[i]) } } + // Return early if not set if tlsParams == nil { - return + return nil } + if tlsParams.MinVersion != nil { httpIR.TLS.MinVersion = ptr.To(ir.TLSVersion(*tlsParams.MinVersion)) } @@ -418,4 +536,55 @@ func translateListenerTLSParameters(tlsParams *egv1a1.TLSSettings, httpIR *ir.HT if len(tlsParams.SignatureAlgorithms) > 0 { httpIR.TLS.SignatureAlgorithms = tlsParams.SignatureAlgorithms } + + if tlsParams.ClientValidation != nil { + from := crossNamespaceFrom{ + group: egv1a1.GroupName, + kind: KindClientTrafficPolicy, + namespace: policy.Namespace, + } + + irCACert := &ir.TLSCACertificate{ + Name: irTLSCACertName(policy.Namespace, policy.Name), + } + + for _, caCertRef := range tlsParams.ClientValidation.CACertificateRefs { + if caCertRef.Kind == nil || string(*caCertRef.Kind) == KindSecret { // nolint + secret, err := t.validateSecretRef(false, from, caCertRef, resources) + if err != nil { + return err + } + + secretBytes, ok := secret.Data[caCertKey] + if !ok || len(secretBytes) == 0 { + return fmt.Errorf( + "caCertificateRef not found in secret %s", caCertRef.Name) + } + + irCACert.Certificate = append(irCACert.Certificate, secretBytes...) + + } else if string(*caCertRef.Kind) == KindConfigMap { + configMap, err := t.validateConfigMapRef(false, from, caCertRef, resources) + if err != nil { + return err + } + + configMapBytes, ok := configMap.Data[caCertKey] + if !ok || len(configMapBytes) == 0 { + return fmt.Errorf( + "caCertificateRef not found in configMap %s", caCertRef.Name) + } + + irCACert.Certificate = append(irCACert.Certificate, configMapBytes...) + } else { + return fmt.Errorf("unsupported caCertificateRef kind:%s", string(*caCertRef.Kind)) + } + } + + if len(irCACert.Certificate) > 0 { + httpIR.TLS.CACertificate = irCACert + } + } + + return nil } diff --git a/internal/gatewayapi/contexts_test.go b/internal/gatewayapi/contexts_test.go index 7a6b1897113..5c016f8b40b 100644 --- a/internal/gatewayapi/contexts_test.go +++ b/internal/gatewayapi/contexts_test.go @@ -40,21 +40,21 @@ func TestContexts(t *testing.T) { lctx.SetCondition(gwapiv1.ListenerConditionAccepted, metav1.ConditionFalse, gwapiv1.ListenerReasonUnsupportedProtocol, "HTTPS protocol is not supported yet") require.Len(t, gateway.Status.Listeners, 1) - require.EqualValues(t, gateway.Status.Listeners[0].Name, "http") + require.EqualValues(t, "http", gateway.Status.Listeners[0].Name) require.Len(t, gateway.Status.Listeners[0].Conditions, 1) - require.EqualValues(t, gateway.Status.Listeners[0].Conditions[0].Type, gwapiv1.ListenerConditionAccepted) - require.EqualValues(t, gateway.Status.Listeners[0].Conditions[0].Status, metav1.ConditionFalse) - require.EqualValues(t, gateway.Status.Listeners[0].Conditions[0].Reason, gwapiv1.ListenerReasonUnsupportedProtocol) - require.EqualValues(t, gateway.Status.Listeners[0].Conditions[0].Message, "HTTPS protocol is not supported yet") + require.EqualValues(t, gwapiv1.ListenerConditionAccepted, gateway.Status.Listeners[0].Conditions[0].Type) + require.EqualValues(t, metav1.ConditionFalse, gateway.Status.Listeners[0].Conditions[0].Status) + require.EqualValues(t, gwapiv1.ListenerReasonUnsupportedProtocol, gateway.Status.Listeners[0].Conditions[0].Reason) + require.EqualValues(t, "HTTPS protocol is not supported yet", gateway.Status.Listeners[0].Conditions[0].Message) lctx.SetSupportedKinds(gwapiv1.RouteGroupKind{Group: GroupPtr(gwapiv1.GroupName), Kind: "HTTPRoute"}) require.Len(t, gateway.Status.Listeners, 1) require.Len(t, gateway.Status.Listeners[0].SupportedKinds, 1) - require.EqualValues(t, gateway.Status.Listeners[0].SupportedKinds[0].Kind, "HTTPRoute") + require.EqualValues(t, "HTTPRoute", gateway.Status.Listeners[0].SupportedKinds[0].Kind) gctx.ResetListeners() - require.Len(t, gateway.Status.Listeners[0].Conditions, 0) + require.Empty(t, gateway.Status.Listeners[0].Conditions) } func TestContextsStaleListener(t *testing.T) { diff --git a/internal/gatewayapi/envoypatchpolicy.go b/internal/gatewayapi/envoypatchpolicy.go index 3f65c713181..2b3025d809a 100644 --- a/internal/gatewayapi/envoypatchpolicy.go +++ b/internal/gatewayapi/envoypatchpolicy.go @@ -94,6 +94,16 @@ func (t *Translator) ProcessEnvoyPatchPolicies(envoyPatchPolicies []*egv1a1.Envo continue } + if !t.EnvoyPatchPolicyEnabled { + status.SetEnvoyPatchPolicyCondition(policy, + gwv1a2.PolicyConditionAccepted, + metav1.ConditionFalse, + egv1a1.PolicyReasonDisabled, + "EnvoyPatchPolicy is disabled in the EnvoyGateway configuration", + ) + continue + } + // Save the patch for _, patch := range policy.Spec.JSONPatches { irPatch := ir.JSONPatchConfig{} @@ -101,6 +111,7 @@ func (t *Translator) ProcessEnvoyPatchPolicies(envoyPatchPolicies []*egv1a1.Envo irPatch.Name = patch.Name irPatch.Operation.Op = string(patch.Operation.Op) irPatch.Operation.Path = patch.Operation.Path + irPatch.Operation.From = patch.Operation.From irPatch.Operation.Value = patch.Operation.Value policyIR.JSONPatches = append(policyIR.JSONPatches, &irPatch) diff --git a/internal/gatewayapi/helpers.go b/internal/gatewayapi/helpers.go index d0ac26fcf11..4c4ef61aece 100644 --- a/internal/gatewayapi/helpers.go +++ b/internal/gatewayapi/helpers.go @@ -13,6 +13,7 @@ import ( v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" "sigs.k8s.io/gateway-api/apis/v1alpha2" @@ -25,6 +26,8 @@ const ( L4Protocol = "L4" L7Protocol = "L7" + + caCertKey = "ca.crt" ) type protocolPort struct { @@ -66,34 +69,12 @@ func ObjectNamePtr(val string) *v1alpha2.ObjectName { return &objectName } -func PathMatchTypeDerefOr(matchType *gwapiv1.PathMatchType, defaultType gwapiv1.PathMatchType) gwapiv1.PathMatchType { - if matchType != nil { - return *matchType - } - return defaultType -} - -func GRPCMethodMatchTypeDerefOr(matchType *v1alpha2.GRPCMethodMatchType, defaultType v1alpha2.GRPCMethodMatchType) v1alpha2.GRPCMethodMatchType { - if matchType != nil { - return *matchType - } - return defaultType -} - -func HeaderMatchTypeDerefOr(matchType *gwapiv1.HeaderMatchType, defaultType gwapiv1.HeaderMatchType) gwapiv1.HeaderMatchType { - if matchType != nil { - return *matchType - } - return defaultType -} - -func QueryParamMatchTypeDerefOr(matchType *gwapiv1.QueryParamMatchType, - defaultType gwapiv1.QueryParamMatchType) gwapiv1.QueryParamMatchType { - if matchType != nil { - return *matchType - } - return defaultType -} +var ( + PathMatchTypeDerefOr = ptr.Deref[gwapiv1.PathMatchType] + GRPCMethodMatchTypeDerefOr = ptr.Deref[v1alpha2.GRPCMethodMatchType] + HeaderMatchTypeDerefOr = ptr.Deref[gwapiv1.HeaderMatchType] + QueryParamMatchTypeDerefOr = ptr.Deref[gwapiv1.QueryParamMatchType] +) func NamespaceDerefOr(namespace *gwapiv1.Namespace, defaultNamespace string) string { if namespace != nil && *namespace != "" { @@ -410,7 +391,11 @@ func irTLSConfigs(tlsSecrets []*v1.Secret) *ir.TLSConfig { } func irTLSListenerConfigName(secret *v1.Secret) string { - return fmt.Sprintf("%s-%s", secret.Namespace, secret.Name) + return fmt.Sprintf("%s/%s", secret.Namespace, secret.Name) +} + +func irTLSCACertName(namespace, name string) string { + return fmt.Sprintf("%s/%s/%s", namespace, name, caCertKey) } func isMergeGatewaysEnabled(resources *Resources) bool { diff --git a/internal/gatewayapi/resource.go b/internal/gatewayapi/resource.go index 6dc630ddc72..a7a16f664b4 100644 --- a/internal/gatewayapi/resource.go +++ b/internal/gatewayapi/resource.go @@ -20,6 +20,41 @@ import ( type XdsIRMap map[string]*ir.Xds type InfraIRMap map[string]*ir.Infra +type GatewayClassResources map[string]*Resources + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +// This was generated by controller-gen and moved over from +// zz_generated.deepcopy.go to this file. +func (in GatewayClassResources) DeepCopyInto(out *GatewayClassResources) { + { + in := &in + *out = make(GatewayClassResources, len(*in)) + for key, val := range *in { + var outVal *Resources + if val == nil { + (*out)[key] = nil + } else { + inVal := (*in)[key] + in, out := &inVal, &outVal + *out = new(Resources) + (*in).DeepCopyInto(*out) + } + (*out)[key] = outVal + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassResources. +// This was generated by controller-gen and moved over from +// zz_generated.deepcopy.go to this file. +func (in GatewayClassResources) DeepCopy() *GatewayClassResources { + if in == nil { + return nil + } + out := new(GatewayClassResources) + in.DeepCopyInto(out) + return out +} // Resources holds the Gateway API and related // resources that the translators needs as inputs. @@ -40,6 +75,7 @@ type Resources struct { ServiceImports []*mcsapi.ServiceImport `json:"serviceImports,omitempty" yaml:"serviceImports,omitempty"` EndpointSlices []*discoveryv1.EndpointSlice `json:"endpointSlices,omitempty" yaml:"endpointSlices,omitempty"` Secrets []*v1.Secret `json:"secrets,omitempty" yaml:"secrets,omitempty"` + ConfigMaps []*v1.ConfigMap `json:"configMaps,omitempty" yaml:"configMaps,omitempty"` EnvoyProxy *egv1a1.EnvoyProxy `json:"envoyProxy,omitempty" yaml:"envoyProxy,omitempty"` ExtensionRefFilters []unstructured.Unstructured `json:"extensionRefFilters,omitempty" yaml:"extensionRefFilters,omitempty"` EnvoyPatchPolicies []*egv1a1.EnvoyPatchPolicy `json:"envoyPatchPolicies,omitempty" yaml:"envoyPatchPolicies,omitempty"` @@ -57,6 +93,7 @@ func NewResources() *Resources { Services: []*v1.Service{}, EndpointSlices: []*discoveryv1.EndpointSlice{}, Secrets: []*v1.Secret{}, + ConfigMaps: []*v1.ConfigMap{}, ReferenceGrants: []*gwapiv1b1.ReferenceGrant{}, Namespaces: []*v1.Namespace{}, ExtensionRefFilters: []unstructured.Unstructured{}, @@ -107,6 +144,16 @@ func (r *Resources) GetSecret(namespace, name string) *v1.Secret { return nil } +func (r *Resources) GetConfigMap(namespace, name string) *v1.ConfigMap { + for _, configMap := range r.ConfigMaps { + if configMap.Namespace == namespace && configMap.Name == name { + return configMap + } + } + + return nil +} + func (r *Resources) GetEndpointSlicesForBackend(svcNamespace, svcName string, backendKind string) []*discoveryv1.EndpointSlice { var endpointSlices []*discoveryv1.EndpointSlice for _, endpointSlice := range r.EndpointSlices { diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index 80d43210a9d..b7e082c849d 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -23,6 +23,13 @@ import ( "github.com/envoyproxy/gateway/internal/utils/regex" ) +const ( + // Following the description in `timeout` section of https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto + // Request timeout, which is defined as Duration, specifies the upstream timeout for the route + // If not specified, the default is 15s + HTTPRequestTimeout = "15s" +) + var ( _ RoutesTranslator = (*Translator)(nil) validServiceName = `(?i)\.?[a-z_][a-z_0-9]*(\.[a-z_][a-z_0-9]*)*` @@ -220,19 +227,51 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe func processTimeout(irRoute *ir.HTTPRoute, rule gwapiv1.HTTPRouteRule) { if rule.Timeouts != nil { + var rto *ir.Timeout + + // Timeout is translated from multiple resources and may already be partially set + if irRoute.Timeout != nil { + rto = irRoute.Timeout.DeepCopy() + } else { + rto = &ir.Timeout{} + } + if rule.Timeouts.Request != nil { - // TODO: handle parse errors - d, _ := time.ParseDuration(string(*rule.Timeouts.Request)) - irRoute.Timeout = ptr.To(metav1.Duration{Duration: d}) + d, err := time.ParseDuration(string(*rule.Timeouts.Request)) + if err != nil { + d, _ = time.ParseDuration(HTTPRequestTimeout) + } + setRequestTimeout(rto, metav1.Duration{Duration: d}) } // Also set the IR Route Timeout to the backend request timeout // until we introduce retries, then set it to per try timeout if rule.Timeouts.BackendRequest != nil { - // TODO: handle parse errors - d, _ := time.ParseDuration(string(*rule.Timeouts.BackendRequest)) - irRoute.Timeout = ptr.To(metav1.Duration{Duration: d}) + d, err := time.ParseDuration(string(*rule.Timeouts.BackendRequest)) + if err != nil { + d, _ = time.ParseDuration(HTTPRequestTimeout) + } + setRequestTimeout(rto, metav1.Duration{Duration: d}) } + + irRoute.Timeout = rto + } +} + +func setRequestTimeout(irTimeout *ir.Timeout, d metav1.Duration) { + switch { + case irTimeout == nil: + irTimeout = &ir.Timeout{ + HTTP: &ir.HTTPTimeout{ + RequestTimeout: ptr.To(d), + }, + } + case irTimeout.HTTP == nil: + irTimeout.HTTP = &ir.HTTPTimeout{ + RequestTimeout: ptr.To(d), + } + default: + irTimeout.HTTP.RequestTimeout = ptr.To(d) } } @@ -616,8 +655,8 @@ func (t *Translator) processHTTPRouteParentRefListener(route RouteContext, route DirectResponse: routeRoute.DirectResponse, URLRewrite: routeRoute.URLRewrite, Mirrors: routeRoute.Mirrors, - Timeout: routeRoute.Timeout, ExtensionRefs: routeRoute.ExtensionRefs, + Timeout: routeRoute.Timeout, } // Don't bother copying over the weights unless the route has invalid backends. if routeRoute.BackendWeights.Invalid > 0 { @@ -1042,6 +1081,11 @@ func (t *Translator) processDestination(backendRef gwapiv1.BackendRef, return nil, weight } + // Skip processing backends with 0 weight + if weight == 0 { + return nil, weight + } + var ( endpoints []*ir.DestinationEndpoint addrType *ir.DestinationAddressType diff --git a/internal/gatewayapi/runner/runner.go b/internal/gatewayapi/runner/runner.go index 835ce10fd05..ac2ec3140a0 100644 --- a/internal/gatewayapi/runner/runner.go +++ b/internal/gatewayapi/runner/runner.go @@ -10,7 +10,6 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" v1 "sigs.k8s.io/gateway-api/apis/v1" - "sigs.k8s.io/yaml" "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/envoygateway/config" @@ -50,65 +49,113 @@ func (r *Runner) Start(ctx context.Context) (err error) { func (r *Runner) subscribeAndTranslate(ctx context.Context) { message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentGatewayAPIRunner), Message: "provider-resources"}, r.ProviderResources.GatewayAPIResources.Subscribe(ctx), - func(update message.Update[string, *gatewayapi.Resources], errChan chan error) { + func(update message.Update[string, *gatewayapi.GatewayClassResources], errChan chan error) { r.Logger.Info("received an update") - val := update.Value - + // There is only 1 key which is the controller name + // so when a delete is triggered, delete all IR keys if update.Delete || val == nil { + r.deleteAllIRKeys() return } - // Translate and publish IRs. - t := &gatewayapi.Translator{ - GatewayControllerName: r.Server.EnvoyGateway.Gateway.ControllerName, - GatewayClassName: v1.ObjectName(update.Key), - GlobalRateLimitEnabled: r.EnvoyGateway.RateLimit != nil, - } - - // If an extension is loaded, pass its supported groups/kinds to the translator - if r.EnvoyGateway.ExtensionManager != nil { - var extGKs []schema.GroupKind - for _, gvk := range r.EnvoyGateway.ExtensionManager.Resources { - extGKs = append(extGKs, schema.GroupKind{Group: gvk.Group, Kind: gvk.Kind}) - } - t.ExtensionGroupKinds = extGKs - } - // Translate to IR - result := t.Translate(val) - - yamlXdsIR, _ := yaml.Marshal(&result.XdsIR) - r.Logger.WithValues("output", "xds-ir").Info(string(yamlXdsIR)) - yamlInfraIR, _ := yaml.Marshal(&result.InfraIR) - r.Logger.WithValues("output", "infra-ir").Info(string(yamlInfraIR)) - var curKeys, newKeys []string // Get current IR keys for key := range r.InfraIR.LoadAll() { curKeys = append(curKeys, key) } - // Publish the IRs. - // Also validate the ir before sending it. - for key, val := range result.InfraIR { - if err := val.Validate(); err != nil { - r.Logger.Error(err, "unable to validate infra ir, skipped sending it") - errChan <- err - } else { - r.InfraIR.Store(key, val) - newKeys = append(newKeys, key) + for gc, resources := range *val { + // Translate and publish IRs. + t := &gatewayapi.Translator{ + GatewayControllerName: r.Server.EnvoyGateway.Gateway.ControllerName, + GatewayClassName: v1.ObjectName(gc), + GlobalRateLimitEnabled: r.EnvoyGateway.RateLimit != nil, + EnvoyPatchPolicyEnabled: r.EnvoyGateway.ExtensionAPIs != nil && r.EnvoyGateway.ExtensionAPIs.EnableEnvoyPatchPolicy, } - } - for key, val := range result.XdsIR { - if err := val.Validate(); err != nil { - r.Logger.Error(err, "unable to validate xds ir, skipped sending it") - errChan <- err - } else { - r.XdsIR.Store(key, val) + // If an extension is loaded, pass its supported groups/kinds to the translator + if r.EnvoyGateway.ExtensionManager != nil { + var extGKs []schema.GroupKind + for _, gvk := range r.EnvoyGateway.ExtensionManager.Resources { + extGKs = append(extGKs, schema.GroupKind{Group: gvk.Group, Kind: gvk.Kind}) + } + t.ExtensionGroupKinds = extGKs + } + // Translate to IR + result := t.Translate(resources) + + // Publish the IRs. + // Also validate the ir before sending it. + for key, val := range result.InfraIR { + r.Logger.WithValues("infra-ir", key).Info(val.YAMLString()) + if err := val.Validate(); err != nil { + r.Logger.Error(err, "unable to validate infra ir, skipped sending it") + errChan <- err + } else { + r.InfraIR.Store(key, val) + newKeys = append(newKeys, key) + } + } + + for key, val := range result.XdsIR { + r.Logger.WithValues("xds-ir", key).Info(val.YAMLString()) + if err := val.Validate(); err != nil { + r.Logger.Error(err, "unable to validate xds ir, skipped sending it") + errChan <- err + } else { + r.XdsIR.Store(key, val) + } } - } + // Update Status + for _, gateway := range result.Gateways { + gateway := gateway + key := utils.NamespacedName(gateway) + r.ProviderResources.GatewayStatuses.Store(key, &gateway.Status) + } + for _, httpRoute := range result.HTTPRoutes { + httpRoute := httpRoute + key := utils.NamespacedName(httpRoute) + r.ProviderResources.HTTPRouteStatuses.Store(key, &httpRoute.Status) + } + for _, grpcRoute := range result.GRPCRoutes { + grpcRoute := grpcRoute + key := utils.NamespacedName(grpcRoute) + r.ProviderResources.GRPCRouteStatuses.Store(key, &grpcRoute.Status) + } + + for _, tlsRoute := range result.TLSRoutes { + tlsRoute := tlsRoute + key := utils.NamespacedName(tlsRoute) + r.ProviderResources.TLSRouteStatuses.Store(key, &tlsRoute.Status) + } + for _, tcpRoute := range result.TCPRoutes { + tcpRoute := tcpRoute + key := utils.NamespacedName(tcpRoute) + r.ProviderResources.TCPRouteStatuses.Store(key, &tcpRoute.Status) + } + for _, udpRoute := range result.UDPRoutes { + udpRoute := udpRoute + key := utils.NamespacedName(udpRoute) + r.ProviderResources.UDPRouteStatuses.Store(key, &udpRoute.Status) + } + for _, clientTrafficPolicy := range result.ClientTrafficPolicies { + clientTrafficPolicy := clientTrafficPolicy + key := utils.NamespacedName(clientTrafficPolicy) + r.ProviderResources.ClientTrafficPolicyStatuses.Store(key, &clientTrafficPolicy.Status) + } + for _, backendTrafficPolicy := range result.BackendTrafficPolicies { + backendTrafficPolicy := backendTrafficPolicy + key := utils.NamespacedName(backendTrafficPolicy) + r.ProviderResources.BackendTrafficPolicyStatuses.Store(key, &backendTrafficPolicy.Status) + } + for _, securityPolicy := range result.SecurityPolicies { + securityPolicy := securityPolicy + key := utils.NamespacedName(securityPolicy) + r.ProviderResources.SecurityPolicyStatuses.Store(key, &securityPolicy.Status) + } + } // Delete keys // There is a 1:1 mapping between infra and xds IR keys delKeys := getIRKeysToDelete(curKeys, newKeys) @@ -116,59 +163,19 @@ func (r *Runner) subscribeAndTranslate(ctx context.Context) { r.InfraIR.Delete(key) r.XdsIR.Delete(key) } - - // Update Status - for _, gateway := range result.Gateways { - gateway := gateway - key := utils.NamespacedName(gateway) - r.ProviderResources.GatewayStatuses.Store(key, &gateway.Status) - } - for _, httpRoute := range result.HTTPRoutes { - httpRoute := httpRoute - key := utils.NamespacedName(httpRoute) - r.ProviderResources.HTTPRouteStatuses.Store(key, &httpRoute.Status) - } - for _, grpcRoute := range result.GRPCRoutes { - grpcRoute := grpcRoute - key := utils.NamespacedName(grpcRoute) - r.ProviderResources.GRPCRouteStatuses.Store(key, &grpcRoute.Status) - } - - for _, tlsRoute := range result.TLSRoutes { - tlsRoute := tlsRoute - key := utils.NamespacedName(tlsRoute) - r.ProviderResources.TLSRouteStatuses.Store(key, &tlsRoute.Status) - } - for _, tcpRoute := range result.TCPRoutes { - tcpRoute := tcpRoute - key := utils.NamespacedName(tcpRoute) - r.ProviderResources.TCPRouteStatuses.Store(key, &tcpRoute.Status) - } - for _, udpRoute := range result.UDPRoutes { - udpRoute := udpRoute - key := utils.NamespacedName(udpRoute) - r.ProviderResources.UDPRouteStatuses.Store(key, &udpRoute.Status) - } - for _, clientTrafficPolicy := range result.ClientTrafficPolicies { - clientTrafficPolicy := clientTrafficPolicy - key := utils.NamespacedName(clientTrafficPolicy) - r.ProviderResources.ClientTrafficPolicyStatuses.Store(key, &clientTrafficPolicy.Status) - } - for _, backendTrafficPolicy := range result.BackendTrafficPolicies { - backendTrafficPolicy := backendTrafficPolicy - key := utils.NamespacedName(backendTrafficPolicy) - r.ProviderResources.BackendTrafficPolicyStatuses.Store(key, &backendTrafficPolicy.Status) - } - for _, securityPolicy := range result.SecurityPolicies { - securityPolicy := securityPolicy - key := utils.NamespacedName(securityPolicy) - r.ProviderResources.SecurityPolicyStatuses.Store(key, &securityPolicy.Status) - } }, ) r.Logger.Info("shutting down") } +// deleteAllIRKeys deletes all XdsIR and InfraIR +func (r *Runner) deleteAllIRKeys() { + for key := range r.InfraIR.LoadAll() { + r.InfraIR.Delete(key) + r.XdsIR.Delete(key) + } +} + // getIRKeysToDelete returns the list of IR keys to delete // based on the difference between the current keys and the // new keys parameters passed to the function. diff --git a/internal/gatewayapi/securitypolicy.go b/internal/gatewayapi/securitypolicy.go index c9af4e4ef6a..0e5d91145e5 100644 --- a/internal/gatewayapi/securitypolicy.go +++ b/internal/gatewayapi/securitypolicy.go @@ -7,9 +7,11 @@ package gatewayapi import ( "encoding/json" + "errors" "fmt" - "net" + "hash/fnv" "net/http" + "net/netip" "net/url" "sort" "strconv" @@ -19,11 +21,10 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/utils/ptr" + gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" gwv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" gwv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" - "github.com/tetratelabs/multierror" - egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/ir" "github.com/envoyproxy/gateway/internal/status" @@ -270,6 +271,7 @@ func (t *Translator) translateSecurityPolicyForRoute( jwt *ir.JWT oidc *ir.OIDC basicAuth *ir.BasicAuth + extAuth *ir.ExtAuth err, errs error ) @@ -283,13 +285,19 @@ func (t *Translator) translateSecurityPolicyForRoute( if policy.Spec.OIDC != nil { if oidc, err = t.buildOIDC(policy, resources); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } if policy.Spec.BasicAuth != nil { if basicAuth, err = t.buildBasicAuth(policy, resources); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) + } + } + + if policy.Spec.ExtAuth != nil { + if extAuth, err = t.buildExtAuth(policy, resources); err != nil { + errs = errors.Join(errs, err) } } @@ -308,6 +316,7 @@ func (t *Translator) translateSecurityPolicyForRoute( r.JWT = jwt r.OIDC = oidc r.BasicAuth = basicAuth + r.ExtAuth = extAuth } } } @@ -324,6 +333,7 @@ func (t *Translator) translateSecurityPolicyForGateway( jwt *ir.JWT oidc *ir.OIDC basicAuth *ir.BasicAuth + extAuth *ir.ExtAuth err, errs error ) @@ -337,13 +347,19 @@ func (t *Translator) translateSecurityPolicyForGateway( if policy.Spec.OIDC != nil { if oidc, err = t.buildOIDC(policy, resources); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } if policy.Spec.BasicAuth != nil { if basicAuth, err = t.buildBasicAuth(policy, resources); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) + } + } + + if policy.Spec.ExtAuth != nil { + if extAuth, err = t.buildExtAuth(policy, resources); err != nil { + errs = errors.Join(errs, err) } } @@ -372,6 +388,9 @@ func (t *Translator) translateSecurityPolicyForGateway( if r.BasicAuth == nil { r.BasicAuth = basicAuth } + if r.ExtAuth == nil { + r.ExtAuth = extAuth + } } } return errs @@ -471,9 +490,17 @@ func (t *Translator) buildOIDC( } redirectURL = *oidc.RedirectURL redirectPath = path + } + if oidc.LogoutPath != nil { logoutPath = *oidc.LogoutPath } + h := fnv.New32a() + if _, err = h.Write([]byte(policy.UID)); err != nil { + return nil, fmt.Errorf("error generating oauth cookie suffix: %w", err) + } + suffix := fmt.Sprintf("%X", h.Sum32()) + return &ir.OIDC{ Provider: *provider, ClientID: oidc.ClientID, @@ -482,6 +509,7 @@ func (t *Translator) buildOIDC( RedirectURL: redirectURL, RedirectPath: redirectPath, LogoutPath: logoutPath, + CookieSuffix: suffix, }, nil } @@ -578,8 +606,8 @@ func validateTokenEndpoint(tokenEndpoint string) error { return fmt.Errorf("token endpoint URL scheme must be https: %s", tokenEndpoint) } - if ip := net.ParseIP(parsedURL.Hostname()); ip != nil { - if v4 := ip.To4(); v4 != nil { + if ip, err := netip.ParseAddr(parsedURL.Hostname()); err == nil { + if ip.Unmap().Is4() { return fmt.Errorf("token endpoint URL must be a domain name: %s", tokenEndpoint) } } @@ -625,3 +653,138 @@ func (t *Translator) buildBasicAuth( return &ir.BasicAuth{Users: usersSecretBytes}, nil } + +func (t *Translator) buildExtAuth( + policy *egv1a1.SecurityPolicy, + resources *Resources) (*ir.ExtAuth, error) { + var ( + http = policy.Spec.ExtAuth.HTTP + grpc = policy.Spec.ExtAuth.GRPC + backendRef *gwapiv1.BackendObjectReference + protocol ir.AppProtocol + ds *ir.DestinationSetting + authority string + err error + ) + + switch { + // These are sanity checks, they should never happen because the API server + // should have caught them + case http == nil && grpc == nil: + return nil, errors.New("one of grpc or http must be specified") + case http != nil && grpc != nil: + return nil, errors.New("only one of grpc or http can be specified") + case http != nil: + backendRef = &http.BackendRef + protocol = ir.HTTP + case grpc != nil: + backendRef = &grpc.BackendRef + protocol = ir.GRPC + } + + if err = t.validateExtServiceBackendReference( + backendRef, + policy.Namespace, + resources); err != nil { + return nil, err + } + authority = fmt.Sprintf( + "%s.%s:%d", + backendRef.Name, + NamespaceDerefOr(backendRef.Namespace, policy.Namespace), + *backendRef.Port) + + if ds, err = t.processExtServiceDestination( + backendRef, + policy.Namespace, + protocol, + resources); err != nil { + return nil, err + } + rd := ir.RouteDestination{ + Name: irExtServiceDestinationName(policy, string(backendRef.Name)), + Settings: []*ir.DestinationSetting{ds}, + } + + extAuth := &ir.ExtAuth{ + HeadersToExtAuth: policy.Spec.ExtAuth.HeadersToExtAuth, + } + + if http != nil { + extAuth.HTTP = &ir.HTTPExtAuthService{ + Destination: rd, + Authority: authority, + Path: ptr.Deref(http.Path, ""), + HeadersToBackend: http.HeadersToBackend, + } + } else { + extAuth.GRPC = &ir.GRPCExtAuthService{ + Destination: rd, + Authority: authority, + } + } + return extAuth, nil +} + +// TODO: zhaohuabing combine this function with the one in the route translator +func (t *Translator) processExtServiceDestination( + backendRef *gwapiv1.BackendObjectReference, + ownerNamespace string, + protocol ir.AppProtocol, + resources *Resources) (*ir.DestinationSetting, error) { + var ( + endpoints []*ir.DestinationEndpoint + addrType *ir.DestinationAddressType + servicePort v1.ServicePort + ) + + serviceNamespace := NamespaceDerefOr(backendRef.Namespace, ownerNamespace) + service := resources.GetService(serviceNamespace, string(backendRef.Name)) + for _, port := range service.Spec.Ports { + if port.Port == int32(*backendRef.Port) { + servicePort = port + break + } + } + + if servicePort.AppProtocol != nil && + *servicePort.AppProtocol == "kubernetes.io/h2c" { + protocol = ir.HTTP2 + } + + // Route to endpoints by default + if !t.EndpointRoutingDisabled { + endpointSlices := resources.GetEndpointSlicesForBackend( + serviceNamespace, string(backendRef.Name), KindService) + endpoints, addrType = getIREndpointsFromEndpointSlices( + endpointSlices, servicePort.Name, servicePort.Protocol) + } else { + // Fall back to Service ClusterIP routing + ep := ir.NewDestEndpoint( + service.Spec.ClusterIP, + uint32(*backendRef.Port)) + endpoints = append(endpoints, ep) + } + + // TODO: support mixed endpointslice address type for the same backendRef + if !t.EndpointRoutingDisabled && addrType != nil && *addrType == ir.MIXED { + return nil, errors.New( + "mixed endpointslice address type for the same backendRef is not supported") + } + + return &ir.DestinationSetting{ + Weight: ptr.To(uint32(1)), + Protocol: protocol, + Endpoints: endpoints, + AddressType: addrType, + }, nil +} + +func irExtServiceDestinationName(policy *egv1a1.SecurityPolicy, service string) string { + return strings.ToLower(fmt.Sprintf( + "%s/%s/%s/%s", + KindSecurityPolicy, + policy.GetNamespace(), + policy.GetName(), + service)) +} diff --git a/internal/gatewayapi/securitypolicy_test.go b/internal/gatewayapi/securitypolicy_test.go index 28f2510f45d..829144b81b0 100644 --- a/internal/gatewayapi/securitypolicy_test.go +++ b/internal/gatewayapi/securitypolicy_test.go @@ -62,15 +62,33 @@ func Test_wildcard2regex(t *testing.T) { origin: "http://foo.example.com", want: 0, }, + { + name: "test8", + wildcard: "http://*", + origin: "http://foo.example.com", + want: 1, + }, + { + name: "test9", + wildcard: "http://*", + origin: "https://foo.example.com", + want: 0, + }, + { + name: "test10", + wildcard: "*", + origin: "http://foo.example.com", + want: 1, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { regexStr := wildcard2regex(tt.wildcard) regex, err := regexp.Compile(regexStr) - require.Nil(t, err) + require.NoError(t, err) finds := regex.FindAllString(tt.origin, -1) - assert.Equalf(t, tt.want, len(finds), "wildcard2regex(%v)", tt.wildcard) + assert.Lenf(t, finds, tt.want, "wildcard2regex(%v)", tt.wildcard) }) } } diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers.in.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers.in.yaml index babae4b3650..8bd4067f17b 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers.in.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers.in.yaml @@ -78,6 +78,7 @@ backendTrafficPolicies: maxConnections: 2048 maxPendingRequests: 1 maxParallelRequests: 4294967295 + maxRequestsPerConnection: 1 - apiVersion: gateway.envoyproxy.io/v1alpha1 kind: BackendTrafficPolicy metadata: @@ -93,3 +94,4 @@ backendTrafficPolicies: maxConnections: 42 maxPendingRequests: 42 maxParallelRequests: 42 + maxRequestsPerConnection: 42 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers.out.yaml index 4b17ac19de0..bcb293af7e3 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers.out.yaml @@ -10,6 +10,7 @@ backendTrafficPolicies: maxConnections: 42 maxParallelRequests: 42 maxPendingRequests: 42 + maxRequestsPerConnection: 42 targetRef: group: gateway.networking.k8s.io kind: HTTPRoute @@ -33,6 +34,7 @@ backendTrafficPolicies: maxConnections: 2048 maxParallelRequests: 4294967295 maxPendingRequests: 1 + maxRequestsPerConnection: 1 targetRef: group: gateway.networking.k8s.io kind: Gateway diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.in.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.in.yaml index 31a494a527d..e0b71ac1328 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.in.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.in.yaml @@ -113,20 +113,25 @@ backendTrafficPolicies: name: gateway-1 namespace: envoy-gateway healthCheck: - timeout: "500ms" - interval: "3s" - unhealthyThreshold: 3 - healthyThreshold: 1 - type: HTTP - http: - path: "/healthz" - method: "GET" - expectedStatuses: - - 200 - - 300 - expectedResponse: - type: Binary - binary: RXZlcnl0aGluZyBPSw== + active: + timeout: "500ms" + interval: "3s" + unhealthyThreshold: 3 + healthyThreshold: 1 + type: HTTP + http: + path: "/healthz" + method: "GET" + expectedStatuses: + - 200 + - 300 + expectedResponse: + type: Binary + binary: RXZlcnl0aGluZyBPSw== + passive: + baseEjectionTime: 160s + interval: 2s + maxEjectionPercent: 100 - apiVersion: gateway.envoyproxy.io/v1alpha1 kind: BackendTrafficPolicy metadata: @@ -139,20 +144,25 @@ backendTrafficPolicies: name: httproute-1 namespace: default healthCheck: - timeout: "1s" - interval: "5s" - unhealthyThreshold: 3 - healthyThreshold: 3 - type: HTTP - http: - path: "/healthz" - method: "GET" - expectedStatuses: - - 200 - - 201 - expectedResponse: - type: Text - text: pong + active: + timeout: "1s" + interval: "5s" + unhealthyThreshold: 3 + healthyThreshold: 3 + type: HTTP + http: + path: "/healthz" + method: "GET" + expectedStatuses: + - 200 + - 201 + expectedResponse: + type: Text + text: pong + passive: + baseEjectionTime: 150s + interval: 1s + maxEjectionPercent: 100 - apiVersion: gateway.envoyproxy.io/v1alpha1 kind: BackendTrafficPolicy metadata: @@ -165,18 +175,23 @@ backendTrafficPolicies: name: httproute-2 namespace: default healthCheck: - timeout: "1s" - interval: "5s" - unhealthyThreshold: 3 - healthyThreshold: 3 - type: TCP - tcp: - send: - type: Text - text: ping - receive: - type: Text - text: pong + active: + timeout: "1s" + interval: "5s" + unhealthyThreshold: 3 + healthyThreshold: 3 + type: TCP + tcp: + send: + type: Text + text: ping + receive: + type: Text + text: pong + passive: + baseEjectionTime: 180s + interval: 1s + maxEjectionPercent: 100 - apiVersion: gateway.envoyproxy.io/v1alpha1 kind: BackendTrafficPolicy metadata: @@ -189,15 +204,20 @@ backendTrafficPolicies: name: httproute-3 namespace: default healthCheck: - timeout: 1s - interval: 3s - unhealthyThreshold: 3 - healthyThreshold: 1 - type: TCP - tcp: - send: - type: Binary - binary: cGluZw== - receive: - type: Binary - binary: RXZlcnl0aGluZyBPSw== + active: + timeout: 1s + interval: 3s + unhealthyThreshold: 3 + healthyThreshold: 1 + type: TCP + tcp: + send: + type: Binary + binary: cGluZw== + receive: + type: Binary + binary: RXZlcnl0aGluZyBPSw== + passive: + baseEjectionTime: 160s + interval: 8ms + maxEjectionPercent: 11 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml index 361a5298381..c17d82f6c58 100755 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml @@ -7,20 +7,25 @@ backendTrafficPolicies: namespace: default spec: healthCheck: - healthyThreshold: 3 - http: - expectedResponse: - text: pong - type: Text - expectedStatuses: - - 200 - - 201 - method: GET - path: /healthz - interval: 5s - timeout: 1s - type: HTTP - unhealthyThreshold: 3 + active: + healthyThreshold: 3 + http: + expectedResponse: + text: pong + type: Text + expectedStatuses: + - 200 + - 201 + method: GET + path: /healthz + interval: 5s + timeout: 1s + type: HTTP + unhealthyThreshold: 3 + passive: + baseEjectionTime: 2m30s + interval: 1s + maxEjectionPercent: 100 targetRef: group: gateway.networking.k8s.io kind: HTTPRoute @@ -41,18 +46,23 @@ backendTrafficPolicies: namespace: default spec: healthCheck: - healthyThreshold: 3 - interval: 5s - tcp: - receive: - text: pong - type: Text - send: - text: ping - type: Text - timeout: 1s - type: TCP - unhealthyThreshold: 3 + active: + healthyThreshold: 3 + interval: 5s + tcp: + receive: + text: pong + type: Text + send: + text: ping + type: Text + timeout: 1s + type: TCP + unhealthyThreshold: 3 + passive: + baseEjectionTime: 3m0s + interval: 1s + maxEjectionPercent: 100 targetRef: group: gateway.networking.k8s.io kind: HTTPRoute @@ -73,18 +83,23 @@ backendTrafficPolicies: namespace: default spec: healthCheck: - healthyThreshold: 1 - interval: 3s - tcp: - receive: - binary: RXZlcnl0aGluZyBPSw== - type: Binary - send: - binary: cGluZw== - type: Binary - timeout: 1s - type: TCP - unhealthyThreshold: 3 + active: + healthyThreshold: 1 + interval: 3s + tcp: + receive: + binary: RXZlcnl0aGluZyBPSw== + type: Binary + send: + binary: cGluZw== + type: Binary + timeout: 1s + type: TCP + unhealthyThreshold: 3 + passive: + baseEjectionTime: 2m40s + interval: 8ms + maxEjectionPercent: 11 targetRef: group: gateway.networking.k8s.io kind: HTTPRoute @@ -105,20 +120,25 @@ backendTrafficPolicies: namespace: envoy-gateway spec: healthCheck: - healthyThreshold: 1 - http: - expectedResponse: - binary: RXZlcnl0aGluZyBPSw== - type: Binary - expectedStatuses: - - 200 - - 300 - method: GET - path: /healthz - interval: 3s - timeout: 500ms - type: HTTP - unhealthyThreshold: 3 + active: + healthyThreshold: 1 + http: + expectedResponse: + binary: RXZlcnl0aGluZyBPSw== + type: Binary + expectedStatuses: + - 200 + - 300 + method: GET + path: /healthz + interval: 3s + timeout: 500ms + type: HTTP + unhealthyThreshold: 3 + passive: + baseEjectionTime: 2m40s + interval: 2s + maxEjectionPercent: 100 targetRef: group: gateway.networking.k8s.io kind: Gateway @@ -421,18 +441,23 @@ xdsIR: protocol: GRPC weight: 1 healthCheck: - healthyThreshold: 1 - http: - expectedResponse: - binary: RXZlcnl0aGluZyBPSw== - expectedStatuses: - - 200 - - 300 - method: GET - path: /healthz - interval: 3s - timeout: 500ms - unhealthyThreshold: 3 + active: + healthyThreshold: 1 + http: + expectedResponse: + binary: RXZlcnl0aGluZyBPSw== + expectedStatuses: + - 200 + - 300 + method: GET + path: /healthz + interval: 3s + timeout: 500ms + unhealthyThreshold: 3 + passive: + baseEjectionTime: 2m40s + interval: 2s + maxEjectionPercent: 100 hostname: '*' name: grpcroute/default/grpcroute-1/rule/0/match/-1/* envoy-gateway/gateway-2: @@ -463,15 +488,20 @@ xdsIR: protocol: HTTP weight: 1 healthCheck: - healthyThreshold: 3 - interval: 5s - tcp: - receive: - text: pong - send: - text: ping - timeout: 1s - unhealthyThreshold: 3 + active: + healthyThreshold: 3 + interval: 5s + tcp: + receive: + text: pong + send: + text: ping + timeout: 1s + unhealthyThreshold: 3 + passive: + baseEjectionTime: 3m0s + interval: 1s + maxEjectionPercent: 100 hostname: gateway.envoyproxy.io name: httproute/default/httproute-2/rule/0/match/0/gateway_envoyproxy_io pathMatch: @@ -491,15 +521,20 @@ xdsIR: protocol: HTTP weight: 1 healthCheck: - healthyThreshold: 1 - interval: 3s - tcp: - receive: - binary: RXZlcnl0aGluZyBPSw== - send: - binary: cGluZw== - timeout: 1s - unhealthyThreshold: 3 + active: + healthyThreshold: 1 + interval: 3s + tcp: + receive: + binary: RXZlcnl0aGluZyBPSw== + send: + binary: cGluZw== + timeout: 1s + unhealthyThreshold: 3 + passive: + baseEjectionTime: 2m40s + interval: 8ms + maxEjectionPercent: 11 hostname: gateway.envoyproxy.io name: httproute/default/httproute-3/rule/0/match/0/gateway_envoyproxy_io pathMatch: @@ -519,18 +554,23 @@ xdsIR: protocol: HTTP weight: 1 healthCheck: - healthyThreshold: 3 - http: - expectedResponse: - text: pong - expectedStatuses: - - 200 - - 201 - method: GET - path: /healthz - interval: 5s - timeout: 1s - unhealthyThreshold: 3 + active: + healthyThreshold: 3 + http: + expectedResponse: + text: pong + expectedStatuses: + - 200 + - 201 + method: GET + path: /healthz + interval: 5s + timeout: 1s + unhealthyThreshold: 3 + passive: + baseEjectionTime: 2m30s + interval: 1s + maxEjectionPercent: 100 hostname: gateway.envoyproxy.io name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcpkeepalive.in.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcpkeepalive.in.yaml new file mode 100644 index 00000000000..df14e30971b --- /dev/null +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcpkeepalive.in.yaml @@ -0,0 +1,95 @@ +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 +grpcRoutes: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: GRPCRoute + metadata: + namespace: default + name: grpcroute-1 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 +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-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-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + tcpKeepalive: + probes: 3 + idleTime: 20m + interval: 60s +- 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 + namespace: default + tcpKeepalive: + probes: 6 + idleTime: 10s + interval: 30m diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcpkeepalive.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcpkeepalive.out.yaml new file mode 100644 index 00000000000..3f9bbb33a3e --- /dev/null +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcpkeepalive.out.yaml @@ -0,0 +1,303 @@ +backendTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + creationTimestamp: null + name: policy-for-route + namespace: default + spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + namespace: default + tcpKeepalive: + idleTime: 10s + interval: 30m + probes: 6 + status: + conditions: + - lastTransitionTime: null + message: BackendTrafficPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + creationTimestamp: null + name: policy-for-gateway + namespace: envoy-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + tcpKeepalive: + idleTime: 20m + interval: 60s + probes: 3 + status: + conditions: + - lastTransitionTime: null + message: BackendTrafficPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +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 +grpcRoutes: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: GRPCRoute + metadata: + creationTimestamp: null + name: grpcroute-1 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + 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 +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-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-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 + 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 + envoy-gateway/gateway-2: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-2/http + ports: + - containerPort: 10080 + name: http + 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 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: true + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: grpcroute/default/grpcroute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: GRPC + weight: 1 + hostname: '*' + name: grpcroute/default/grpcroute-1/rule/0/match/-1/* + tcpKeepalive: + idleTime: 1200 + interval: 60 + probes: 3 + envoy-gateway/gateway-2: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-2/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: gateway.envoyproxy.io + name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: / + tcpKeepalive: + idleTime: 10 + interval: 1800 + probes: 6 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout-error.in.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout-error.in.yaml new file mode 100644 index 00000000000..8025e82f1d8 --- /dev/null +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout-error.in.yaml @@ -0,0 +1,49 @@ +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 +grpcRoutes: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: GRPCRoute + metadata: + namespace: default + name: grpcroute-1 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 +backendTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + namespace: envoy-gateway + name: policy-for-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + timeout: + http: + connectionIdleTimeout: 21s + maxConnectionDuration: 22mib + tcp: + connectTimeout: 20s + diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout-error.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout-error.out.yaml new file mode 100755 index 00000000000..6feff83ca6b --- /dev/null +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout-error.out.yaml @@ -0,0 +1,148 @@ +backendTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + creationTimestamp: null + name: policy-for-gateway + namespace: envoy-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + timeout: + http: + connectionIdleTimeout: 21s + maxConnectionDuration: 22mib + tcp: + connectTimeout: 20s + status: + conditions: + - lastTransitionTime: null + message: 'Unable to translate HTTP Timeout: invalid MaxConnectionDuration value + 22mib' + reason: Invalid + status: "False" + type: Accepted +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 +grpcRoutes: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: GRPCRoute + metadata: + creationTimestamp: null + name: grpcroute-1 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + 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 +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-1/http + ports: + - containerPort: 10080 + name: http + 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 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: true + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: grpcroute/default/grpcroute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: GRPC + weight: 1 + hostname: '*' + name: grpcroute/default/grpcroute-1/rule/0/match/-1/* diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout.in.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout.in.yaml new file mode 100644 index 00000000000..c73a4504d4c --- /dev/null +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout.in.yaml @@ -0,0 +1,99 @@ +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 +grpcRoutes: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: GRPCRoute + metadata: + namespace: default + name: grpcroute-1 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 +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-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-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + timeout: + tcp: + connectTimeout: 15s + http: + connectionIdleTimeout: 16s + maxConnectionDuration: 17s +- 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 + namespace: default + timeout: + tcp: + connectTimeout: 20s + http: + connectionIdleTimeout: 21s + maxConnectionDuration: 22s diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout.out.yaml new file mode 100755 index 00000000000..9c5fe2dca53 --- /dev/null +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout.out.yaml @@ -0,0 +1,311 @@ +backendTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + creationTimestamp: null + name: policy-for-route + namespace: default + spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + namespace: default + timeout: + http: + connectionIdleTimeout: 21s + maxConnectionDuration: 22s + tcp: + connectTimeout: 20s + status: + conditions: + - lastTransitionTime: null + message: BackendTrafficPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + creationTimestamp: null + name: policy-for-gateway + namespace: envoy-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + timeout: + http: + connectionIdleTimeout: 16s + maxConnectionDuration: 17s + tcp: + connectTimeout: 15s + status: + conditions: + - lastTransitionTime: null + message: BackendTrafficPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +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 +grpcRoutes: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: GRPCRoute + metadata: + creationTimestamp: null + name: grpcroute-1 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + 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 +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-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-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 + 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 + envoy-gateway/gateway-2: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-2/http + ports: + - containerPort: 10080 + name: http + 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 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: true + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: grpcroute/default/grpcroute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: GRPC + weight: 1 + hostname: '*' + name: grpcroute/default/grpcroute-1/rule/0/match/-1/* + timeout: + http: + connectionIdleTimeout: 16s + maxConnectionDuration: 17s + tcp: + connectTimeout: 15s + envoy-gateway/gateway-2: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-2/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: gateway.envoyproxy.io + name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: / + timeout: + http: + connectionIdleTimeout: 21s + maxConnectionDuration: 22s + tcp: + connectTimeout: 20s diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-client-ip-detection.in.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-client-ip-detection.in.yaml new file mode 100644 index 00000000000..11204555a03 --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-client-ip-detection.in.yaml @@ -0,0 +1,82 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-1-http-1 + spec: + clientIPDetection: + xForwardedFor: + numTrustedHops: 2 + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http-1 +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-1-http-2 + spec: + clientIPDetection: + customHeader: + name: "x-client-ip-address" + failClosed: false + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http-2 +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-1-http-3 + spec: + clientIPDetection: + customHeader: + name: "x-client-ip-address" + failClosed: true + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http-3 +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http-1 + protocol: HTTP + port: 8081 + allowedRoutes: + namespaces: + from: Same + - name: http-2 + protocol: HTTP + port: 8082 + allowedRoutes: + namespaces: + from: Same + - name: http-3 + protocol: HTTP + port: 8083 + allowedRoutes: + namespaces: + from: Same + - name: http-4 + protocol: HTTP + port: 8084 + allowedRoutes: + namespaces: + from: Same + diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-client-ip-detection.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-client-ip-detection.out.yaml new file mode 100644 index 00000000000..66978bcc4ef --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-client-ip-detection.out.yaml @@ -0,0 +1,290 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-1-http-1 + namespace: envoy-gateway + spec: + clientIPDetection: + xForwardedFor: + numTrustedHops: 2 + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http-1 + status: + conditions: + - lastTransitionTime: null + message: ClientTrafficPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-1-http-2 + namespace: envoy-gateway + spec: + clientIPDetection: + customHeader: + failClosed: false + name: x-client-ip-address + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http-2 + status: + conditions: + - lastTransitionTime: null + message: ClientTrafficPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-1-http-3 + namespace: envoy-gateway + spec: + clientIPDetection: + customHeader: + failClosed: true + name: x-client-ip-address + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http-3 + status: + conditions: + - lastTransitionTime: null + message: ClientTrafficPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +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: Same + name: http-1 + port: 8081 + protocol: HTTP + - allowedRoutes: + namespaces: + from: Same + name: http-2 + port: 8082 + protocol: HTTP + - allowedRoutes: + namespaces: + from: Same + name: http-3 + port: 8083 + protocol: HTTP + - allowedRoutes: + namespaces: + from: Same + name: http-4 + port: 8084 + protocol: HTTP + 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 + name: http-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: http-2 + 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: http-3 + 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: http-4 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-1/http-1 + ports: + - containerPort: 8081 + name: http-1 + protocol: HTTP + servicePort: 8081 + - address: null + name: envoy-gateway/gateway-1/http-2 + ports: + - containerPort: 8082 + name: http-2 + protocol: HTTP + servicePort: 8082 + - address: null + name: envoy-gateway/gateway-1/http-3 + ports: + - containerPort: 8083 + name: http-3 + protocol: HTTP + servicePort: 8083 + - address: null + name: envoy-gateway/gateway-1/http-4 + ports: + - containerPort: 8084 + name: http-4 + protocol: HTTP + servicePort: 8084 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-1 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + clientIPDetection: + xForwardedFor: + numTrustedHops: 2 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 8081 + - address: 0.0.0.0 + clientIPDetection: + customHeader: + failClosed: false + name: x-client-ip-address + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http-2 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 8082 + - address: 0.0.0.0 + clientIPDetection: + customHeader: + failClosed: true + name: x-client-ip-address + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http-3 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 8083 + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http-4 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 8084 diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-suppress-envoy-headers.in.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-headers.in.yaml similarity index 87% rename from internal/gatewayapi/testdata/clienttrafficpolicy-suppress-envoy-headers.in.yaml rename to internal/gatewayapi/testdata/clienttrafficpolicy-headers.in.yaml index dead8c186b9..82a60c2c033 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-suppress-envoy-headers.in.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-headers.in.yaml @@ -3,14 +3,14 @@ clientTrafficPolicies: kind: ClientTrafficPolicy metadata: namespace: envoy-gateway - name: target-gateway-1-section-http-1 + name: target-gateway-1 spec: - suppressEnvoyHeaders: true + headers: + enableEnvoyHeaders: true targetRef: group: gateway.networking.k8s.io kind: Gateway name: gateway-1 - sectionName: http-1 namespace: envoy-gateway gateways: - apiVersion: gateway.networking.k8s.io/v1 diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-headers.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-headers.out.yaml new file mode 100644 index 00000000000..debec3ba699 --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-headers.out.yaml @@ -0,0 +1,143 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-1 + namespace: envoy-gateway + spec: + headers: + enableEnvoyHeaders: true + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + status: + conditions: + - lastTransitionTime: null + message: ClientTrafficPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +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: Same + name: http-1 + port: 80 + protocol: HTTP + - allowedRoutes: + namespaces: + from: Same + name: http-2 + port: 8080 + protocol: HTTP + 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 + name: http-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: http-2 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-1/http-1 + ports: + - containerPort: 10080 + name: http-1 + protocol: HTTP + servicePort: 80 + - address: null + name: envoy-gateway/gateway-1/http-2 + ports: + - containerPort: 8080 + name: http-2 + protocol: HTTP + servicePort: 8080 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-1 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + headers: + enableEnvoyHeaders: true + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + - address: 0.0.0.0 + headers: + enableEnvoyHeaders: true + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http-2 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 8080 diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-http10.in.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-http10.in.yaml new file mode 100644 index 00000000000..8d54877593d --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-http10.in.yaml @@ -0,0 +1,73 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-1-section-http-1 + spec: + http1: + http10: {} + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + sectionName: http-1 + namespace: envoy-gateway +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-1-section-http-2 + spec: + http1: + http10: + useDefaultHost: true + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + sectionName: http-2 + namespace: envoy-gateway +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-1-section-http-3 + spec: + http1: + http10: + useDefaultHost: true + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + sectionName: http-3 + namespace: envoy-gateway +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http-1 + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: Same + - name: http-2 + protocol: HTTP + hostname: www.example.com + port: 8080 + allowedRoutes: + namespaces: + from: Same + - name: http-3 + protocol: HTTP + port: 8081 + allowedRoutes: + namespaces: + from: Same diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-http10.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-http10.out.yaml new file mode 100644 index 00000000000..07640e3a50e --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-http10.out.yaml @@ -0,0 +1,238 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-1-section-http-1 + namespace: envoy-gateway + spec: + http1: + http10: {} + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http-1 + status: + conditions: + - lastTransitionTime: null + message: ClientTrafficPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-1-section-http-2 + namespace: envoy-gateway + spec: + http1: + http10: + useDefaultHost: true + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http-2 + status: + conditions: + - lastTransitionTime: null + message: ClientTrafficPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-1-section-http-3 + namespace: envoy-gateway + spec: + http1: + http10: + useDefaultHost: true + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http-3 + status: + conditions: + - lastTransitionTime: null + message: Can't set http10 default host on listener with only wildcard hostnames + reason: Invalid + status: "False" + type: Accepted +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: Same + name: http-1 + port: 80 + protocol: HTTP + - allowedRoutes: + namespaces: + from: Same + hostname: www.example.com + name: http-2 + port: 8080 + protocol: HTTP + - allowedRoutes: + namespaces: + from: Same + name: http-3 + port: 8081 + protocol: HTTP + 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 + name: http-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: http-2 + 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: http-3 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-1/http-1 + ports: + - containerPort: 10080 + name: http-1 + protocol: HTTP + servicePort: 80 + - address: null + name: envoy-gateway/gateway-1/http-2 + ports: + - containerPort: 8080 + name: http-2 + protocol: HTTP + servicePort: 8080 + - address: null + name: envoy-gateway/gateway-1/http-3 + ports: + - containerPort: 8081 + name: http-3 + protocol: HTTP + servicePort: 8081 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-1 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + http1: + http10: {} + isHTTP2: false + name: envoy-gateway/gateway-1/http-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + - address: 0.0.0.0 + hostnames: + - www.example.com + http1: + http10: + defaultHost: www.example.com + isHTTP2: false + name: envoy-gateway/gateway-1/http-2 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 8080 + - address: 0.0.0.0 + hostnames: + - '*' + http1: {} + isHTTP2: false + name: envoy-gateway/gateway-1/http-3 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 8081 diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-http3.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-http3.out.yaml index 49ba2bb9f81..1ffbde52972 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-http3.out.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-http3.out.yaml @@ -157,7 +157,7 @@ xdsIR: alpnProtocols: - h3 certificates: - - name: envoy-gateway-tls-secret-1 + - name: envoy-gateway/tls-secret-1 privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2QwZlBDYWtweE1nUnUKT0VXQjFiQk5FM3ZseW55aTZWbkV2VWF1OUhvakR2UHVPTFJIaGI4MmoyY1ovMHhnL1lKR09LelBuV2JERkxGNApHdWh3dDRENmFUR0xYNklPODEwTDZ0SXZIWGZNUXRJS2VwdTZ3K3p1WVo4bG1yejB1RjZlWEtqamVIbHhyb2ZrCnVNekM3OUVaU0lYZlZlczJ1SmdVRSs4VGFzSDUzQ2Y4MFNSRGlIeEdxckttdVNjWCtwejBreGdCZ1VWYTVVS20KUWdTZDFmVUxLOUEwNXAxOXkrdURPM204bVhRNkxVQ0N1STFwZHNROGFlNS9zamlxa0VjWlJjMTdWYVgxWjVVaQpvcGZnNW9SY05VTG9VTHNiek9aNTR0YlVDUmdSV2VLbGZxaElINEZ6OUlkVlUyR3dFdEdhMmV6TjgyMVBaQ3QzCjZhbVRIelJsQWdNQkFBRUNnZ0VBWTFGTUlLNDVXTkVNUHJ6RTZUY3NNdVV2RkdhQVZ4bVk5NW5SMEtwajdvb3IKY21CVys2ZXN0TTQ4S1AwaitPbXd3VFpMY29Cd3VoWGN0V1Bob1lXcDhteWUxRUlEdjNyaHRHMDdocEQ1NGg2dgpCZzh3ejdFYStzMk9sT0N6UnlKNzBSY281YlhjWDNGaGJjdnFlRWJwaFFyQnpOSEtLMjZ4cmZqNWZIT3p6T1FGCmJHdUZ3SDVic3JGdFhlajJXM3c4eW90N0ZQSDV3S3RpdnhvSWU5RjMyOXNnOU9EQnZqWnpiaG1LVTArckFTK1kKRGVield2bFJyaEUrbXVmQTN6M0N0QXhDOFJpNzNscFNoTDRQQWlvcG1SUXlxZXRXMjYzOFFxcnM0R3hnNzhwbApJUXJXTmNBc2s3Slg5d3RZenV6UFBXSXRWTTFscFJiQVRhNTJqdFl2NVFLQmdRRE5tMTFtZTRYam1ZSFV2cStZCmFTUzdwK2UybXZEMHVaOU9JeFluQnBWMGkrckNlYnFFMkE1Rm5hcDQ5Yld4QTgwUElldlVkeUpCL2pUUkoxcVMKRUpXQkpMWm1LVkg2K1QwdWw1ZUtOcWxFTFZHU0dCSXNpeE9SUXpDZHBoMkx0UmtBMHVjSVUzY3hiUmVMZkZCRQpiSkdZWENCdlNGcWd0VDlvZTFldVpMVmFOd0tCZ1FERWdENzJENk81eGIweEQ1NDQ1M0RPMUJhZmd6aThCWDRTCk1SaVd2LzFUQ0w5N05sRWtoeXovNmtQd1owbXJRcE5CMzZFdkpKZFVteHdkU2MyWDhrOGcxMC85NVlLQkdWQWoKL3d0YVZYbE9WeEFvK0ZSelpZeFpyQ29uWWFSMHVwUzFybDRtenN4REhlZU9mUVZUTUgwUjdZN0pnbTA5dXQ4SwplanAvSXZBb1F3S0JnQjNaRWlRUWhvMVYrWjBTMlpiOG5KS0plMy9zMmxJTXFHM0ZkaS9RS3Q0eWViQWx6OGY5ClBZVXBzRmZEQTg5Z3grSU1nSm5sZVptdTk2ZnRXSjZmdmJSenllN216TG5zZU05TXZua1lHbGFGWmJRWnZubXMKN3ZoRmtzY3dHRlh4d21GMlBJZmU1Z3pNMDRBeVdjeTFIaVhLS2dNOXM3cGsxWUdyZGowZzdacmRBb0dCQUtLNApDR3MrbkRmMEZTMFJYOWFEWVJrRTdBNy9YUFhtSG5YMkRnU1h5N0Q4NTRPaWdTTWNoUmtPNTErbVNJejNQbllvCk41T1FXM2lHVVl1M1YvYmhnc0VSUzM1V2xmRk9BdDBzRUR5bjF5SVdXcDF5dG93d3BUNkVvUXVuZ2NYZjA5RjMKS1NROXowd3M4VmsvRWkvSFVXcU5LOWFXbU51cmFaT0ZqL2REK1ZkOUFvR0FMWFN3dEE3K043RDRkN0VEMURSRQpHTWdZNVd3OHFvdDZSdUNlNkpUY0FnU3B1MkhNU3JVY2dXclpiQnJZb09FUnVNQjFoMVJydk5ybU1qQlM0VW9FClgyZC8vbGhpOG1wL2VESWN3UDNRa2puanBJRFJWMFN1eWxrUkVaZURKZjVZb3R6eDdFdkJhbzFIbkQrWEg4eUIKVUtmWGJTaHZKVUdhRmgxT3Q1Y3JoM1k9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNxRENDQVpBQ0NRREVNZ1lZblFyQ29EQU5CZ2txaGtpRzl3MEJBUXNGQURBV01SUXdFZ1lEVlFRRERBdG0KYjI4dVltRnlMbU52YlRBZUZ3MHlNekF4TURVeE16UXpNalJhRncweU5EQXhNRFV4TXpRek1qUmFNQll4RkRBUwpCZ05WQkFNTUMyWnZieTVpWVhJdVkyOXRNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDCkFRRUFuZEh6d21wS2NUSUViamhGZ2RXd1RSTjc1Y3A4b3VsWnhMMUdydlI2SXc3ejdqaTBSNFcvTm85bkdmOU0KWVAyQ1JqaXN6NTFtd3hTeGVCcm9jTGVBK21reGkxK2lEdk5kQytyU0x4MTN6RUxTQ25xYnVzUHM3bUdmSlpxOAo5TGhlbmx5bzQzaDVjYTZINUxqTXd1L1JHVWlGMzFYck5yaVlGQlB2RTJyQitkd24vTkVrUTRoOFJxcXlwcmtuCkYvcWM5Sk1ZQVlGRld1VkNwa0lFbmRYMUN5dlFOT2FkZmN2cmd6dDV2SmwwT2kxQWdyaU5hWGJFUEdudWY3STQKcXBCSEdVWE5lMVdsOVdlVklxS1g0T2FFWERWQzZGQzdHOHptZWVMVzFBa1lFVm5pcFg2b1NCK0JjL1NIVlZOaApzQkxSbXRuc3pmTnRUMlFyZCttcGt4ODBaUUlEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ1VKOElDCkJveUVqT3V3enBHYVJoR044QjRqT1B6aHVDT0V0ZDM3UzAybHUwN09IenlCdmJzVEd6S3dCZ0x5bVdmR2tINEIKajdDTHNwOEZ6TkhLWnVhQmdwblo5SjZETE9Od2ZXZTJBWXA3TGRmT0tWQlVkTVhRaU9tN2pKOUhob0Ntdk1ONwpic2pjaFdKb013ckZmK3dkQUthdHowcUFQeWhMeWUvRnFtaVZ4a09SWmF3K1Q5bURaK0g0OXVBU2d1SnVOTXlRClY2RXlYNmd0Z1dxMzc2SHZhWE1TLzNoYW1Zb1ZXWEk1TXhpUE9ZeG5BQmtKQjRTQ2dJUmVqYkpmVmFRdG9RNGEKejAyaVVMZW5ESUllUU9Zb2JLY01CWGYxQjRQQVFtc2VocVZJYnpzUUNHaTU0VkRyczZiWmQvN0pzMXpDcHBncwpKaUQ1SXFNaktXRHdxN2FLCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K maxVersion: "1.3" diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-mtls.in.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-mtls.in.yaml new file mode 100644 index 00000000000..05ff5b87294 --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-mtls.in.yaml @@ -0,0 +1,118 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-1 + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + tls: + clientValidation: + caCertificateRefs: + - name: tls-secret-1 + namespace: envoy-gateway +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-2 + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-2 + namespace: envoy-gateway + tls: + clientValidation: + caCertificateRefs: + - kind: ConfigMap + name: ca-configmap + namespace: envoy-gateway +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http-1 + protocol: HTTPS + port: 443 + allowedRoutes: + namespaces: + from: Same + tls: + mode: Terminate + certificateRefs: + - name: tls-secret-1 + namespace: envoy-gateway + - name: http-2 + protocol: HTTP + port: 8080 + allowedRoutes: + namespaces: + from: Same +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-2 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http-1 + protocol: HTTPS + port: 443 + allowedRoutes: + namespaces: + from: Same + tls: + mode: Terminate + certificateRefs: + - name: tls-secret-1 + namespace: envoy-gateway +configMaps: +- apiVersion: v1 + kind: ConfigMap + metadata: + name: ca-configmap + namespace: envoy-gateway + data: + ca.crt: | + -----BEGIN CERTIFICATE----- + MIIDOzCCAiOgAwIBAgIUc41kpE9wK+NHgRGvBIgw8SCaz/8wDQYJKoZIhvcNAQEL + BQAwLTEVMBMGA1UECgwMZXhhbXBsZSBJbmMuMRQwEgYDVQQDDAtleGFtcGxlLmNv + bTAeFw0yNDAxMjYyMzE1MzFaFw0yNTAxMjUyMzE1MzFaMC0xFTATBgNVBAoMDGV4 + YW1wbGUgSW5jLjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEB + AQUAA4IBDwAwggEKAoIBAQDCLhZ5DnCVE5JJ97yOocpRwclbl0UwX3cI+1ZZNltl + W6jRgy1GuN6Vr7CBmI/mPtgGs9T7DNRMl5gJJkNHSZomI6GjuP1KUhuvlfbZPWNo + p45T235Z82Gg8ORJHT5mn1QRK+bz9ruJfyldMMlicUJv/Yft6zNURxQ7BU9ciGe1 + tM+UMSxkop3dovVptELnkTDJSwt5dn+nj6j/Gr95z90/e2gjfVTtmArAG3xh/2B1 + /D6NXhwPMzYrplnM3lOpxzflOVgjMUloL1oI7sm6c+2A14NeBrW/ofB9RD7DWBHd + 76j+hcAWFsxYmsHo5Ox/tFeTk7GRdkHEELLWFBvYG0BTAgMBAAGjUzBRMB0GA1Ud + DgQWBBSrLbcQPpEx+Dt+hYE/yrjt6rOV6TAfBgNVHSMEGDAWgBSrLbcQPpEx+Dt+ + hYE/yrjt6rOV6TAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCF + 4jltqxVaKZaVML7HNQSwegy+gZ1xalymMNo7Ipc8zOyUUI47weEf/p+nkq8oxi/m + mLZoeMSdXg+gebYMMcURgtl9QfuF0aYCB3AlCxlpdH4Lk3uXNTLQXJiLQRTNsBu/ + LJ6UYvLFKPwodvRKL8KWKEgLVJmrTe3g8iL3SSnw00hWieuCdSsxNl/47ThgYXrg + u1PRBUt5g+XoWpUSOCMOFWlBJqwJYKfRA3E6ff44IUJsb7qUHHAe1wa1YDfuD+T5 + At9/m+M7GyW9oEbSQsPTGfYqP59QE+1iei6qiG+7kn4iRxJqhgm5N5o86QSk0Maz + Cz4jTEKdNvXYVFfh6Zqr + -----END CERTIFICATE----- +secrets: +- apiVersion: v1 + kind: Secret + metadata: + namespace: envoy-gateway + name: tls-secret-1 + type: kubernetes.io/tls + data: + ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURPekNDQWlPZ0F3SUJBZ0lVYzQxa3BFOXdLK05IZ1JHdkJJZ3c4U0Nhei84d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeE1qVXlNekUxTXpGYU1DMHhGVEFUQmdOVkJBb01ER1Y0CllXMXdiR1VnU1c1akxqRVVNQklHQTFVRUF3d0xaWGhoYlhCc1pTNWpiMjB3Z2dFaU1BMEdDU3FHU0liM0RRRUIKQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURDTGhaNURuQ1ZFNUpKOTd5T29jcFJ3Y2xibDBVd1gzY0krMVpaTmx0bApXNmpSZ3kxR3VONlZyN0NCbUkvbVB0Z0dzOVQ3RE5STWw1Z0pKa05IU1pvbUk2R2p1UDFLVWh1dmxmYlpQV05vCnA0NVQyMzVaODJHZzhPUkpIVDVtbjFRUksrYno5cnVKZnlsZE1NbGljVUp2L1lmdDZ6TlVSeFE3QlU5Y2lHZTEKdE0rVU1TeGtvcDNkb3ZWcHRFTG5rVERKU3d0NWRuK25qNmovR3I5NXo5MC9lMmdqZlZUdG1BckFHM3hoLzJCMQovRDZOWGh3UE16WXJwbG5NM2xPcHh6ZmxPVmdqTVVsb0wxb0k3c202YysyQTE0TmVCclcvb2ZCOVJEN0RXQkhkCjc2aitoY0FXRnN4WW1zSG81T3gvdEZlVGs3R1Jka0hFRUxMV0ZCdllHMEJUQWdNQkFBR2pVekJSTUIwR0ExVWQKRGdRV0JCU3JMYmNRUHBFeCtEdCtoWUUveXJqdDZyT1Y2VEFmQmdOVkhTTUVHREFXZ0JTckxiY1FQcEV4K0R0KwpoWUUveXJqdDZyT1Y2VEFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUNGCjRqbHRxeFZhS1phVk1MN0hOUVN3ZWd5K2daMXhhbHltTU5vN0lwYzh6T3lVVUk0N3dlRWYvcCtua3E4b3hpL20KbUxab2VNU2RYZytnZWJZTU1jVVJndGw5UWZ1RjBhWUNCM0FsQ3hscGRINExrM3VYTlRMUVhKaUxRUlROc0J1LwpMSjZVWXZMRktQd29kdlJLTDhLV0tFZ0xWSm1yVGUzZzhpTDNTU253MDBoV2lldUNkU3N4TmwvNDdUaGdZWHJnCnUxUFJCVXQ1ZytYb1dwVVNPQ01PRldsQkpxd0pZS2ZSQTNFNmZmNDRJVUpzYjdxVUhIQWUxd2ExWURmdUQrVDUKQXQ5L20rTTdHeVc5b0ViU1FzUFRHZllxUDU5UUUrMWllaTZxaUcrN2tuNGlSeEpxaGdtNU41bzg2UVNrME1hegpDejRqVEVLZE52WFlWRmZoNlpxcgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM0RENDQWNnQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeApNalV5TXpFMU16RmFNRDh4R1RBWEJnTlZCQU1NRUdWa1oyVXVaWGhoYlhCc1pTNWpiMjB4SWpBZ0JnTlZCQW9NCkdXVmtaMlVnWlhoaGJYQnNaU0J2Y21kaGJtbDZZWFJwYjI0d2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUIKRHdBd2dnRUtBb0lCQVFDNzdodkFQQWVGUm5xL3RwR1ZkSk5lY2Fhaks2a1F5Q2pZNXIvcFh4TkJhOXZXVlFIVQpuQ1dWT3lscEVkaDZPZlltR2dvSmF0TVRUWUFYK1ZpdkxTOVhwSDhuUENZYVpvQmRpMlA0MWRrbmsyUnpGWm1sCi9YUjVIWnREWmplRE8zd3ZCSm9ubStNeFA3Qms1TGdlOWhGSFJ3akViTGNZN3crN3pxOEJEQXlJSHY3T0ozYTcKeDkvalgyUlpGdTdPNXI1eWZFUTZGc0tjelREb29DeGRVa05JZ3RwVkNvRExLdmJMNjFuZE51bGUzL21EbS92MgpTeVRIdWQxUzVkcXNwOGtKZHU4WFVSZmMyWUVsRktXdkJ0bmpoL2pyTE1YRmNhaFYvb3hKckNIdXQvUENMYkJUCkFqVGV1U0RhdVM3T0hiSlJES3dtSDdvVnZ5SUNhSXlhWWNaTkFnTUJBQUV3RFFZSktvWklodmNOQVFFTEJRQUQKZ2dFQkFHeW5yNGNPMWFZbjRNQk90aVJ2WHFJdllHNnpxZXNrNGpQbU96TjdiUTdyRzdNUngzSVQ2SW4zVFI4RApHbFAxVE54TTg5cXZRcXp4VERsdER3bXluTlV1SEdEUW4yV1Z1OFEyK0RqRnFoc3B1WHp0NnhVK2RoVVBxUnV1Ckt6c1l4TDNpMVlWZ2pDQWtBUmp4SGhMWHYwdkFUWUVRMlJ6Uko5c2ZGcWVCMHVxSk5WL0lHamJFSzQ2eTQ5QU0KNzU4TUY4T0R6cVR2Q3hMRjJYd3BScjdjSDFuZ2J4eUJ6cEdlbkpsVTI2Q2hJT1BMZUV1NTUyUVJYVGwrU2JlQQpXUzNpS01Pb3F5NGV0b0ExNWFueW43Zm01YnpINEcyZ3Yxd1pWYlBkT1dNQWRZU2I5NDIvR09CSWUzSnIyVHo3CjRJdDRROWFERnF1aG9iOTVQMUhHQkxSQ2Y5QT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQzc3aHZBUEFlRlJucS8KdHBHVmRKTmVjYWFqSzZrUXlDalk1ci9wWHhOQmE5dldWUUhVbkNXVk95bHBFZGg2T2ZZbUdnb0phdE1UVFlBWAorVml2TFM5WHBIOG5QQ1lhWm9CZGkyUDQxZGtuazJSekZabWwvWFI1SFp0RFpqZURPM3d2Qkpvbm0rTXhQN0JrCjVMZ2U5aEZIUndqRWJMY1k3dys3enE4QkRBeUlIdjdPSjNhN3g5L2pYMlJaRnU3TzVyNXlmRVE2RnNLY3pURG8Kb0N4ZFVrTklndHBWQ29ETEt2Ykw2MW5kTnVsZTMvbURtL3YyU3lUSHVkMVM1ZHFzcDhrSmR1OFhVUmZjMllFbApGS1d2QnRuamgvanJMTVhGY2FoVi9veEpyQ0h1dC9QQ0xiQlRBalRldVNEYXVTN09IYkpSREt3bUg3b1Z2eUlDCmFJeWFZY1pOQWdNQkFBRUNnZ0VBSG1McVd4NHZCbk9ybHFLMGVNLzM5c1lLOEVpTTlra0c5eHRJWGVSTGxCWnIKM2dTeUNSTStXRzk2ZGZkaFkxSDFPa1ZDUGpJOFNEQzRkMzA2Ymw0Ris2RW93TXFrUytjcTlrcDYzYTg3aE5TbQpOMGdxSnl3TGV5YzRXdll2ZFA2c25scnd6MXE3Vk5QbXpQUXJ6b1hIQVc2N2tpeHA1cFF3OG1oVzVQcHlidkp5Clo2TERCZGRSZkVma2ZXVnZUUk5YWUVDUEllUStST05jR3JvVzZ5RXRrbk1BWUJjdjRlNUhCQkkrcHdyYmsrOVMKY2FQYUVjdm4vS0lyT3NpVW1FT2wwb3JXVnhkbjRmMy9MNmlFZFgyZHhIdXlwYkFiL0Qwak1MSzBwb3kyaXYyTApyOGI5VUQrRVZFNmFTVnp0MFRHbVpJYUdRVVZDQnVDTDhodlYwSU9PV1FLQmdRRGplL3JXdmk4Rndia3BRNDA0CnFQcitBaEFwaG1pV3l1a1B1VmJLN2Q5ZkdURzRHOW9Bd2wzYlFoRGVUNHhjMzd0cjlkcCtpamJuWnpKWHczL1cKcm5xTDlGWkZsVXZCYXN6c05VK1lRNmJVOE9zTXl6cURSdGJaaytVWEowUEx6QzZKWHFkNTFZdVVDM3NwL2lmNwpqWEZrME55aHcrdkY3VU51N0ZFSzVuWEUwd0tCZ1FEVGZOT0RLYmZyalNkZEhkV05iOHhkN2pGMlZSY3hTTnRUCit0L0FmbkRjZG8zK1NBUnJaRi9TM0hZWUxxL0l4dmZ5ZHdIblUxdC9INkxDZjBnQ2RXS2NXL1hway93ZUo1QXYKWmdaZjBPTXZsOXF0THJhTU44OG1HblV4K2IxdHZLWm4xQVcySFNuYXd2Z0kvMWVjSldNRUJiYkREbkx4cUpMegowTHJhT2pYVVh3S0JnRGlBbE44OXdjUTJSOTFkNy9mQTBRYkNVRzFmK3g1cEs5WkIvTExPdm9xS1lYVVBSZWltClhsV1ZaVWN5anZTS2hhemRGZllVTW1ycmtPK0htWHNqUDBELzRXWExIVlBmU1NMcVl1aTQ5UGt6RmM3SnM3RGoKcVgzRlpFT0o5eWJwZ2kyUW14eUIwL2RqbXFYbGdOelVWdlBwaE1PUlBFQ2ZHLzZ6SjdZRFpBRU5Bb0dBSElVcQo2UGRKVEVTKzJEbmJ3TFVnOUZIWTdjSlAzRitjNUZoaXNFemMzMzVGYTlNK2RWVVY3eE80QVU3YWVkTUxRUEYzCm1rQ05pRGsxODlEQ1gwS0JSK0RHNnZiLyt2a080clY1aXBaYTdPSW5wVTgxWXZkcndoR3pXRWY3bWI3bEdmOW4KdmNWMURZRlpmYTBoblhjVlFVZWIrL1lJM2pvRGgwblF5UGtzcFRVQ2dZRUF0NERNajdZbStRS2J2bTJXaWNlcAo1Q2s3YWFMSUxuVHZqbGRLMkdjM2loOGVGRlE2Vy9pcUc1UUEzeHMwem8xVnhlUkhPWGkrK01xWjVWTVZMZFRWCjMxWXZOeUdPbVByTitZemVINmlTYXd5VXo2dW1UN1ZkMXRuUEJ1SmdPMFM3RnRlb01BckE3TGtDcUVhMDc4bS8KRXNxNzZjYW1WdW5kRXFTRWhGMllYNkU9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-mtls.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-mtls.out.yaml new file mode 100644 index 00000000000..31c3ae82535 --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-mtls.out.yaml @@ -0,0 +1,273 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-1 + namespace: envoy-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + tls: + clientValidation: + caCertificateRefs: + - group: null + kind: null + name: tls-secret-1 + namespace: envoy-gateway + status: + conditions: + - lastTransitionTime: null + message: ClientTrafficPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-2 + namespace: envoy-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-2 + namespace: envoy-gateway + tls: + clientValidation: + caCertificateRefs: + - group: null + kind: ConfigMap + name: ca-configmap + namespace: envoy-gateway + status: + conditions: + - lastTransitionTime: null + message: ClientTrafficPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +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: Same + name: http-1 + port: 443 + protocol: HTTPS + tls: + certificateRefs: + - group: null + kind: null + name: tls-secret-1 + namespace: envoy-gateway + mode: Terminate + - allowedRoutes: + namespaces: + from: Same + name: http-2 + port: 8080 + protocol: HTTP + 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 + name: http-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: http-2 + 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: Same + name: http-1 + port: 443 + protocol: HTTPS + tls: + certificateRefs: + - group: null + kind: null + name: tls-secret-1 + namespace: envoy-gateway + 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 + name: http-1 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-1/http-1 + ports: + - containerPort: 10443 + name: http-1 + protocol: HTTPS + servicePort: 443 + - address: null + name: envoy-gateway/gateway-1/http-2 + ports: + - containerPort: 8080 + name: http-2 + protocol: HTTP + servicePort: 8080 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-1 + envoy-gateway/gateway-2: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-2/http-1 + ports: + - containerPort: 10443 + name: http-1 + protocol: HTTPS + servicePort: 443 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-2 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-2 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10443 + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURPekNDQWlPZ0F3SUJBZ0lVYzQxa3BFOXdLK05IZ1JHdkJJZ3c4U0Nhei84d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeE1qVXlNekUxTXpGYU1DMHhGVEFUQmdOVkJBb01ER1Y0CllXMXdiR1VnU1c1akxqRVVNQklHQTFVRUF3d0xaWGhoYlhCc1pTNWpiMjB3Z2dFaU1BMEdDU3FHU0liM0RRRUIKQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURDTGhaNURuQ1ZFNUpKOTd5T29jcFJ3Y2xibDBVd1gzY0krMVpaTmx0bApXNmpSZ3kxR3VONlZyN0NCbUkvbVB0Z0dzOVQ3RE5STWw1Z0pKa05IU1pvbUk2R2p1UDFLVWh1dmxmYlpQV05vCnA0NVQyMzVaODJHZzhPUkpIVDVtbjFRUksrYno5cnVKZnlsZE1NbGljVUp2L1lmdDZ6TlVSeFE3QlU5Y2lHZTEKdE0rVU1TeGtvcDNkb3ZWcHRFTG5rVERKU3d0NWRuK25qNmovR3I5NXo5MC9lMmdqZlZUdG1BckFHM3hoLzJCMQovRDZOWGh3UE16WXJwbG5NM2xPcHh6ZmxPVmdqTVVsb0wxb0k3c202YysyQTE0TmVCclcvb2ZCOVJEN0RXQkhkCjc2aitoY0FXRnN4WW1zSG81T3gvdEZlVGs3R1Jka0hFRUxMV0ZCdllHMEJUQWdNQkFBR2pVekJSTUIwR0ExVWQKRGdRV0JCU3JMYmNRUHBFeCtEdCtoWUUveXJqdDZyT1Y2VEFmQmdOVkhTTUVHREFXZ0JTckxiY1FQcEV4K0R0KwpoWUUveXJqdDZyT1Y2VEFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUNGCjRqbHRxeFZhS1phVk1MN0hOUVN3ZWd5K2daMXhhbHltTU5vN0lwYzh6T3lVVUk0N3dlRWYvcCtua3E4b3hpL20KbUxab2VNU2RYZytnZWJZTU1jVVJndGw5UWZ1RjBhWUNCM0FsQ3hscGRINExrM3VYTlRMUVhKaUxRUlROc0J1LwpMSjZVWXZMRktQd29kdlJLTDhLV0tFZ0xWSm1yVGUzZzhpTDNTU253MDBoV2lldUNkU3N4TmwvNDdUaGdZWHJnCnUxUFJCVXQ1ZytYb1dwVVNPQ01PRldsQkpxd0pZS2ZSQTNFNmZmNDRJVUpzYjdxVUhIQWUxd2ExWURmdUQrVDUKQXQ5L20rTTdHeVc5b0ViU1FzUFRHZllxUDU5UUUrMWllaTZxaUcrN2tuNGlSeEpxaGdtNU41bzg2UVNrME1hegpDejRqVEVLZE52WFlWRmZoNlpxcgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + name: envoy-gateway/target-gateway-1/ca.crt + certificates: + - name: envoy-gateway/tls-secret-1 + privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQzc3aHZBUEFlRlJucS8KdHBHVmRKTmVjYWFqSzZrUXlDalk1ci9wWHhOQmE5dldWUUhVbkNXVk95bHBFZGg2T2ZZbUdnb0phdE1UVFlBWAorVml2TFM5WHBIOG5QQ1lhWm9CZGkyUDQxZGtuazJSekZabWwvWFI1SFp0RFpqZURPM3d2Qkpvbm0rTXhQN0JrCjVMZ2U5aEZIUndqRWJMY1k3dys3enE4QkRBeUlIdjdPSjNhN3g5L2pYMlJaRnU3TzVyNXlmRVE2RnNLY3pURG8Kb0N4ZFVrTklndHBWQ29ETEt2Ykw2MW5kTnVsZTMvbURtL3YyU3lUSHVkMVM1ZHFzcDhrSmR1OFhVUmZjMllFbApGS1d2QnRuamgvanJMTVhGY2FoVi9veEpyQ0h1dC9QQ0xiQlRBalRldVNEYXVTN09IYkpSREt3bUg3b1Z2eUlDCmFJeWFZY1pOQWdNQkFBRUNnZ0VBSG1McVd4NHZCbk9ybHFLMGVNLzM5c1lLOEVpTTlra0c5eHRJWGVSTGxCWnIKM2dTeUNSTStXRzk2ZGZkaFkxSDFPa1ZDUGpJOFNEQzRkMzA2Ymw0Ris2RW93TXFrUytjcTlrcDYzYTg3aE5TbQpOMGdxSnl3TGV5YzRXdll2ZFA2c25scnd6MXE3Vk5QbXpQUXJ6b1hIQVc2N2tpeHA1cFF3OG1oVzVQcHlidkp5Clo2TERCZGRSZkVma2ZXVnZUUk5YWUVDUEllUStST05jR3JvVzZ5RXRrbk1BWUJjdjRlNUhCQkkrcHdyYmsrOVMKY2FQYUVjdm4vS0lyT3NpVW1FT2wwb3JXVnhkbjRmMy9MNmlFZFgyZHhIdXlwYkFiL0Qwak1MSzBwb3kyaXYyTApyOGI5VUQrRVZFNmFTVnp0MFRHbVpJYUdRVVZDQnVDTDhodlYwSU9PV1FLQmdRRGplL3JXdmk4Rndia3BRNDA0CnFQcitBaEFwaG1pV3l1a1B1VmJLN2Q5ZkdURzRHOW9Bd2wzYlFoRGVUNHhjMzd0cjlkcCtpamJuWnpKWHczL1cKcm5xTDlGWkZsVXZCYXN6c05VK1lRNmJVOE9zTXl6cURSdGJaaytVWEowUEx6QzZKWHFkNTFZdVVDM3NwL2lmNwpqWEZrME55aHcrdkY3VU51N0ZFSzVuWEUwd0tCZ1FEVGZOT0RLYmZyalNkZEhkV05iOHhkN2pGMlZSY3hTTnRUCit0L0FmbkRjZG8zK1NBUnJaRi9TM0hZWUxxL0l4dmZ5ZHdIblUxdC9INkxDZjBnQ2RXS2NXL1hway93ZUo1QXYKWmdaZjBPTXZsOXF0THJhTU44OG1HblV4K2IxdHZLWm4xQVcySFNuYXd2Z0kvMWVjSldNRUJiYkREbkx4cUpMegowTHJhT2pYVVh3S0JnRGlBbE44OXdjUTJSOTFkNy9mQTBRYkNVRzFmK3g1cEs5WkIvTExPdm9xS1lYVVBSZWltClhsV1ZaVWN5anZTS2hhemRGZllVTW1ycmtPK0htWHNqUDBELzRXWExIVlBmU1NMcVl1aTQ5UGt6RmM3SnM3RGoKcVgzRlpFT0o5eWJwZ2kyUW14eUIwL2RqbXFYbGdOelVWdlBwaE1PUlBFQ2ZHLzZ6SjdZRFpBRU5Bb0dBSElVcQo2UGRKVEVTKzJEbmJ3TFVnOUZIWTdjSlAzRitjNUZoaXNFemMzMzVGYTlNK2RWVVY3eE80QVU3YWVkTUxRUEYzCm1rQ05pRGsxODlEQ1gwS0JSK0RHNnZiLyt2a080clY1aXBaYTdPSW5wVTgxWXZkcndoR3pXRWY3bWI3bEdmOW4KdmNWMURZRlpmYTBoblhjVlFVZWIrL1lJM2pvRGgwblF5UGtzcFRVQ2dZRUF0NERNajdZbStRS2J2bTJXaWNlcAo1Q2s3YWFMSUxuVHZqbGRLMkdjM2loOGVGRlE2Vy9pcUc1UUEzeHMwem8xVnhlUkhPWGkrK01xWjVWTVZMZFRWCjMxWXZOeUdPbVByTitZemVINmlTYXd5VXo2dW1UN1ZkMXRuUEJ1SmdPMFM3RnRlb01BckE3TGtDcUVhMDc4bS8KRXNxNzZjYW1WdW5kRXFTRWhGMllYNkU9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM0RENDQWNnQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeApNalV5TXpFMU16RmFNRDh4R1RBWEJnTlZCQU1NRUdWa1oyVXVaWGhoYlhCc1pTNWpiMjB4SWpBZ0JnTlZCQW9NCkdXVmtaMlVnWlhoaGJYQnNaU0J2Y21kaGJtbDZZWFJwYjI0d2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUIKRHdBd2dnRUtBb0lCQVFDNzdodkFQQWVGUm5xL3RwR1ZkSk5lY2Fhaks2a1F5Q2pZNXIvcFh4TkJhOXZXVlFIVQpuQ1dWT3lscEVkaDZPZlltR2dvSmF0TVRUWUFYK1ZpdkxTOVhwSDhuUENZYVpvQmRpMlA0MWRrbmsyUnpGWm1sCi9YUjVIWnREWmplRE8zd3ZCSm9ubStNeFA3Qms1TGdlOWhGSFJ3akViTGNZN3crN3pxOEJEQXlJSHY3T0ozYTcKeDkvalgyUlpGdTdPNXI1eWZFUTZGc0tjelREb29DeGRVa05JZ3RwVkNvRExLdmJMNjFuZE51bGUzL21EbS92MgpTeVRIdWQxUzVkcXNwOGtKZHU4WFVSZmMyWUVsRktXdkJ0bmpoL2pyTE1YRmNhaFYvb3hKckNIdXQvUENMYkJUCkFqVGV1U0RhdVM3T0hiSlJES3dtSDdvVnZ5SUNhSXlhWWNaTkFnTUJBQUV3RFFZSktvWklodmNOQVFFTEJRQUQKZ2dFQkFHeW5yNGNPMWFZbjRNQk90aVJ2WHFJdllHNnpxZXNrNGpQbU96TjdiUTdyRzdNUngzSVQ2SW4zVFI4RApHbFAxVE54TTg5cXZRcXp4VERsdER3bXluTlV1SEdEUW4yV1Z1OFEyK0RqRnFoc3B1WHp0NnhVK2RoVVBxUnV1Ckt6c1l4TDNpMVlWZ2pDQWtBUmp4SGhMWHYwdkFUWUVRMlJ6Uko5c2ZGcWVCMHVxSk5WL0lHamJFSzQ2eTQ5QU0KNzU4TUY4T0R6cVR2Q3hMRjJYd3BScjdjSDFuZ2J4eUJ6cEdlbkpsVTI2Q2hJT1BMZUV1NTUyUVJYVGwrU2JlQQpXUzNpS01Pb3F5NGV0b0ExNWFueW43Zm01YnpINEcyZ3Yxd1pWYlBkT1dNQWRZU2I5NDIvR09CSWUzSnIyVHo3CjRJdDRROWFERnF1aG9iOTVQMUhHQkxSQ2Y5QT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + maxVersion: "1.3" + minVersion: "1.2" + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http-2 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 8080 + envoy-gateway/gateway-2: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-2/http-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10443 + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURPekNDQWlPZ0F3SUJBZ0lVYzQxa3BFOXdLK05IZ1JHdkJJZ3c4U0Nhei84d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeE1qVXlNekUxTXpGYU1DMHhGVEFUQmdOVkJBb01ER1Y0CllXMXdiR1VnU1c1akxqRVVNQklHQTFVRUF3d0xaWGhoYlhCc1pTNWpiMjB3Z2dFaU1BMEdDU3FHU0liM0RRRUIKQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURDTGhaNURuQ1ZFNUpKOTd5T29jcFJ3Y2xibDBVd1gzY0krMVpaTmx0bApXNmpSZ3kxR3VONlZyN0NCbUkvbVB0Z0dzOVQ3RE5STWw1Z0pKa05IU1pvbUk2R2p1UDFLVWh1dmxmYlpQV05vCnA0NVQyMzVaODJHZzhPUkpIVDVtbjFRUksrYno5cnVKZnlsZE1NbGljVUp2L1lmdDZ6TlVSeFE3QlU5Y2lHZTEKdE0rVU1TeGtvcDNkb3ZWcHRFTG5rVERKU3d0NWRuK25qNmovR3I5NXo5MC9lMmdqZlZUdG1BckFHM3hoLzJCMQovRDZOWGh3UE16WXJwbG5NM2xPcHh6ZmxPVmdqTVVsb0wxb0k3c202YysyQTE0TmVCclcvb2ZCOVJEN0RXQkhkCjc2aitoY0FXRnN4WW1zSG81T3gvdEZlVGs3R1Jka0hFRUxMV0ZCdllHMEJUQWdNQkFBR2pVekJSTUIwR0ExVWQKRGdRV0JCU3JMYmNRUHBFeCtEdCtoWUUveXJqdDZyT1Y2VEFmQmdOVkhTTUVHREFXZ0JTckxiY1FQcEV4K0R0KwpoWUUveXJqdDZyT1Y2VEFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUNGCjRqbHRxeFZhS1phVk1MN0hOUVN3ZWd5K2daMXhhbHltTU5vN0lwYzh6T3lVVUk0N3dlRWYvcCtua3E4b3hpL20KbUxab2VNU2RYZytnZWJZTU1jVVJndGw5UWZ1RjBhWUNCM0FsQ3hscGRINExrM3VYTlRMUVhKaUxRUlROc0J1LwpMSjZVWXZMRktQd29kdlJLTDhLV0tFZ0xWSm1yVGUzZzhpTDNTU253MDBoV2lldUNkU3N4TmwvNDdUaGdZWHJnCnUxUFJCVXQ1ZytYb1dwVVNPQ01PRldsQkpxd0pZS2ZSQTNFNmZmNDRJVUpzYjdxVUhIQWUxd2ExWURmdUQrVDUKQXQ5L20rTTdHeVc5b0ViU1FzUFRHZllxUDU5UUUrMWllaTZxaUcrN2tuNGlSeEpxaGdtNU41bzg2UVNrME1hegpDejRqVEVLZE52WFlWRmZoNlpxcgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + name: envoy-gateway/target-gateway-2/ca.crt + certificates: + - name: envoy-gateway/tls-secret-1 + privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQzc3aHZBUEFlRlJucS8KdHBHVmRKTmVjYWFqSzZrUXlDalk1ci9wWHhOQmE5dldWUUhVbkNXVk95bHBFZGg2T2ZZbUdnb0phdE1UVFlBWAorVml2TFM5WHBIOG5QQ1lhWm9CZGkyUDQxZGtuazJSekZabWwvWFI1SFp0RFpqZURPM3d2Qkpvbm0rTXhQN0JrCjVMZ2U5aEZIUndqRWJMY1k3dys3enE4QkRBeUlIdjdPSjNhN3g5L2pYMlJaRnU3TzVyNXlmRVE2RnNLY3pURG8Kb0N4ZFVrTklndHBWQ29ETEt2Ykw2MW5kTnVsZTMvbURtL3YyU3lUSHVkMVM1ZHFzcDhrSmR1OFhVUmZjMllFbApGS1d2QnRuamgvanJMTVhGY2FoVi9veEpyQ0h1dC9QQ0xiQlRBalRldVNEYXVTN09IYkpSREt3bUg3b1Z2eUlDCmFJeWFZY1pOQWdNQkFBRUNnZ0VBSG1McVd4NHZCbk9ybHFLMGVNLzM5c1lLOEVpTTlra0c5eHRJWGVSTGxCWnIKM2dTeUNSTStXRzk2ZGZkaFkxSDFPa1ZDUGpJOFNEQzRkMzA2Ymw0Ris2RW93TXFrUytjcTlrcDYzYTg3aE5TbQpOMGdxSnl3TGV5YzRXdll2ZFA2c25scnd6MXE3Vk5QbXpQUXJ6b1hIQVc2N2tpeHA1cFF3OG1oVzVQcHlidkp5Clo2TERCZGRSZkVma2ZXVnZUUk5YWUVDUEllUStST05jR3JvVzZ5RXRrbk1BWUJjdjRlNUhCQkkrcHdyYmsrOVMKY2FQYUVjdm4vS0lyT3NpVW1FT2wwb3JXVnhkbjRmMy9MNmlFZFgyZHhIdXlwYkFiL0Qwak1MSzBwb3kyaXYyTApyOGI5VUQrRVZFNmFTVnp0MFRHbVpJYUdRVVZDQnVDTDhodlYwSU9PV1FLQmdRRGplL3JXdmk4Rndia3BRNDA0CnFQcitBaEFwaG1pV3l1a1B1VmJLN2Q5ZkdURzRHOW9Bd2wzYlFoRGVUNHhjMzd0cjlkcCtpamJuWnpKWHczL1cKcm5xTDlGWkZsVXZCYXN6c05VK1lRNmJVOE9zTXl6cURSdGJaaytVWEowUEx6QzZKWHFkNTFZdVVDM3NwL2lmNwpqWEZrME55aHcrdkY3VU51N0ZFSzVuWEUwd0tCZ1FEVGZOT0RLYmZyalNkZEhkV05iOHhkN2pGMlZSY3hTTnRUCit0L0FmbkRjZG8zK1NBUnJaRi9TM0hZWUxxL0l4dmZ5ZHdIblUxdC9INkxDZjBnQ2RXS2NXL1hway93ZUo1QXYKWmdaZjBPTXZsOXF0THJhTU44OG1HblV4K2IxdHZLWm4xQVcySFNuYXd2Z0kvMWVjSldNRUJiYkREbkx4cUpMegowTHJhT2pYVVh3S0JnRGlBbE44OXdjUTJSOTFkNy9mQTBRYkNVRzFmK3g1cEs5WkIvTExPdm9xS1lYVVBSZWltClhsV1ZaVWN5anZTS2hhemRGZllVTW1ycmtPK0htWHNqUDBELzRXWExIVlBmU1NMcVl1aTQ5UGt6RmM3SnM3RGoKcVgzRlpFT0o5eWJwZ2kyUW14eUIwL2RqbXFYbGdOelVWdlBwaE1PUlBFQ2ZHLzZ6SjdZRFpBRU5Bb0dBSElVcQo2UGRKVEVTKzJEbmJ3TFVnOUZIWTdjSlAzRitjNUZoaXNFemMzMzVGYTlNK2RWVVY3eE80QVU3YWVkTUxRUEYzCm1rQ05pRGsxODlEQ1gwS0JSK0RHNnZiLyt2a080clY1aXBaYTdPSW5wVTgxWXZkcndoR3pXRWY3bWI3bEdmOW4KdmNWMURZRlpmYTBoblhjVlFVZWIrL1lJM2pvRGgwblF5UGtzcFRVQ2dZRUF0NERNajdZbStRS2J2bTJXaWNlcAo1Q2s3YWFMSUxuVHZqbGRLMkdjM2loOGVGRlE2Vy9pcUc1UUEzeHMwem8xVnhlUkhPWGkrK01xWjVWTVZMZFRWCjMxWXZOeUdPbVByTitZemVINmlTYXd5VXo2dW1UN1ZkMXRuUEJ1SmdPMFM3RnRlb01BckE3TGtDcUVhMDc4bS8KRXNxNzZjYW1WdW5kRXFTRWhGMllYNkU9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM0RENDQWNnQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5EQXhNall5TXpFMU16RmFGdzB5TlRBeApNalV5TXpFMU16RmFNRDh4R1RBWEJnTlZCQU1NRUdWa1oyVXVaWGhoYlhCc1pTNWpiMjB4SWpBZ0JnTlZCQW9NCkdXVmtaMlVnWlhoaGJYQnNaU0J2Y21kaGJtbDZZWFJwYjI0d2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUIKRHdBd2dnRUtBb0lCQVFDNzdodkFQQWVGUm5xL3RwR1ZkSk5lY2Fhaks2a1F5Q2pZNXIvcFh4TkJhOXZXVlFIVQpuQ1dWT3lscEVkaDZPZlltR2dvSmF0TVRUWUFYK1ZpdkxTOVhwSDhuUENZYVpvQmRpMlA0MWRrbmsyUnpGWm1sCi9YUjVIWnREWmplRE8zd3ZCSm9ubStNeFA3Qms1TGdlOWhGSFJ3akViTGNZN3crN3pxOEJEQXlJSHY3T0ozYTcKeDkvalgyUlpGdTdPNXI1eWZFUTZGc0tjelREb29DeGRVa05JZ3RwVkNvRExLdmJMNjFuZE51bGUzL21EbS92MgpTeVRIdWQxUzVkcXNwOGtKZHU4WFVSZmMyWUVsRktXdkJ0bmpoL2pyTE1YRmNhaFYvb3hKckNIdXQvUENMYkJUCkFqVGV1U0RhdVM3T0hiSlJES3dtSDdvVnZ5SUNhSXlhWWNaTkFnTUJBQUV3RFFZSktvWklodmNOQVFFTEJRQUQKZ2dFQkFHeW5yNGNPMWFZbjRNQk90aVJ2WHFJdllHNnpxZXNrNGpQbU96TjdiUTdyRzdNUngzSVQ2SW4zVFI4RApHbFAxVE54TTg5cXZRcXp4VERsdER3bXluTlV1SEdEUW4yV1Z1OFEyK0RqRnFoc3B1WHp0NnhVK2RoVVBxUnV1Ckt6c1l4TDNpMVlWZ2pDQWtBUmp4SGhMWHYwdkFUWUVRMlJ6Uko5c2ZGcWVCMHVxSk5WL0lHamJFSzQ2eTQ5QU0KNzU4TUY4T0R6cVR2Q3hMRjJYd3BScjdjSDFuZ2J4eUJ6cEdlbkpsVTI2Q2hJT1BMZUV1NTUyUVJYVGwrU2JlQQpXUzNpS01Pb3F5NGV0b0ExNWFueW43Zm01YnpINEcyZ3Yxd1pWYlBkT1dNQWRZU2I5NDIvR09CSWUzSnIyVHo3CjRJdDRROWFERnF1aG9iOTVQMUhHQkxSQ2Y5QT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= + maxVersion: "1.3" + minVersion: "1.2" diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-preserve-case.in.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-preserve-case.in.yaml new file mode 100644 index 00000000000..5a5711f32ed --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-preserve-case.in.yaml @@ -0,0 +1,36 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-1 + spec: + http1: + enableTrailers: true + preserveHeaderCase: true + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http-1 + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: Same + - name: http-2 + protocol: HTTP + port: 8080 + allowedRoutes: + namespaces: + from: Same diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-preserve-case.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-preserve-case.out.yaml new file mode 100644 index 00000000000..c291e36929d --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-preserve-case.out.yaml @@ -0,0 +1,146 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-1 + namespace: envoy-gateway + spec: + http1: + enableTrailers: true + preserveHeaderCase: true + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + status: + conditions: + - lastTransitionTime: null + message: ClientTrafficPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +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: Same + name: http-1 + port: 80 + protocol: HTTP + - allowedRoutes: + namespaces: + from: Same + name: http-2 + port: 8080 + protocol: HTTP + 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 + name: http-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: http-2 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-1/http-1 + ports: + - containerPort: 10080 + name: http-1 + protocol: HTTP + servicePort: 80 + - address: null + name: envoy-gateway/gateway-1/http-2 + ports: + - containerPort: 8080 + name: http-2 + protocol: HTTP + servicePort: 8080 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-1 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + http1: + enableTrailers: true + preserveHeaderCase: true + isHTTP2: false + name: envoy-gateway/gateway-1/http-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + - address: 0.0.0.0 + hostnames: + - '*' + http1: + enableTrailers: true + preserveHeaderCase: true + isHTTP2: false + name: envoy-gateway/gateway-1/http-2 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 8080 diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-timeout-with-error.in.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-timeout-with-error.in.yaml new file mode 100644 index 00000000000..b9cad3568bc --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-timeout-with-error.in.yaml @@ -0,0 +1,31 @@ +clientTrafficPolicies: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway + namespace: envoy-gateway + timeout: + http: + requestReceivedTimeout: "5sec" +gateways: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: Same + diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-timeout-with-error.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-timeout-with-error.out.yaml new file mode 100644 index 00000000000..7aa096ad457 --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-timeout-with-error.out.yaml @@ -0,0 +1,95 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway + namespace: envoy-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway + namespace: envoy-gateway + timeout: + http: + requestReceivedTimeout: 5sec + status: + conditions: + - lastTransitionTime: null + message: 'Time: unknown unit "sec" in duration "5sec"' + reason: Invalid + status: "False" + type: Accepted +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: Same + name: http + port: 80 + protocol: HTTP + 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 + name: http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +infraIR: + envoy-gateway/gateway: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway/http + ports: + - containerPort: 10080 + name: http + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway +xdsIR: + envoy-gateway/gateway: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-timeout.in.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-timeout.in.yaml new file mode 100644 index 00000000000..0c962e72fe8 --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-timeout.in.yaml @@ -0,0 +1,38 @@ +clientTrafficPolicies: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway + namespace: envoy-gateway + sectionName: http-1 + timeout: + http: + requestReceivedTimeout: "5s" +gateways: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http-1 + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: Same + - name: http-2 + protocol: HTTP + port: 8080 + allowedRoutes: + namespaces: + from: Same + diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-timeout.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-timeout.out.yaml new file mode 100644 index 00000000000..32d9e109bd0 --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-timeout.out.yaml @@ -0,0 +1,144 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway + namespace: envoy-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway + namespace: envoy-gateway + sectionName: http-1 + timeout: + http: + requestReceivedTimeout: 5s + status: + conditions: + - lastTransitionTime: null + message: ClientTrafficPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: Same + name: http-1 + port: 80 + protocol: HTTP + - allowedRoutes: + namespaces: + from: Same + name: http-2 + port: 8080 + protocol: HTTP + 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 + name: http-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: http-2 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +infraIR: + envoy-gateway/gateway: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway/http-1 + ports: + - containerPort: 10080 + name: http-1 + protocol: HTTP + servicePort: 80 + - address: null + name: envoy-gateway/gateway/http-2 + ports: + - containerPort: 8080 + name: http-2 + protocol: HTTP + servicePort: 8080 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway +xdsIR: + envoy-gateway/gateway: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway/http-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + timeout: + http: + requestReceivedTimeout: 5s + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway/http-2 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 8080 diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-tls-settings.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-tls-settings.out.yaml index 13154cdb100..70adfea5072 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-tls-settings.out.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-tls-settings.out.yaml @@ -150,7 +150,7 @@ xdsIR: alpnProtocols: - h2 certificates: - - name: envoy-gateway-tls-secret-1 + - name: envoy-gateway/tls-secret-1 privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2QwZlBDYWtweE1nUnUKT0VXQjFiQk5FM3ZseW55aTZWbkV2VWF1OUhvakR2UHVPTFJIaGI4MmoyY1ovMHhnL1lKR09LelBuV2JERkxGNApHdWh3dDRENmFUR0xYNklPODEwTDZ0SXZIWGZNUXRJS2VwdTZ3K3p1WVo4bG1yejB1RjZlWEtqamVIbHhyb2ZrCnVNekM3OUVaU0lYZlZlczJ1SmdVRSs4VGFzSDUzQ2Y4MFNSRGlIeEdxckttdVNjWCtwejBreGdCZ1VWYTVVS20KUWdTZDFmVUxLOUEwNXAxOXkrdURPM204bVhRNkxVQ0N1STFwZHNROGFlNS9zamlxa0VjWlJjMTdWYVgxWjVVaQpvcGZnNW9SY05VTG9VTHNiek9aNTR0YlVDUmdSV2VLbGZxaElINEZ6OUlkVlUyR3dFdEdhMmV6TjgyMVBaQ3QzCjZhbVRIelJsQWdNQkFBRUNnZ0VBWTFGTUlLNDVXTkVNUHJ6RTZUY3NNdVV2RkdhQVZ4bVk5NW5SMEtwajdvb3IKY21CVys2ZXN0TTQ4S1AwaitPbXd3VFpMY29Cd3VoWGN0V1Bob1lXcDhteWUxRUlEdjNyaHRHMDdocEQ1NGg2dgpCZzh3ejdFYStzMk9sT0N6UnlKNzBSY281YlhjWDNGaGJjdnFlRWJwaFFyQnpOSEtLMjZ4cmZqNWZIT3p6T1FGCmJHdUZ3SDVic3JGdFhlajJXM3c4eW90N0ZQSDV3S3RpdnhvSWU5RjMyOXNnOU9EQnZqWnpiaG1LVTArckFTK1kKRGVield2bFJyaEUrbXVmQTN6M0N0QXhDOFJpNzNscFNoTDRQQWlvcG1SUXlxZXRXMjYzOFFxcnM0R3hnNzhwbApJUXJXTmNBc2s3Slg5d3RZenV6UFBXSXRWTTFscFJiQVRhNTJqdFl2NVFLQmdRRE5tMTFtZTRYam1ZSFV2cStZCmFTUzdwK2UybXZEMHVaOU9JeFluQnBWMGkrckNlYnFFMkE1Rm5hcDQ5Yld4QTgwUElldlVkeUpCL2pUUkoxcVMKRUpXQkpMWm1LVkg2K1QwdWw1ZUtOcWxFTFZHU0dCSXNpeE9SUXpDZHBoMkx0UmtBMHVjSVUzY3hiUmVMZkZCRQpiSkdZWENCdlNGcWd0VDlvZTFldVpMVmFOd0tCZ1FERWdENzJENk81eGIweEQ1NDQ1M0RPMUJhZmd6aThCWDRTCk1SaVd2LzFUQ0w5N05sRWtoeXovNmtQd1owbXJRcE5CMzZFdkpKZFVteHdkU2MyWDhrOGcxMC85NVlLQkdWQWoKL3d0YVZYbE9WeEFvK0ZSelpZeFpyQ29uWWFSMHVwUzFybDRtenN4REhlZU9mUVZUTUgwUjdZN0pnbTA5dXQ4SwplanAvSXZBb1F3S0JnQjNaRWlRUWhvMVYrWjBTMlpiOG5KS0plMy9zMmxJTXFHM0ZkaS9RS3Q0eWViQWx6OGY5ClBZVXBzRmZEQTg5Z3grSU1nSm5sZVptdTk2ZnRXSjZmdmJSenllN216TG5zZU05TXZua1lHbGFGWmJRWnZubXMKN3ZoRmtzY3dHRlh4d21GMlBJZmU1Z3pNMDRBeVdjeTFIaVhLS2dNOXM3cGsxWUdyZGowZzdacmRBb0dCQUtLNApDR3MrbkRmMEZTMFJYOWFEWVJrRTdBNy9YUFhtSG5YMkRnU1h5N0Q4NTRPaWdTTWNoUmtPNTErbVNJejNQbllvCk41T1FXM2lHVVl1M1YvYmhnc0VSUzM1V2xmRk9BdDBzRUR5bjF5SVdXcDF5dG93d3BUNkVvUXVuZ2NYZjA5RjMKS1NROXowd3M4VmsvRWkvSFVXcU5LOWFXbU51cmFaT0ZqL2REK1ZkOUFvR0FMWFN3dEE3K043RDRkN0VEMURSRQpHTWdZNVd3OHFvdDZSdUNlNkpUY0FnU3B1MkhNU3JVY2dXclpiQnJZb09FUnVNQjFoMVJydk5ybU1qQlM0VW9FClgyZC8vbGhpOG1wL2VESWN3UDNRa2puanBJRFJWMFN1eWxrUkVaZURKZjVZb3R6eDdFdkJhbzFIbkQrWEg4eUIKVUtmWGJTaHZKVUdhRmgxT3Q1Y3JoM1k9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNxRENDQVpBQ0NRREVNZ1lZblFyQ29EQU5CZ2txaGtpRzl3MEJBUXNGQURBV01SUXdFZ1lEVlFRRERBdG0KYjI4dVltRnlMbU52YlRBZUZ3MHlNekF4TURVeE16UXpNalJhRncweU5EQXhNRFV4TXpRek1qUmFNQll4RkRBUwpCZ05WQkFNTUMyWnZieTVpWVhJdVkyOXRNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDCkFRRUFuZEh6d21wS2NUSUViamhGZ2RXd1RSTjc1Y3A4b3VsWnhMMUdydlI2SXc3ejdqaTBSNFcvTm85bkdmOU0KWVAyQ1JqaXN6NTFtd3hTeGVCcm9jTGVBK21reGkxK2lEdk5kQytyU0x4MTN6RUxTQ25xYnVzUHM3bUdmSlpxOAo5TGhlbmx5bzQzaDVjYTZINUxqTXd1L1JHVWlGMzFYck5yaVlGQlB2RTJyQitkd24vTkVrUTRoOFJxcXlwcmtuCkYvcWM5Sk1ZQVlGRld1VkNwa0lFbmRYMUN5dlFOT2FkZmN2cmd6dDV2SmwwT2kxQWdyaU5hWGJFUEdudWY3STQKcXBCSEdVWE5lMVdsOVdlVklxS1g0T2FFWERWQzZGQzdHOHptZWVMVzFBa1lFVm5pcFg2b1NCK0JjL1NIVlZOaApzQkxSbXRuc3pmTnRUMlFyZCttcGt4ODBaUUlEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ1VKOElDCkJveUVqT3V3enBHYVJoR044QjRqT1B6aHVDT0V0ZDM3UzAybHUwN09IenlCdmJzVEd6S3dCZ0x5bVdmR2tINEIKajdDTHNwOEZ6TkhLWnVhQmdwblo5SjZETE9Od2ZXZTJBWXA3TGRmT0tWQlVkTVhRaU9tN2pKOUhob0Ntdk1ONwpic2pjaFdKb013ckZmK3dkQUthdHowcUFQeWhMeWUvRnFtaVZ4a09SWmF3K1Q5bURaK0g0OXVBU2d1SnVOTXlRClY2RXlYNmd0Z1dxMzc2SHZhWE1TLzNoYW1Zb1ZXWEk1TXhpUE9ZeG5BQmtKQjRTQ2dJUmVqYkpmVmFRdG9RNGEKejAyaVVMZW5ESUllUU9Zb2JLY01CWGYxQjRQQVFtc2VocVZJYnpzUUNHaTU0VkRyczZiWmQvN0pzMXpDcHBncwpKaUQ1SXFNaktXRHdxN2FLCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K ciphers: diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-trailers.in.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-trailers.in.yaml new file mode 100644 index 00000000000..c9b087d3ff4 --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-trailers.in.yaml @@ -0,0 +1,35 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-1 + spec: + http1: + enableTrailers: true + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http-1 + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: Same + - name: http-2 + protocol: HTTP + port: 8080 + allowedRoutes: + namespaces: + from: Same diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-suppress-envoy-headers.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-trailers.out.yaml similarity index 96% rename from internal/gatewayapi/testdata/clienttrafficpolicy-suppress-envoy-headers.out.yaml rename to internal/gatewayapi/testdata/clienttrafficpolicy-trailers.out.yaml index c68422f5084..a469b4ecddd 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-suppress-envoy-headers.out.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-trailers.out.yaml @@ -3,16 +3,16 @@ clientTrafficPolicies: kind: ClientTrafficPolicy metadata: creationTimestamp: null - name: target-gateway-1-section-http-1 + name: target-gateway-1 namespace: envoy-gateway spec: - suppressEnvoyHeaders: true + http1: + enableTrailers: true targetRef: group: gateway.networking.k8s.io kind: Gateway name: gateway-1 namespace: envoy-gateway - sectionName: http-1 status: conditions: - lastTransitionTime: null @@ -122,16 +122,19 @@ xdsIR: - address: 0.0.0.0 hostnames: - '*' + http1: + enableTrailers: true isHTTP2: false name: envoy-gateway/gateway-1/http-1 path: escapedSlashesAction: UnescapeAndRedirect mergeSlashes: true port: 10080 - suppressEnvoyHeaders: true - address: 0.0.0.0 hostnames: - '*' + http1: + enableTrailers: true isHTTP2: false name: envoy-gateway/gateway-1/http-2 path: diff --git a/internal/gatewayapi/testdata/disable-accesslog.in.yaml b/internal/gatewayapi/testdata/disable-accesslog.in.yaml index 206f0d46b2c..c6fa25f5cc6 100644 --- a/internal/gatewayapi/testdata/disable-accesslog.in.yaml +++ b/internal/gatewayapi/testdata/disable-accesslog.in.yaml @@ -21,7 +21,7 @@ envoyproxy: value: env_a_value - name: env_b value: env_b_name - image: "envoyproxy/envoy-dev:latest" + image: "envoyproxy/envoy:distroless-dev" resources: requests: cpu: 100m diff --git a/internal/gatewayapi/testdata/disable-accesslog.out.yaml b/internal/gatewayapi/testdata/disable-accesslog.out.yaml index 3806e4f113e..c48bad79000 100644 --- a/internal/gatewayapi/testdata/disable-accesslog.out.yaml +++ b/internal/gatewayapi/testdata/disable-accesslog.out.yaml @@ -60,7 +60,7 @@ infraIR: value: env_a_value - name: env_b value: env_b_name - image: envoyproxy/envoy-dev:latest + image: envoyproxy/envoy:distroless-dev resources: requests: cpu: 100m diff --git a/internal/gatewayapi/testdata/envoypatchpolicy-invalid-feature-disabled.in.yaml b/internal/gatewayapi/testdata/envoypatchpolicy-invalid-feature-disabled.in.yaml new file mode 100644 index 00000000000..4942b803092 --- /dev/null +++ b/internal/gatewayapi/testdata/envoypatchpolicy-invalid-feature-disabled.in.yaml @@ -0,0 +1,43 @@ +envoyproxy: + apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyProxy + metadata: + namespace: envoy-gateway-system + name: test + spec: + mergeGateways: true +envoyPatchPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyPatchPolicy + metadata: + namespace: envoy-gateway + name: edit-conn-buffer-bytes + spec: + type: "JSONPatch" + targetRef: + group: gateway.networking.k8s.io + kind: GatewayClass + name: envoy-gateway-class + namespace: envoy-gateway + jsonPatches: + - type: "type.googleapis.com/envoy.config.listener.v3.Listener" + name: "envoy-gateway-gateway-1-http" + operation: + op: replace + path: "/per_connection_buffer_limit_bytes" + value: "1024" +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: Same diff --git a/internal/gatewayapi/testdata/envoypatchpolicy-invalid-feature-disabled.out.yaml b/internal/gatewayapi/testdata/envoypatchpolicy-invalid-feature-disabled.out.yaml new file mode 100644 index 00000000000..711b21017b2 --- /dev/null +++ b/internal/gatewayapi/testdata/envoypatchpolicy-invalid-feature-disabled.out.yaml @@ -0,0 +1,92 @@ +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: Same + name: http + port: 80 + protocol: HTTP + 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 + name: http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +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/http + ports: + - containerPort: 10080 + name: envoy-gateway/gateway-1/http + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gatewayclass: envoy-gateway-class + name: envoy-gateway-class +xdsIR: + envoy-gateway-class: + accessLog: + text: + - path: /dev/stdout + envoyPatchPolicies: + - name: edit-conn-buffer-bytes + namespace: envoy-gateway + status: + conditions: + - lastTransitionTime: null + message: EnvoyPatchPolicy is disabled in the EnvoyGateway configuration + reason: Disabled + status: "False" + type: Accepted + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 diff --git a/internal/gatewayapi/testdata/envoyproxy-accesslog-file-json-no-format.in.yaml b/internal/gatewayapi/testdata/envoyproxy-accesslog-file-json-no-format.in.yaml index 3b1940f1fbd..67db26d8e71 100644 --- a/internal/gatewayapi/testdata/envoyproxy-accesslog-file-json-no-format.in.yaml +++ b/internal/gatewayapi/testdata/envoyproxy-accesslog-file-json-no-format.in.yaml @@ -27,7 +27,7 @@ envoyproxy: value: env_a_value - name: env_b value: env_b_name - image: "envoyproxy/envoy-dev:latest" + image: "envoyproxy/envoy:distroless-dev" resources: requests: cpu: 100m diff --git a/internal/gatewayapi/testdata/envoyproxy-accesslog-file-json-no-format.out.yaml b/internal/gatewayapi/testdata/envoyproxy-accesslog-file-json-no-format.out.yaml index 8108fe962c9..7b6af7c2fd3 100644 --- a/internal/gatewayapi/testdata/envoyproxy-accesslog-file-json-no-format.out.yaml +++ b/internal/gatewayapi/testdata/envoyproxy-accesslog-file-json-no-format.out.yaml @@ -60,7 +60,7 @@ infraIR: value: env_a_value - name: env_b value: env_b_name - image: envoyproxy/envoy-dev:latest + image: envoyproxy/envoy:distroless-dev resources: requests: cpu: 100m diff --git a/internal/gatewayapi/testdata/envoyproxy-accesslog-file-json.in.yaml b/internal/gatewayapi/testdata/envoyproxy-accesslog-file-json.in.yaml index 2bf2dc6ae59..3dc3c98a88c 100644 --- a/internal/gatewayapi/testdata/envoyproxy-accesslog-file-json.in.yaml +++ b/internal/gatewayapi/testdata/envoyproxy-accesslog-file-json.in.yaml @@ -30,7 +30,7 @@ envoyproxy: value: env_a_value - name: env_b value: env_b_name - image: "envoyproxy/envoy-dev:latest" + image: "envoyproxy/envoy:distroless-dev" resources: requests: cpu: 100m diff --git a/internal/gatewayapi/testdata/envoyproxy-accesslog-file-json.out.yaml b/internal/gatewayapi/testdata/envoyproxy-accesslog-file-json.out.yaml index 1993cfea30d..73566a7adec 100644 --- a/internal/gatewayapi/testdata/envoyproxy-accesslog-file-json.out.yaml +++ b/internal/gatewayapi/testdata/envoyproxy-accesslog-file-json.out.yaml @@ -60,7 +60,7 @@ infraIR: value: env_a_value - name: env_b value: env_b_name - image: envoyproxy/envoy-dev:latest + image: envoyproxy/envoy:distroless-dev resources: requests: cpu: 100m diff --git a/internal/gatewayapi/testdata/envoyproxy-accesslog-with-bad-sinks.in.yaml b/internal/gatewayapi/testdata/envoyproxy-accesslog-with-bad-sinks.in.yaml index 4cfbeea2e6d..cccabc9cd4d 100644 --- a/internal/gatewayapi/testdata/envoyproxy-accesslog-with-bad-sinks.in.yaml +++ b/internal/gatewayapi/testdata/envoyproxy-accesslog-with-bad-sinks.in.yaml @@ -28,7 +28,7 @@ envoyproxy: value: env_a_value - name: env_b value: env_b_name - image: "envoyproxy/envoy-dev:latest" + image: "envoyproxy/envoy:distroless-dev" resources: requests: cpu: 100m diff --git a/internal/gatewayapi/testdata/envoyproxy-accesslog-with-bad-sinks.out.yaml b/internal/gatewayapi/testdata/envoyproxy-accesslog-with-bad-sinks.out.yaml index 87e10907af6..583ce720c9a 100644 --- a/internal/gatewayapi/testdata/envoyproxy-accesslog-with-bad-sinks.out.yaml +++ b/internal/gatewayapi/testdata/envoyproxy-accesslog-with-bad-sinks.out.yaml @@ -60,7 +60,7 @@ infraIR: value: env_a_value - name: env_b value: env_b_name - image: envoyproxy/envoy-dev:latest + image: envoyproxy/envoy:distroless-dev resources: requests: cpu: 100m diff --git a/internal/gatewayapi/testdata/envoyproxy-accesslog.in.yaml b/internal/gatewayapi/testdata/envoyproxy-accesslog.in.yaml index fe311ea0a59..0d691420576 100644 --- a/internal/gatewayapi/testdata/envoyproxy-accesslog.in.yaml +++ b/internal/gatewayapi/testdata/envoyproxy-accesslog.in.yaml @@ -35,7 +35,7 @@ envoyproxy: value: env_a_value - name: env_b value: env_b_name - image: "envoyproxy/envoy-dev:latest" + image: "envoyproxy/envoy:distroless-dev" resources: requests: cpu: 100m diff --git a/internal/gatewayapi/testdata/envoyproxy-accesslog.out.yaml b/internal/gatewayapi/testdata/envoyproxy-accesslog.out.yaml index ecc7aa7642d..74a090dc6e8 100644 --- a/internal/gatewayapi/testdata/envoyproxy-accesslog.out.yaml +++ b/internal/gatewayapi/testdata/envoyproxy-accesslog.out.yaml @@ -60,7 +60,7 @@ infraIR: value: env_a_value - name: env_b value: env_b_name - image: envoyproxy/envoy-dev:latest + image: envoyproxy/envoy:distroless-dev resources: requests: cpu: 100m diff --git a/internal/gatewayapi/testdata/envoyproxy-valid.in.yaml b/internal/gatewayapi/testdata/envoyproxy-valid.in.yaml index 172af475b30..fced37e87f2 100644 --- a/internal/gatewayapi/testdata/envoyproxy-valid.in.yaml +++ b/internal/gatewayapi/testdata/envoyproxy-valid.in.yaml @@ -18,7 +18,7 @@ envoyproxy: value: env_a_value - name: env_b value: env_b_name - image: "envoyproxy/envoy-dev:latest" + image: "envoyproxy/envoy:distroless-dev" resources: requests: cpu: 100m diff --git a/internal/gatewayapi/testdata/envoyproxy-valid.out.yaml b/internal/gatewayapi/testdata/envoyproxy-valid.out.yaml index 5b6092a6171..b5a1347f4fc 100644 --- a/internal/gatewayapi/testdata/envoyproxy-valid.out.yaml +++ b/internal/gatewayapi/testdata/envoyproxy-valid.out.yaml @@ -60,7 +60,7 @@ infraIR: value: env_a_value - name: env_b value: env_b_name - image: envoyproxy/envoy-dev:latest + image: envoyproxy/envoy:distroless-dev resources: requests: cpu: 100m diff --git a/internal/gatewayapi/testdata/gateway-infrastructure.out.yaml b/internal/gatewayapi/testdata/gateway-infrastructure.out.yaml index 34d5ebda862..57e77d7b5f5 100644 --- a/internal/gatewayapi/testdata/gateway-infrastructure.out.yaml +++ b/internal/gatewayapi/testdata/gateway-infrastructure.out.yaml @@ -144,6 +144,6 @@ xdsIR: prefix: / tls: certificates: - - name: default-tls-secret-1 + - name: default/tls-secret-1 privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2QwZlBDYWtweE1nUnUKT0VXQjFiQk5FM3ZseW55aTZWbkV2VWF1OUhvakR2UHVPTFJIaGI4MmoyY1ovMHhnL1lKR09LelBuV2JERkxGNApHdWh3dDRENmFUR0xYNklPODEwTDZ0SXZIWGZNUXRJS2VwdTZ3K3p1WVo4bG1yejB1RjZlWEtqamVIbHhyb2ZrCnVNekM3OUVaU0lYZlZlczJ1SmdVRSs4VGFzSDUzQ2Y4MFNSRGlIeEdxckttdVNjWCtwejBreGdCZ1VWYTVVS20KUWdTZDFmVUxLOUEwNXAxOXkrdURPM204bVhRNkxVQ0N1STFwZHNROGFlNS9zamlxa0VjWlJjMTdWYVgxWjVVaQpvcGZnNW9SY05VTG9VTHNiek9aNTR0YlVDUmdSV2VLbGZxaElINEZ6OUlkVlUyR3dFdEdhMmV6TjgyMVBaQ3QzCjZhbVRIelJsQWdNQkFBRUNnZ0VBWTFGTUlLNDVXTkVNUHJ6RTZUY3NNdVV2RkdhQVZ4bVk5NW5SMEtwajdvb3IKY21CVys2ZXN0TTQ4S1AwaitPbXd3VFpMY29Cd3VoWGN0V1Bob1lXcDhteWUxRUlEdjNyaHRHMDdocEQ1NGg2dgpCZzh3ejdFYStzMk9sT0N6UnlKNzBSY281YlhjWDNGaGJjdnFlRWJwaFFyQnpOSEtLMjZ4cmZqNWZIT3p6T1FGCmJHdUZ3SDVic3JGdFhlajJXM3c4eW90N0ZQSDV3S3RpdnhvSWU5RjMyOXNnOU9EQnZqWnpiaG1LVTArckFTK1kKRGVield2bFJyaEUrbXVmQTN6M0N0QXhDOFJpNzNscFNoTDRQQWlvcG1SUXlxZXRXMjYzOFFxcnM0R3hnNzhwbApJUXJXTmNBc2s3Slg5d3RZenV6UFBXSXRWTTFscFJiQVRhNTJqdFl2NVFLQmdRRE5tMTFtZTRYam1ZSFV2cStZCmFTUzdwK2UybXZEMHVaOU9JeFluQnBWMGkrckNlYnFFMkE1Rm5hcDQ5Yld4QTgwUElldlVkeUpCL2pUUkoxcVMKRUpXQkpMWm1LVkg2K1QwdWw1ZUtOcWxFTFZHU0dCSXNpeE9SUXpDZHBoMkx0UmtBMHVjSVUzY3hiUmVMZkZCRQpiSkdZWENCdlNGcWd0VDlvZTFldVpMVmFOd0tCZ1FERWdENzJENk81eGIweEQ1NDQ1M0RPMUJhZmd6aThCWDRTCk1SaVd2LzFUQ0w5N05sRWtoeXovNmtQd1owbXJRcE5CMzZFdkpKZFVteHdkU2MyWDhrOGcxMC85NVlLQkdWQWoKL3d0YVZYbE9WeEFvK0ZSelpZeFpyQ29uWWFSMHVwUzFybDRtenN4REhlZU9mUVZUTUgwUjdZN0pnbTA5dXQ4SwplanAvSXZBb1F3S0JnQjNaRWlRUWhvMVYrWjBTMlpiOG5KS0plMy9zMmxJTXFHM0ZkaS9RS3Q0eWViQWx6OGY5ClBZVXBzRmZEQTg5Z3grSU1nSm5sZVptdTk2ZnRXSjZmdmJSenllN216TG5zZU05TXZua1lHbGFGWmJRWnZubXMKN3ZoRmtzY3dHRlh4d21GMlBJZmU1Z3pNMDRBeVdjeTFIaVhLS2dNOXM3cGsxWUdyZGowZzdacmRBb0dCQUtLNApDR3MrbkRmMEZTMFJYOWFEWVJrRTdBNy9YUFhtSG5YMkRnU1h5N0Q4NTRPaWdTTWNoUmtPNTErbVNJejNQbllvCk41T1FXM2lHVVl1M1YvYmhnc0VSUzM1V2xmRk9BdDBzRUR5bjF5SVdXcDF5dG93d3BUNkVvUXVuZ2NYZjA5RjMKS1NROXowd3M4VmsvRWkvSFVXcU5LOWFXbU51cmFaT0ZqL2REK1ZkOUFvR0FMWFN3dEE3K043RDRkN0VEMURSRQpHTWdZNVd3OHFvdDZSdUNlNkpUY0FnU3B1MkhNU3JVY2dXclpiQnJZb09FUnVNQjFoMVJydk5ybU1qQlM0VW9FClgyZC8vbGhpOG1wL2VESWN3UDNRa2puanBJRFJWMFN1eWxrUkVaZURKZjVZb3R6eDdFdkJhbzFIbkQrWEg4eUIKVUtmWGJTaHZKVUdhRmgxT3Q1Y3JoM1k9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNxRENDQVpBQ0NRREVNZ1lZblFyQ29EQU5CZ2txaGtpRzl3MEJBUXNGQURBV01SUXdFZ1lEVlFRRERBdG0KYjI4dVltRnlMbU52YlRBZUZ3MHlNekF4TURVeE16UXpNalJhRncweU5EQXhNRFV4TXpRek1qUmFNQll4RkRBUwpCZ05WQkFNTUMyWnZieTVpWVhJdVkyOXRNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDCkFRRUFuZEh6d21wS2NUSUViamhGZ2RXd1RSTjc1Y3A4b3VsWnhMMUdydlI2SXc3ejdqaTBSNFcvTm85bkdmOU0KWVAyQ1JqaXN6NTFtd3hTeGVCcm9jTGVBK21reGkxK2lEdk5kQytyU0x4MTN6RUxTQ25xYnVzUHM3bUdmSlpxOAo5TGhlbmx5bzQzaDVjYTZINUxqTXd1L1JHVWlGMzFYck5yaVlGQlB2RTJyQitkd24vTkVrUTRoOFJxcXlwcmtuCkYvcWM5Sk1ZQVlGRld1VkNwa0lFbmRYMUN5dlFOT2FkZmN2cmd6dDV2SmwwT2kxQWdyaU5hWGJFUEdudWY3STQKcXBCSEdVWE5lMVdsOVdlVklxS1g0T2FFWERWQzZGQzdHOHptZWVMVzFBa1lFVm5pcFg2b1NCK0JjL1NIVlZOaApzQkxSbXRuc3pmTnRUMlFyZCttcGt4ODBaUUlEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ1VKOElDCkJveUVqT3V3enBHYVJoR044QjRqT1B6aHVDT0V0ZDM3UzAybHUwN09IenlCdmJzVEd6S3dCZ0x5bVdmR2tINEIKajdDTHNwOEZ6TkhLWnVhQmdwblo5SjZETE9Od2ZXZTJBWXA3TGRmT0tWQlVkTVhRaU9tN2pKOUhob0Ntdk1ONwpic2pjaFdKb013ckZmK3dkQUthdHowcUFQeWhMeWUvRnFtaVZ4a09SWmF3K1Q5bURaK0g0OXVBU2d1SnVOTXlRClY2RXlYNmd0Z1dxMzc2SHZhWE1TLzNoYW1Zb1ZXWEk1TXhpUE9ZeG5BQmtKQjRTQ2dJUmVqYkpmVmFRdG9RNGEKejAyaVVMZW5ESUllUU9Zb2JLY01CWGYxQjRQQVFtc2VocVZJYnpzUUNHaTU0VkRyczZiWmQvN0pzMXpDcHBncwpKaUQ1SXFNaktXRHdxN2FLCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-tls-secret-in-other-namespace-allowed-by-refgrant.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-tls-secret-in-other-namespace-allowed-by-refgrant.out.yaml index 7165c0b5780..f72ccd5db18 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-tls-secret-in-other-namespace-allowed-by-refgrant.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-tls-secret-in-other-namespace-allowed-by-refgrant.out.yaml @@ -133,6 +133,6 @@ xdsIR: prefix: / tls: certificates: - - name: default-tls-secret-1 + - name: default/tls-secret-1 privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2QwZlBDYWtweE1nUnUKT0VXQjFiQk5FM3ZseW55aTZWbkV2VWF1OUhvakR2UHVPTFJIaGI4MmoyY1ovMHhnL1lKR09LelBuV2JERkxGNApHdWh3dDRENmFUR0xYNklPODEwTDZ0SXZIWGZNUXRJS2VwdTZ3K3p1WVo4bG1yejB1RjZlWEtqamVIbHhyb2ZrCnVNekM3OUVaU0lYZlZlczJ1SmdVRSs4VGFzSDUzQ2Y4MFNSRGlIeEdxckttdVNjWCtwejBreGdCZ1VWYTVVS20KUWdTZDFmVUxLOUEwNXAxOXkrdURPM204bVhRNkxVQ0N1STFwZHNROGFlNS9zamlxa0VjWlJjMTdWYVgxWjVVaQpvcGZnNW9SY05VTG9VTHNiek9aNTR0YlVDUmdSV2VLbGZxaElINEZ6OUlkVlUyR3dFdEdhMmV6TjgyMVBaQ3QzCjZhbVRIelJsQWdNQkFBRUNnZ0VBWTFGTUlLNDVXTkVNUHJ6RTZUY3NNdVV2RkdhQVZ4bVk5NW5SMEtwajdvb3IKY21CVys2ZXN0TTQ4S1AwaitPbXd3VFpMY29Cd3VoWGN0V1Bob1lXcDhteWUxRUlEdjNyaHRHMDdocEQ1NGg2dgpCZzh3ejdFYStzMk9sT0N6UnlKNzBSY281YlhjWDNGaGJjdnFlRWJwaFFyQnpOSEtLMjZ4cmZqNWZIT3p6T1FGCmJHdUZ3SDVic3JGdFhlajJXM3c4eW90N0ZQSDV3S3RpdnhvSWU5RjMyOXNnOU9EQnZqWnpiaG1LVTArckFTK1kKRGVield2bFJyaEUrbXVmQTN6M0N0QXhDOFJpNzNscFNoTDRQQWlvcG1SUXlxZXRXMjYzOFFxcnM0R3hnNzhwbApJUXJXTmNBc2s3Slg5d3RZenV6UFBXSXRWTTFscFJiQVRhNTJqdFl2NVFLQmdRRE5tMTFtZTRYam1ZSFV2cStZCmFTUzdwK2UybXZEMHVaOU9JeFluQnBWMGkrckNlYnFFMkE1Rm5hcDQ5Yld4QTgwUElldlVkeUpCL2pUUkoxcVMKRUpXQkpMWm1LVkg2K1QwdWw1ZUtOcWxFTFZHU0dCSXNpeE9SUXpDZHBoMkx0UmtBMHVjSVUzY3hiUmVMZkZCRQpiSkdZWENCdlNGcWd0VDlvZTFldVpMVmFOd0tCZ1FERWdENzJENk81eGIweEQ1NDQ1M0RPMUJhZmd6aThCWDRTCk1SaVd2LzFUQ0w5N05sRWtoeXovNmtQd1owbXJRcE5CMzZFdkpKZFVteHdkU2MyWDhrOGcxMC85NVlLQkdWQWoKL3d0YVZYbE9WeEFvK0ZSelpZeFpyQ29uWWFSMHVwUzFybDRtenN4REhlZU9mUVZUTUgwUjdZN0pnbTA5dXQ4SwplanAvSXZBb1F3S0JnQjNaRWlRUWhvMVYrWjBTMlpiOG5KS0plMy9zMmxJTXFHM0ZkaS9RS3Q0eWViQWx6OGY5ClBZVXBzRmZEQTg5Z3grSU1nSm5sZVptdTk2ZnRXSjZmdmJSenllN216TG5zZU05TXZua1lHbGFGWmJRWnZubXMKN3ZoRmtzY3dHRlh4d21GMlBJZmU1Z3pNMDRBeVdjeTFIaVhLS2dNOXM3cGsxWUdyZGowZzdacmRBb0dCQUtLNApDR3MrbkRmMEZTMFJYOWFEWVJrRTdBNy9YUFhtSG5YMkRnU1h5N0Q4NTRPaWdTTWNoUmtPNTErbVNJejNQbllvCk41T1FXM2lHVVl1M1YvYmhnc0VSUzM1V2xmRk9BdDBzRUR5bjF5SVdXcDF5dG93d3BUNkVvUXVuZ2NYZjA5RjMKS1NROXowd3M4VmsvRWkvSFVXcU5LOWFXbU51cmFaT0ZqL2REK1ZkOUFvR0FMWFN3dEE3K043RDRkN0VEMURSRQpHTWdZNVd3OHFvdDZSdUNlNkpUY0FnU3B1MkhNU3JVY2dXclpiQnJZb09FUnVNQjFoMVJydk5ybU1qQlM0VW9FClgyZC8vbGhpOG1wL2VESWN3UDNRa2puanBJRFJWMFN1eWxrUkVaZURKZjVZb3R6eDdFdkJhbzFIbkQrWEg4eUIKVUtmWGJTaHZKVUdhRmgxT3Q1Y3JoM1k9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNxRENDQVpBQ0NRREVNZ1lZblFyQ29EQU5CZ2txaGtpRzl3MEJBUXNGQURBV01SUXdFZ1lEVlFRRERBdG0KYjI4dVltRnlMbU52YlRBZUZ3MHlNekF4TURVeE16UXpNalJhRncweU5EQXhNRFV4TXpRek1qUmFNQll4RkRBUwpCZ05WQkFNTUMyWnZieTVpWVhJdVkyOXRNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDCkFRRUFuZEh6d21wS2NUSUViamhGZ2RXd1RSTjc1Y3A4b3VsWnhMMUdydlI2SXc3ejdqaTBSNFcvTm85bkdmOU0KWVAyQ1JqaXN6NTFtd3hTeGVCcm9jTGVBK21reGkxK2lEdk5kQytyU0x4MTN6RUxTQ25xYnVzUHM3bUdmSlpxOAo5TGhlbmx5bzQzaDVjYTZINUxqTXd1L1JHVWlGMzFYck5yaVlGQlB2RTJyQitkd24vTkVrUTRoOFJxcXlwcmtuCkYvcWM5Sk1ZQVlGRld1VkNwa0lFbmRYMUN5dlFOT2FkZmN2cmd6dDV2SmwwT2kxQWdyaU5hWGJFUEdudWY3STQKcXBCSEdVWE5lMVdsOVdlVklxS1g0T2FFWERWQzZGQzdHOHptZWVMVzFBa1lFVm5pcFg2b1NCK0JjL1NIVlZOaApzQkxSbXRuc3pmTnRUMlFyZCttcGt4ODBaUUlEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ1VKOElDCkJveUVqT3V3enBHYVJoR044QjRqT1B6aHVDT0V0ZDM3UzAybHUwN09IenlCdmJzVEd6S3dCZ0x5bVdmR2tINEIKajdDTHNwOEZ6TkhLWnVhQmdwblo5SjZETE9Od2ZXZTJBWXA3TGRmT0tWQlVkTVhRaU9tN2pKOUhob0Ntdk1ONwpic2pjaFdKb013ckZmK3dkQUthdHowcUFQeWhMeWUvRnFtaVZ4a09SWmF3K1Q5bURaK0g0OXVBU2d1SnVOTXlRClY2RXlYNmd0Z1dxMzc2SHZhWE1TLzNoYW1Zb1ZXWEk1TXhpUE9ZeG5BQmtKQjRTQ2dJUmVqYkpmVmFRdG9RNGEKejAyaVVMZW5ESUllUU9Zb2JLY01CWGYxQjRQQVFtc2VocVZJYnpzUUNHaTU0VkRyczZiWmQvN0pzMXpDcHBncwpKaUQ1SXFNaktXRHdxN2FLCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-tls-terminate-and-passthrough.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-tls-terminate-and-passthrough.out.yaml index 03bff1ce9d8..e8683486282 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-tls-terminate-and-passthrough.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-tls-terminate-and-passthrough.out.yaml @@ -202,7 +202,7 @@ xdsIR: prefix: / tls: certificates: - - name: envoy-gateway-tls-secret-1 + - name: envoy-gateway/tls-secret-1 privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2QwZlBDYWtweE1nUnUKT0VXQjFiQk5FM3ZseW55aTZWbkV2VWF1OUhvakR2UHVPTFJIaGI4MmoyY1ovMHhnL1lKR09LelBuV2JERkxGNApHdWh3dDRENmFUR0xYNklPODEwTDZ0SXZIWGZNUXRJS2VwdTZ3K3p1WVo4bG1yejB1RjZlWEtqamVIbHhyb2ZrCnVNekM3OUVaU0lYZlZlczJ1SmdVRSs4VGFzSDUzQ2Y4MFNSRGlIeEdxckttdVNjWCtwejBreGdCZ1VWYTVVS20KUWdTZDFmVUxLOUEwNXAxOXkrdURPM204bVhRNkxVQ0N1STFwZHNROGFlNS9zamlxa0VjWlJjMTdWYVgxWjVVaQpvcGZnNW9SY05VTG9VTHNiek9aNTR0YlVDUmdSV2VLbGZxaElINEZ6OUlkVlUyR3dFdEdhMmV6TjgyMVBaQ3QzCjZhbVRIelJsQWdNQkFBRUNnZ0VBWTFGTUlLNDVXTkVNUHJ6RTZUY3NNdVV2RkdhQVZ4bVk5NW5SMEtwajdvb3IKY21CVys2ZXN0TTQ4S1AwaitPbXd3VFpMY29Cd3VoWGN0V1Bob1lXcDhteWUxRUlEdjNyaHRHMDdocEQ1NGg2dgpCZzh3ejdFYStzMk9sT0N6UnlKNzBSY281YlhjWDNGaGJjdnFlRWJwaFFyQnpOSEtLMjZ4cmZqNWZIT3p6T1FGCmJHdUZ3SDVic3JGdFhlajJXM3c4eW90N0ZQSDV3S3RpdnhvSWU5RjMyOXNnOU9EQnZqWnpiaG1LVTArckFTK1kKRGVield2bFJyaEUrbXVmQTN6M0N0QXhDOFJpNzNscFNoTDRQQWlvcG1SUXlxZXRXMjYzOFFxcnM0R3hnNzhwbApJUXJXTmNBc2s3Slg5d3RZenV6UFBXSXRWTTFscFJiQVRhNTJqdFl2NVFLQmdRRE5tMTFtZTRYam1ZSFV2cStZCmFTUzdwK2UybXZEMHVaOU9JeFluQnBWMGkrckNlYnFFMkE1Rm5hcDQ5Yld4QTgwUElldlVkeUpCL2pUUkoxcVMKRUpXQkpMWm1LVkg2K1QwdWw1ZUtOcWxFTFZHU0dCSXNpeE9SUXpDZHBoMkx0UmtBMHVjSVUzY3hiUmVMZkZCRQpiSkdZWENCdlNGcWd0VDlvZTFldVpMVmFOd0tCZ1FERWdENzJENk81eGIweEQ1NDQ1M0RPMUJhZmd6aThCWDRTCk1SaVd2LzFUQ0w5N05sRWtoeXovNmtQd1owbXJRcE5CMzZFdkpKZFVteHdkU2MyWDhrOGcxMC85NVlLQkdWQWoKL3d0YVZYbE9WeEFvK0ZSelpZeFpyQ29uWWFSMHVwUzFybDRtenN4REhlZU9mUVZUTUgwUjdZN0pnbTA5dXQ4SwplanAvSXZBb1F3S0JnQjNaRWlRUWhvMVYrWjBTMlpiOG5KS0plMy9zMmxJTXFHM0ZkaS9RS3Q0eWViQWx6OGY5ClBZVXBzRmZEQTg5Z3grSU1nSm5sZVptdTk2ZnRXSjZmdmJSenllN216TG5zZU05TXZua1lHbGFGWmJRWnZubXMKN3ZoRmtzY3dHRlh4d21GMlBJZmU1Z3pNMDRBeVdjeTFIaVhLS2dNOXM3cGsxWUdyZGowZzdacmRBb0dCQUtLNApDR3MrbkRmMEZTMFJYOWFEWVJrRTdBNy9YUFhtSG5YMkRnU1h5N0Q4NTRPaWdTTWNoUmtPNTErbVNJejNQbllvCk41T1FXM2lHVVl1M1YvYmhnc0VSUzM1V2xmRk9BdDBzRUR5bjF5SVdXcDF5dG93d3BUNkVvUXVuZ2NYZjA5RjMKS1NROXowd3M4VmsvRWkvSFVXcU5LOWFXbU51cmFaT0ZqL2REK1ZkOUFvR0FMWFN3dEE3K043RDRkN0VEMURSRQpHTWdZNVd3OHFvdDZSdUNlNkpUY0FnU3B1MkhNU3JVY2dXclpiQnJZb09FUnVNQjFoMVJydk5ybU1qQlM0VW9FClgyZC8vbGhpOG1wL2VESWN3UDNRa2puanBJRFJWMFN1eWxrUkVaZURKZjVZb3R6eDdFdkJhbzFIbkQrWEg4eUIKVUtmWGJTaHZKVUdhRmgxT3Q1Y3JoM1k9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNxRENDQVpBQ0NRREVNZ1lZblFyQ29EQU5CZ2txaGtpRzl3MEJBUXNGQURBV01SUXdFZ1lEVlFRRERBdG0KYjI4dVltRnlMbU52YlRBZUZ3MHlNekF4TURVeE16UXpNalJhRncweU5EQXhNRFV4TXpRek1qUmFNQll4RkRBUwpCZ05WQkFNTUMyWnZieTVpWVhJdVkyOXRNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDCkFRRUFuZEh6d21wS2NUSUViamhGZ2RXd1RSTjc1Y3A4b3VsWnhMMUdydlI2SXc3ejdqaTBSNFcvTm85bkdmOU0KWVAyQ1JqaXN6NTFtd3hTeGVCcm9jTGVBK21reGkxK2lEdk5kQytyU0x4MTN6RUxTQ25xYnVzUHM3bUdmSlpxOAo5TGhlbmx5bzQzaDVjYTZINUxqTXd1L1JHVWlGMzFYck5yaVlGQlB2RTJyQitkd24vTkVrUTRoOFJxcXlwcmtuCkYvcWM5Sk1ZQVlGRld1VkNwa0lFbmRYMUN5dlFOT2FkZmN2cmd6dDV2SmwwT2kxQWdyaU5hWGJFUEdudWY3STQKcXBCSEdVWE5lMVdsOVdlVklxS1g0T2FFWERWQzZGQzdHOHptZWVMVzFBa1lFVm5pcFg2b1NCK0JjL1NIVlZOaApzQkxSbXRuc3pmTnRUMlFyZCttcGt4ODBaUUlEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ1VKOElDCkJveUVqT3V3enBHYVJoR044QjRqT1B6aHVDT0V0ZDM3UzAybHUwN09IenlCdmJzVEd6S3dCZ0x5bVdmR2tINEIKajdDTHNwOEZ6TkhLWnVhQmdwblo5SjZETE9Od2ZXZTJBWXA3TGRmT0tWQlVkTVhRaU9tN2pKOUhob0Ntdk1ONwpic2pjaFdKb013ckZmK3dkQUthdHowcUFQeWhMeWUvRnFtaVZ4a09SWmF3K1Q5bURaK0g0OXVBU2d1SnVOTXlRClY2RXlYNmd0Z1dxMzc2SHZhWE1TLzNoYW1Zb1ZXWEk1TXhpUE9ZeG5BQmtKQjRTQ2dJUmVqYkpmVmFRdG9RNGEKejAyaVVMZW5ESUllUU9Zb2JLY01CWGYxQjRQQVFtc2VocVZJYnpzUUNHaTU0VkRyczZiWmQvN0pzMXpDcHBncwpKaUQ1SXFNaktXRHdxN2FLCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K tcp: diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration-with-same-algorithm-different-fqdn.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration-with-same-algorithm-different-fqdn.out.yaml index 4ed7fc048bf..e2cd9a173fe 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration-with-same-algorithm-different-fqdn.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration-with-same-algorithm-different-fqdn.out.yaml @@ -135,9 +135,9 @@ xdsIR: prefix: / tls: certificates: - - name: envoy-gateway-tls-secret-ecdsa-1 + - name: envoy-gateway/tls-secret-ecdsa-1 privateKey: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUxEbnZNM1RKM3NHYm9EeTF4T3dqSVppVFNWeWZXVWF5YVExcWdrdUdacEtvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFSDVWdHJjenJQS091alV5RTMyaDU2UnVrdHUzSVhTVnJJMkNibXh5UUpqcEY3di9rNVNqTQpSVXZjUnBCdmpnQWROaGhUNGNUMXV4YW1TMFlmQ2JXMVhRPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo= serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJHekNCd2dJSkFJL3gxc0NEL0lSa01Bb0dDQ3FHU000OUJBTUNNQll4RkRBU0JnTlZCQU1NQzJadmJ5NWkKWVhJdVkyOXRNQjRYRFRJek1ERXdOVEl4TlRNeU9Wb1hEVEkwTURFd05USXhOVE15T1Zvd0ZqRVVNQklHQTFVRQpBd3dMWm05dkxtSmhjaTVqYjIwd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFRZmxXMnR6T3M4Cm82Nk5USVRmYUhucEc2UzI3Y2hkSldzallKdWJISkFtT2tYdS8rVGxLTXhGUzl4R2tHK09BQjAyR0ZQaHhQVzcKRnFaTFJoOEp0YlZkTUFvR0NDcUdTTTQ5QkFNQ0EwZ0FNRVVDSVFEdlplU1pBZ1VWV2VpM3o0ZEhOTEd0aHpiaQoxRHZ0anRQekhYZ1R3WS92YmdJZ05KWStNcTRweFJnNit3eU04R1R4czVUV3k5Zml5RGhMUEU5QnhlbEsxSjQ9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K - - name: envoy-gateway-tls-secret-ecdsa-2 + - name: envoy-gateway/tls-secret-ecdsa-2 privateKey: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1JR2tBZ0VCQkRDUUE5VWo0SkR5c0Q0MlJIMGI2cjU5NTlXTmlXU2ZKZlMxK2RvTjk0TzZCUGdaQUJiUTI4eTIKUTZsM3pZdklLeFNnQndZRks0RUVBQ0toWkFOaUFBUjR5MGNMZUVoNnJaQ3gyUzFLTDlrMUg4d28xcTlLYmNjMgpmdTBhaUIrcHFxZndCS0FjaHJ2SlJUNzQreWdNUHFSLzc0Sjd1NngzU1pBN1ZLZDFnaGFQWkF1SWpQUTFrZndICjlDdmlMc25RZ3JDeENWU2U2ZG1xL2twajFNdEJyU2M9Ci0tLS0tRU5EIEVDIFBSSVZBVEUgS0VZLS0tLS0K serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJZakNCNlFJSkFNcDhYTGNsWGJ2NU1Bb0dDQ3FHU000OUJBTUNNQnN4R1RBWEJnTlZCQU1NRUhSbGMzUXUKWlhoaGJYQnNaUzVqYjIwd0hoY05Nak13TlRJMU1UUXhNRFF5V2hjTk1qUXdOVEkwTVRReE1EUXlXakFiTVJrdwpGd1lEVlFRRERCQjBaWE4wTG1WNFlXMXdiR1V1WTI5dE1IWXdFQVlIS29aSXpqMENBUVlGSzRFRUFDSURZZ0FFCmVNdEhDM2hJZXEyUXNka3RTaS9aTlIvTUtOYXZTbTNITm43dEdvZ2ZxYXFuOEFTZ0hJYTd5VVUrK1Bzb0RENmsKZisrQ2U3dXNkMG1RTzFTbmRZSVdqMlFMaUl6ME5aSDhCL1FyNGk3SjBJS3dzUWxVbnVuWnF2NUtZOVRMUWEwbgpNQW9HQ0NxR1NNNDlCQU1DQTJnQU1HVUNNUUNHVGpQa2hqZE1KcWUrVjFGRWpteUk2andEV0FDalhucFRuaXhVCnM2dUNKZjVNNUw1TmpGYmkydGplMGlES0UxVUNNQXdxSjZmOUs2bUhUd2JxVGkzTVNFMmQxODl6aUcyWVZCaUQKYmVXcHc0UjF5ZTdHRFJvVm9veG9ob2lERjdsNm13PT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration.out.yaml index c8df40b5660..741785be4b6 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration.out.yaml @@ -135,9 +135,9 @@ xdsIR: prefix: / tls: certificates: - - name: envoy-gateway-tls-secret-1 + - name: envoy-gateway/tls-secret-1 privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2QwZlBDYWtweE1nUnUKT0VXQjFiQk5FM3ZseW55aTZWbkV2VWF1OUhvakR2UHVPTFJIaGI4MmoyY1ovMHhnL1lKR09LelBuV2JERkxGNApHdWh3dDRENmFUR0xYNklPODEwTDZ0SXZIWGZNUXRJS2VwdTZ3K3p1WVo4bG1yejB1RjZlWEtqamVIbHhyb2ZrCnVNekM3OUVaU0lYZlZlczJ1SmdVRSs4VGFzSDUzQ2Y4MFNSRGlIeEdxckttdVNjWCtwejBreGdCZ1VWYTVVS20KUWdTZDFmVUxLOUEwNXAxOXkrdURPM204bVhRNkxVQ0N1STFwZHNROGFlNS9zamlxa0VjWlJjMTdWYVgxWjVVaQpvcGZnNW9SY05VTG9VTHNiek9aNTR0YlVDUmdSV2VLbGZxaElINEZ6OUlkVlUyR3dFdEdhMmV6TjgyMVBaQ3QzCjZhbVRIelJsQWdNQkFBRUNnZ0VBWTFGTUlLNDVXTkVNUHJ6RTZUY3NNdVV2RkdhQVZ4bVk5NW5SMEtwajdvb3IKY21CVys2ZXN0TTQ4S1AwaitPbXd3VFpMY29Cd3VoWGN0V1Bob1lXcDhteWUxRUlEdjNyaHRHMDdocEQ1NGg2dgpCZzh3ejdFYStzMk9sT0N6UnlKNzBSY281YlhjWDNGaGJjdnFlRWJwaFFyQnpOSEtLMjZ4cmZqNWZIT3p6T1FGCmJHdUZ3SDVic3JGdFhlajJXM3c4eW90N0ZQSDV3S3RpdnhvSWU5RjMyOXNnOU9EQnZqWnpiaG1LVTArckFTK1kKRGVield2bFJyaEUrbXVmQTN6M0N0QXhDOFJpNzNscFNoTDRQQWlvcG1SUXlxZXRXMjYzOFFxcnM0R3hnNzhwbApJUXJXTmNBc2s3Slg5d3RZenV6UFBXSXRWTTFscFJiQVRhNTJqdFl2NVFLQmdRRE5tMTFtZTRYam1ZSFV2cStZCmFTUzdwK2UybXZEMHVaOU9JeFluQnBWMGkrckNlYnFFMkE1Rm5hcDQ5Yld4QTgwUElldlVkeUpCL2pUUkoxcVMKRUpXQkpMWm1LVkg2K1QwdWw1ZUtOcWxFTFZHU0dCSXNpeE9SUXpDZHBoMkx0UmtBMHVjSVUzY3hiUmVMZkZCRQpiSkdZWENCdlNGcWd0VDlvZTFldVpMVmFOd0tCZ1FERWdENzJENk81eGIweEQ1NDQ1M0RPMUJhZmd6aThCWDRTCk1SaVd2LzFUQ0w5N05sRWtoeXovNmtQd1owbXJRcE5CMzZFdkpKZFVteHdkU2MyWDhrOGcxMC85NVlLQkdWQWoKL3d0YVZYbE9WeEFvK0ZSelpZeFpyQ29uWWFSMHVwUzFybDRtenN4REhlZU9mUVZUTUgwUjdZN0pnbTA5dXQ4SwplanAvSXZBb1F3S0JnQjNaRWlRUWhvMVYrWjBTMlpiOG5KS0plMy9zMmxJTXFHM0ZkaS9RS3Q0eWViQWx6OGY5ClBZVXBzRmZEQTg5Z3grSU1nSm5sZVptdTk2ZnRXSjZmdmJSenllN216TG5zZU05TXZua1lHbGFGWmJRWnZubXMKN3ZoRmtzY3dHRlh4d21GMlBJZmU1Z3pNMDRBeVdjeTFIaVhLS2dNOXM3cGsxWUdyZGowZzdacmRBb0dCQUtLNApDR3MrbkRmMEZTMFJYOWFEWVJrRTdBNy9YUFhtSG5YMkRnU1h5N0Q4NTRPaWdTTWNoUmtPNTErbVNJejNQbllvCk41T1FXM2lHVVl1M1YvYmhnc0VSUzM1V2xmRk9BdDBzRUR5bjF5SVdXcDF5dG93d3BUNkVvUXVuZ2NYZjA5RjMKS1NROXowd3M4VmsvRWkvSFVXcU5LOWFXbU51cmFaT0ZqL2REK1ZkOUFvR0FMWFN3dEE3K043RDRkN0VEMURSRQpHTWdZNVd3OHFvdDZSdUNlNkpUY0FnU3B1MkhNU3JVY2dXclpiQnJZb09FUnVNQjFoMVJydk5ybU1qQlM0VW9FClgyZC8vbGhpOG1wL2VESWN3UDNRa2puanBJRFJWMFN1eWxrUkVaZURKZjVZb3R6eDdFdkJhbzFIbkQrWEg4eUIKVUtmWGJTaHZKVUdhRmgxT3Q1Y3JoM1k9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNxRENDQVpBQ0NRREVNZ1lZblFyQ29EQU5CZ2txaGtpRzl3MEJBUXNGQURBV01SUXdFZ1lEVlFRRERBdG0KYjI4dVltRnlMbU52YlRBZUZ3MHlNekF4TURVeE16UXpNalJhRncweU5EQXhNRFV4TXpRek1qUmFNQll4RkRBUwpCZ05WQkFNTUMyWnZieTVpWVhJdVkyOXRNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDCkFRRUFuZEh6d21wS2NUSUViamhGZ2RXd1RSTjc1Y3A4b3VsWnhMMUdydlI2SXc3ejdqaTBSNFcvTm85bkdmOU0KWVAyQ1JqaXN6NTFtd3hTeGVCcm9jTGVBK21reGkxK2lEdk5kQytyU0x4MTN6RUxTQ25xYnVzUHM3bUdmSlpxOAo5TGhlbmx5bzQzaDVjYTZINUxqTXd1L1JHVWlGMzFYck5yaVlGQlB2RTJyQitkd24vTkVrUTRoOFJxcXlwcmtuCkYvcWM5Sk1ZQVlGRld1VkNwa0lFbmRYMUN5dlFOT2FkZmN2cmd6dDV2SmwwT2kxQWdyaU5hWGJFUEdudWY3STQKcXBCSEdVWE5lMVdsOVdlVklxS1g0T2FFWERWQzZGQzdHOHptZWVMVzFBa1lFVm5pcFg2b1NCK0JjL1NIVlZOaApzQkxSbXRuc3pmTnRUMlFyZCttcGt4ODBaUUlEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ1VKOElDCkJveUVqT3V3enBHYVJoR044QjRqT1B6aHVDT0V0ZDM3UzAybHUwN09IenlCdmJzVEd6S3dCZ0x5bVdmR2tINEIKajdDTHNwOEZ6TkhLWnVhQmdwblo5SjZETE9Od2ZXZTJBWXA3TGRmT0tWQlVkTVhRaU9tN2pKOUhob0Ntdk1ONwpic2pjaFdKb013ckZmK3dkQUthdHowcUFQeWhMeWUvRnFtaVZ4a09SWmF3K1Q5bURaK0g0OXVBU2d1SnVOTXlRClY2RXlYNmd0Z1dxMzc2SHZhWE1TLzNoYW1Zb1ZXWEk1TXhpUE9ZeG5BQmtKQjRTQ2dJUmVqYkpmVmFRdG9RNGEKejAyaVVMZW5ESUllUU9Zb2JLY01CWGYxQjRQQVFtc2VocVZJYnpzUUNHaTU0VkRyczZiWmQvN0pzMXpDcHBncwpKaUQ1SXFNaktXRHdxN2FLCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K - - name: envoy-gateway-tls-secret-ecdsa-1 + - name: envoy-gateway/tls-secret-ecdsa-1 privateKey: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUxEbnZNM1RKM3NHYm9EeTF4T3dqSVppVFNWeWZXVWF5YVExcWdrdUdacEtvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFSDVWdHJjenJQS091alV5RTMyaDU2UnVrdHUzSVhTVnJJMkNibXh5UUpqcEY3di9rNVNqTQpSVXZjUnBCdmpnQWROaGhUNGNUMXV4YW1TMFlmQ2JXMVhRPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo= serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJHekNCd2dJSkFJL3gxc0NEL0lSa01Bb0dDQ3FHU000OUJBTUNNQll4RkRBU0JnTlZCQU1NQzJadmJ5NWkKWVhJdVkyOXRNQjRYRFRJek1ERXdOVEl4TlRNeU9Wb1hEVEkwTURFd05USXhOVE15T1Zvd0ZqRVVNQklHQTFVRQpBd3dMWm05dkxtSmhjaTVqYjIwd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFRZmxXMnR6T3M4Cm82Nk5USVRmYUhucEc2UzI3Y2hkSldzallKdWJISkFtT2tYdS8rVGxLTXhGUzl4R2tHK09BQjAyR0ZQaHhQVzcKRnFaTFJoOEp0YlZkTUFvR0NDcUdTTTQ5QkFNQ0EwZ0FNRVVDSVFEdlplU1pBZ1VWV2VpM3o0ZEhOTEd0aHpiaQoxRHZ0anRQekhYZ1R3WS92YmdJZ05KWStNcTRweFJnNit3eU04R1R4czVUV3k5Zml5RGhMUEU5QnhlbEsxSjQ9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-valid-tls-configuration.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-valid-tls-configuration.out.yaml index 3bfd5c50811..bc02d7f9543 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-valid-tls-configuration.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-valid-tls-configuration.out.yaml @@ -132,6 +132,6 @@ xdsIR: prefix: / tls: certificates: - - name: envoy-gateway-tls-secret-1 + - name: envoy-gateway/tls-secret-1 privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2QwZlBDYWtweE1nUnUKT0VXQjFiQk5FM3ZseW55aTZWbkV2VWF1OUhvakR2UHVPTFJIaGI4MmoyY1ovMHhnL1lKR09LelBuV2JERkxGNApHdWh3dDRENmFUR0xYNklPODEwTDZ0SXZIWGZNUXRJS2VwdTZ3K3p1WVo4bG1yejB1RjZlWEtqamVIbHhyb2ZrCnVNekM3OUVaU0lYZlZlczJ1SmdVRSs4VGFzSDUzQ2Y4MFNSRGlIeEdxckttdVNjWCtwejBreGdCZ1VWYTVVS20KUWdTZDFmVUxLOUEwNXAxOXkrdURPM204bVhRNkxVQ0N1STFwZHNROGFlNS9zamlxa0VjWlJjMTdWYVgxWjVVaQpvcGZnNW9SY05VTG9VTHNiek9aNTR0YlVDUmdSV2VLbGZxaElINEZ6OUlkVlUyR3dFdEdhMmV6TjgyMVBaQ3QzCjZhbVRIelJsQWdNQkFBRUNnZ0VBWTFGTUlLNDVXTkVNUHJ6RTZUY3NNdVV2RkdhQVZ4bVk5NW5SMEtwajdvb3IKY21CVys2ZXN0TTQ4S1AwaitPbXd3VFpMY29Cd3VoWGN0V1Bob1lXcDhteWUxRUlEdjNyaHRHMDdocEQ1NGg2dgpCZzh3ejdFYStzMk9sT0N6UnlKNzBSY281YlhjWDNGaGJjdnFlRWJwaFFyQnpOSEtLMjZ4cmZqNWZIT3p6T1FGCmJHdUZ3SDVic3JGdFhlajJXM3c4eW90N0ZQSDV3S3RpdnhvSWU5RjMyOXNnOU9EQnZqWnpiaG1LVTArckFTK1kKRGVield2bFJyaEUrbXVmQTN6M0N0QXhDOFJpNzNscFNoTDRQQWlvcG1SUXlxZXRXMjYzOFFxcnM0R3hnNzhwbApJUXJXTmNBc2s3Slg5d3RZenV6UFBXSXRWTTFscFJiQVRhNTJqdFl2NVFLQmdRRE5tMTFtZTRYam1ZSFV2cStZCmFTUzdwK2UybXZEMHVaOU9JeFluQnBWMGkrckNlYnFFMkE1Rm5hcDQ5Yld4QTgwUElldlVkeUpCL2pUUkoxcVMKRUpXQkpMWm1LVkg2K1QwdWw1ZUtOcWxFTFZHU0dCSXNpeE9SUXpDZHBoMkx0UmtBMHVjSVUzY3hiUmVMZkZCRQpiSkdZWENCdlNGcWd0VDlvZTFldVpMVmFOd0tCZ1FERWdENzJENk81eGIweEQ1NDQ1M0RPMUJhZmd6aThCWDRTCk1SaVd2LzFUQ0w5N05sRWtoeXovNmtQd1owbXJRcE5CMzZFdkpKZFVteHdkU2MyWDhrOGcxMC85NVlLQkdWQWoKL3d0YVZYbE9WeEFvK0ZSelpZeFpyQ29uWWFSMHVwUzFybDRtenN4REhlZU9mUVZUTUgwUjdZN0pnbTA5dXQ4SwplanAvSXZBb1F3S0JnQjNaRWlRUWhvMVYrWjBTMlpiOG5KS0plMy9zMmxJTXFHM0ZkaS9RS3Q0eWViQWx6OGY5ClBZVXBzRmZEQTg5Z3grSU1nSm5sZVptdTk2ZnRXSjZmdmJSenllN216TG5zZU05TXZua1lHbGFGWmJRWnZubXMKN3ZoRmtzY3dHRlh4d21GMlBJZmU1Z3pNMDRBeVdjeTFIaVhLS2dNOXM3cGsxWUdyZGowZzdacmRBb0dCQUtLNApDR3MrbkRmMEZTMFJYOWFEWVJrRTdBNy9YUFhtSG5YMkRnU1h5N0Q4NTRPaWdTTWNoUmtPNTErbVNJejNQbllvCk41T1FXM2lHVVl1M1YvYmhnc0VSUzM1V2xmRk9BdDBzRUR5bjF5SVdXcDF5dG93d3BUNkVvUXVuZ2NYZjA5RjMKS1NROXowd3M4VmsvRWkvSFVXcU5LOWFXbU51cmFaT0ZqL2REK1ZkOUFvR0FMWFN3dEE3K043RDRkN0VEMURSRQpHTWdZNVd3OHFvdDZSdUNlNkpUY0FnU3B1MkhNU3JVY2dXclpiQnJZb09FUnVNQjFoMVJydk5ybU1qQlM0VW9FClgyZC8vbGhpOG1wL2VESWN3UDNRa2puanBJRFJWMFN1eWxrUkVaZURKZjVZb3R6eDdFdkJhbzFIbkQrWEg4eUIKVUtmWGJTaHZKVUdhRmgxT3Q1Y3JoM1k9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNxRENDQVpBQ0NRREVNZ1lZblFyQ29EQU5CZ2txaGtpRzl3MEJBUXNGQURBV01SUXdFZ1lEVlFRRERBdG0KYjI4dVltRnlMbU52YlRBZUZ3MHlNekF4TURVeE16UXpNalJhRncweU5EQXhNRFV4TXpRek1qUmFNQll4RkRBUwpCZ05WQkFNTUMyWnZieTVpWVhJdVkyOXRNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDCkFRRUFuZEh6d21wS2NUSUViamhGZ2RXd1RSTjc1Y3A4b3VsWnhMMUdydlI2SXc3ejdqaTBSNFcvTm85bkdmOU0KWVAyQ1JqaXN6NTFtd3hTeGVCcm9jTGVBK21reGkxK2lEdk5kQytyU0x4MTN6RUxTQ25xYnVzUHM3bUdmSlpxOAo5TGhlbmx5bzQzaDVjYTZINUxqTXd1L1JHVWlGMzFYck5yaVlGQlB2RTJyQitkd24vTkVrUTRoOFJxcXlwcmtuCkYvcWM5Sk1ZQVlGRld1VkNwa0lFbmRYMUN5dlFOT2FkZmN2cmd6dDV2SmwwT2kxQWdyaU5hWGJFUEdudWY3STQKcXBCSEdVWE5lMVdsOVdlVklxS1g0T2FFWERWQzZGQzdHOHptZWVMVzFBa1lFVm5pcFg2b1NCK0JjL1NIVlZOaApzQkxSbXRuc3pmTnRUMlFyZCttcGt4ODBaUUlEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ1VKOElDCkJveUVqT3V3enBHYVJoR044QjRqT1B6aHVDT0V0ZDM3UzAybHUwN09IenlCdmJzVEd6S3dCZ0x5bVdmR2tINEIKajdDTHNwOEZ6TkhLWnVhQmdwblo5SjZETE9Od2ZXZTJBWXA3TGRmT0tWQlVkTVhRaU9tN2pKOUhob0Ntdk1ONwpic2pjaFdKb013ckZmK3dkQUthdHowcUFQeWhMeWUvRnFtaVZ4a09SWmF3K1Q5bURaK0g0OXVBU2d1SnVOTXlRClY2RXlYNmd0Z1dxMzc2SHZhWE1TLzNoYW1Zb1ZXWEk1TXhpUE9ZeG5BQmtKQjRTQ2dJUmVqYkpmVmFRdG9RNGEKejAyaVVMZW5ESUllUU9Zb2JLY01CWGYxQjRQQVFtc2VocVZJYnpzUUNHaTU0VkRyczZiWmQvN0pzMXpDcHBncwpKaUQ1SXFNaktXRHdxN2FLCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K diff --git a/internal/gatewayapi/testdata/gateway-with-stale-status-condition.out.yaml b/internal/gatewayapi/testdata/gateway-with-stale-status-condition.out.yaml index 987cff5897e..aae3821da4d 100644 --- a/internal/gatewayapi/testdata/gateway-with-stale-status-condition.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-stale-status-condition.out.yaml @@ -132,6 +132,6 @@ xdsIR: prefix: / tls: certificates: - - name: default-tls-secret-1 + - name: default/tls-secret-1 privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2QwZlBDYWtweE1nUnUKT0VXQjFiQk5FM3ZseW55aTZWbkV2VWF1OUhvakR2UHVPTFJIaGI4MmoyY1ovMHhnL1lKR09LelBuV2JERkxGNApHdWh3dDRENmFUR0xYNklPODEwTDZ0SXZIWGZNUXRJS2VwdTZ3K3p1WVo4bG1yejB1RjZlWEtqamVIbHhyb2ZrCnVNekM3OUVaU0lYZlZlczJ1SmdVRSs4VGFzSDUzQ2Y4MFNSRGlIeEdxckttdVNjWCtwejBreGdCZ1VWYTVVS20KUWdTZDFmVUxLOUEwNXAxOXkrdURPM204bVhRNkxVQ0N1STFwZHNROGFlNS9zamlxa0VjWlJjMTdWYVgxWjVVaQpvcGZnNW9SY05VTG9VTHNiek9aNTR0YlVDUmdSV2VLbGZxaElINEZ6OUlkVlUyR3dFdEdhMmV6TjgyMVBaQ3QzCjZhbVRIelJsQWdNQkFBRUNnZ0VBWTFGTUlLNDVXTkVNUHJ6RTZUY3NNdVV2RkdhQVZ4bVk5NW5SMEtwajdvb3IKY21CVys2ZXN0TTQ4S1AwaitPbXd3VFpMY29Cd3VoWGN0V1Bob1lXcDhteWUxRUlEdjNyaHRHMDdocEQ1NGg2dgpCZzh3ejdFYStzMk9sT0N6UnlKNzBSY281YlhjWDNGaGJjdnFlRWJwaFFyQnpOSEtLMjZ4cmZqNWZIT3p6T1FGCmJHdUZ3SDVic3JGdFhlajJXM3c4eW90N0ZQSDV3S3RpdnhvSWU5RjMyOXNnOU9EQnZqWnpiaG1LVTArckFTK1kKRGVield2bFJyaEUrbXVmQTN6M0N0QXhDOFJpNzNscFNoTDRQQWlvcG1SUXlxZXRXMjYzOFFxcnM0R3hnNzhwbApJUXJXTmNBc2s3Slg5d3RZenV6UFBXSXRWTTFscFJiQVRhNTJqdFl2NVFLQmdRRE5tMTFtZTRYam1ZSFV2cStZCmFTUzdwK2UybXZEMHVaOU9JeFluQnBWMGkrckNlYnFFMkE1Rm5hcDQ5Yld4QTgwUElldlVkeUpCL2pUUkoxcVMKRUpXQkpMWm1LVkg2K1QwdWw1ZUtOcWxFTFZHU0dCSXNpeE9SUXpDZHBoMkx0UmtBMHVjSVUzY3hiUmVMZkZCRQpiSkdZWENCdlNGcWd0VDlvZTFldVpMVmFOd0tCZ1FERWdENzJENk81eGIweEQ1NDQ1M0RPMUJhZmd6aThCWDRTCk1SaVd2LzFUQ0w5N05sRWtoeXovNmtQd1owbXJRcE5CMzZFdkpKZFVteHdkU2MyWDhrOGcxMC85NVlLQkdWQWoKL3d0YVZYbE9WeEFvK0ZSelpZeFpyQ29uWWFSMHVwUzFybDRtenN4REhlZU9mUVZUTUgwUjdZN0pnbTA5dXQ4SwplanAvSXZBb1F3S0JnQjNaRWlRUWhvMVYrWjBTMlpiOG5KS0plMy9zMmxJTXFHM0ZkaS9RS3Q0eWViQWx6OGY5ClBZVXBzRmZEQTg5Z3grSU1nSm5sZVptdTk2ZnRXSjZmdmJSenllN216TG5zZU05TXZua1lHbGFGWmJRWnZubXMKN3ZoRmtzY3dHRlh4d21GMlBJZmU1Z3pNMDRBeVdjeTFIaVhLS2dNOXM3cGsxWUdyZGowZzdacmRBb0dCQUtLNApDR3MrbkRmMEZTMFJYOWFEWVJrRTdBNy9YUFhtSG5YMkRnU1h5N0Q4NTRPaWdTTWNoUmtPNTErbVNJejNQbllvCk41T1FXM2lHVVl1M1YvYmhnc0VSUzM1V2xmRk9BdDBzRUR5bjF5SVdXcDF5dG93d3BUNkVvUXVuZ2NYZjA5RjMKS1NROXowd3M4VmsvRWkvSFVXcU5LOWFXbU51cmFaT0ZqL2REK1ZkOUFvR0FMWFN3dEE3K043RDRkN0VEMURSRQpHTWdZNVd3OHFvdDZSdUNlNkpUY0FnU3B1MkhNU3JVY2dXclpiQnJZb09FUnVNQjFoMVJydk5ybU1qQlM0VW9FClgyZC8vbGhpOG1wL2VESWN3UDNRa2puanBJRFJWMFN1eWxrUkVaZURKZjVZb3R6eDdFdkJhbzFIbkQrWEg4eUIKVUtmWGJTaHZKVUdhRmgxT3Q1Y3JoM1k9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNxRENDQVpBQ0NRREVNZ1lZblFyQ29EQU5CZ2txaGtpRzl3MEJBUXNGQURBV01SUXdFZ1lEVlFRRERBdG0KYjI4dVltRnlMbU52YlRBZUZ3MHlNekF4TURVeE16UXpNalJhRncweU5EQXhNRFV4TXpRek1qUmFNQll4RkRBUwpCZ05WQkFNTUMyWnZieTVpWVhJdVkyOXRNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDCkFRRUFuZEh6d21wS2NUSUViamhGZ2RXd1RSTjc1Y3A4b3VsWnhMMUdydlI2SXc3ejdqaTBSNFcvTm85bkdmOU0KWVAyQ1JqaXN6NTFtd3hTeGVCcm9jTGVBK21reGkxK2lEdk5kQytyU0x4MTN6RUxTQ25xYnVzUHM3bUdmSlpxOAo5TGhlbmx5bzQzaDVjYTZINUxqTXd1L1JHVWlGMzFYck5yaVlGQlB2RTJyQitkd24vTkVrUTRoOFJxcXlwcmtuCkYvcWM5Sk1ZQVlGRld1VkNwa0lFbmRYMUN5dlFOT2FkZmN2cmd6dDV2SmwwT2kxQWdyaU5hWGJFUEdudWY3STQKcXBCSEdVWE5lMVdsOVdlVklxS1g0T2FFWERWQzZGQzdHOHptZWVMVzFBa1lFVm5pcFg2b1NCK0JjL1NIVlZOaApzQkxSbXRuc3pmTnRUMlFyZCttcGt4ODBaUUlEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ1VKOElDCkJveUVqT3V3enBHYVJoR044QjRqT1B6aHVDT0V0ZDM3UzAybHUwN09IenlCdmJzVEd6S3dCZ0x5bVdmR2tINEIKajdDTHNwOEZ6TkhLWnVhQmdwblo5SjZETE9Od2ZXZTJBWXA3TGRmT0tWQlVkTVhRaU9tN2pKOUhob0Ntdk1ONwpic2pjaFdKb013ckZmK3dkQUthdHowcUFQeWhMeWUvRnFtaVZ4a09SWmF3K1Q5bURaK0g0OXVBU2d1SnVOTXlRClY2RXlYNmd0Z1dxMzc2SHZhWE1TLzNoYW1Zb1ZXWEk1TXhpUE9ZeG5BQmtKQjRTQ2dJUmVqYkpmVmFRdG9RNGEKejAyaVVMZW5ESUllUU9Zb2JLY01CWGYxQjRQQVFtc2VocVZJYnpzUUNHaTU0VkRyczZiWmQvN0pzMXpDcHBncwpKaUQ1SXFNaktXRHdxN2FLCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K diff --git a/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout-error.in.yaml b/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout-error.in.yaml new file mode 100644 index 00000000000..c95fd909515 --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout-error.in.yaml @@ -0,0 +1,54 @@ +gateways: +- 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-2 + sectionName: http + rules: + - matches: + - path: + value: "/" + timeouts: + request: 1s + backendRefs: + - name: service-1 + port: 8080 +backendTrafficPolicies: +- 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 + namespace: default + timeout: + tcp: + connectTimeout: 20kib + http: + maxConnectionDuration: 22s diff --git a/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout-error.out.yaml b/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout-error.out.yaml new file mode 100755 index 00000000000..7087de39768 --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout-error.out.yaml @@ -0,0 +1,160 @@ +backendTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + creationTimestamp: null + name: policy-for-route + namespace: default + spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + namespace: default + timeout: + http: + maxConnectionDuration: 22s + tcp: + connectTimeout: 20kib + status: + conditions: + - lastTransitionTime: null + message: 'Unable to translate TCP Timeout: invalid ConnectTimeout value 20kib' + reason: Invalid + status: "False" + type: Accepted +gateways: +- 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-2 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: / + timeouts: + request: 1s + 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-2 + namespace: envoy-gateway + sectionName: http +infraIR: + envoy-gateway/gateway-2: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-2/http + ports: + - containerPort: 10080 + name: http + 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 +xdsIR: + envoy-gateway/gateway-2: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-2/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: gateway.envoyproxy.io + name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: / + timeout: + http: + requestTimeout: 1s diff --git a/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout.in.yaml b/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout.in.yaml new file mode 100644 index 00000000000..90157f5e80f --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout.in.yaml @@ -0,0 +1,100 @@ +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 +grpcRoutes: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: GRPCRoute + metadata: + namespace: default + name: grpcroute-1 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 +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-2 + sectionName: http + rules: + - matches: + - path: + value: "/" + timeouts: + request: 1s + backendRefs: + - name: service-1 + port: 8080 +backendTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + namespace: envoy-gateway + name: policy-for-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + timeout: + tcp: + connectTimeout: 15s + http: + connectionIdleTimeout: 16s + maxConnectionDuration: 17s +- 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 + namespace: default + timeout: + tcp: + connectTimeout: 20s + http: + maxConnectionDuration: 22s diff --git a/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout.out.yaml b/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout.out.yaml new file mode 100755 index 00000000000..4f34e9e2b46 --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout.out.yaml @@ -0,0 +1,312 @@ +backendTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + creationTimestamp: null + name: policy-for-route + namespace: default + spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + namespace: default + timeout: + http: + maxConnectionDuration: 22s + tcp: + connectTimeout: 20s + status: + conditions: + - lastTransitionTime: null + message: BackendTrafficPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + creationTimestamp: null + name: policy-for-gateway + namespace: envoy-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + timeout: + http: + connectionIdleTimeout: 16s + maxConnectionDuration: 17s + tcp: + connectTimeout: 15s + status: + conditions: + - lastTransitionTime: null + message: BackendTrafficPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +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 +grpcRoutes: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: GRPCRoute + metadata: + creationTimestamp: null + name: grpcroute-1 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + 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 +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-2 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: / + timeouts: + request: 1s + 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-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 + 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 + envoy-gateway/gateway-2: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-2/http + ports: + - containerPort: 10080 + name: http + 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 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: true + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: grpcroute/default/grpcroute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: GRPC + weight: 1 + hostname: '*' + name: grpcroute/default/grpcroute-1/rule/0/match/-1/* + timeout: + http: + connectionIdleTimeout: 16s + maxConnectionDuration: 17s + tcp: + connectTimeout: 15s + envoy-gateway/gateway-2: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-2/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: gateway.envoyproxy.io + name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: / + timeout: + http: + maxConnectionDuration: 22s + requestTimeout: 1s + tcp: + connectTimeout: 20s diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-two-listeners-with-different-ports.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-two-listeners-with-different-ports.out.yaml index ebaafcee77f..fbb816e0e08 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-two-listeners-with-different-ports.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-two-listeners-with-different-ports.out.yaml @@ -196,6 +196,6 @@ xdsIR: prefix: / tls: certificates: - - name: envoy-gateway-tls-secret-1 + - name: envoy-gateway/tls-secret-1 privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2QwZlBDYWtweE1nUnUKT0VXQjFiQk5FM3ZseW55aTZWbkV2VWF1OUhvakR2UHVPTFJIaGI4MmoyY1ovMHhnL1lKR09LelBuV2JERkxGNApHdWh3dDRENmFUR0xYNklPODEwTDZ0SXZIWGZNUXRJS2VwdTZ3K3p1WVo4bG1yejB1RjZlWEtqamVIbHhyb2ZrCnVNekM3OUVaU0lYZlZlczJ1SmdVRSs4VGFzSDUzQ2Y4MFNSRGlIeEdxckttdVNjWCtwejBreGdCZ1VWYTVVS20KUWdTZDFmVUxLOUEwNXAxOXkrdURPM204bVhRNkxVQ0N1STFwZHNROGFlNS9zamlxa0VjWlJjMTdWYVgxWjVVaQpvcGZnNW9SY05VTG9VTHNiek9aNTR0YlVDUmdSV2VLbGZxaElINEZ6OUlkVlUyR3dFdEdhMmV6TjgyMVBaQ3QzCjZhbVRIelJsQWdNQkFBRUNnZ0VBWTFGTUlLNDVXTkVNUHJ6RTZUY3NNdVV2RkdhQVZ4bVk5NW5SMEtwajdvb3IKY21CVys2ZXN0TTQ4S1AwaitPbXd3VFpMY29Cd3VoWGN0V1Bob1lXcDhteWUxRUlEdjNyaHRHMDdocEQ1NGg2dgpCZzh3ejdFYStzMk9sT0N6UnlKNzBSY281YlhjWDNGaGJjdnFlRWJwaFFyQnpOSEtLMjZ4cmZqNWZIT3p6T1FGCmJHdUZ3SDVic3JGdFhlajJXM3c4eW90N0ZQSDV3S3RpdnhvSWU5RjMyOXNnOU9EQnZqWnpiaG1LVTArckFTK1kKRGVield2bFJyaEUrbXVmQTN6M0N0QXhDOFJpNzNscFNoTDRQQWlvcG1SUXlxZXRXMjYzOFFxcnM0R3hnNzhwbApJUXJXTmNBc2s3Slg5d3RZenV6UFBXSXRWTTFscFJiQVRhNTJqdFl2NVFLQmdRRE5tMTFtZTRYam1ZSFV2cStZCmFTUzdwK2UybXZEMHVaOU9JeFluQnBWMGkrckNlYnFFMkE1Rm5hcDQ5Yld4QTgwUElldlVkeUpCL2pUUkoxcVMKRUpXQkpMWm1LVkg2K1QwdWw1ZUtOcWxFTFZHU0dCSXNpeE9SUXpDZHBoMkx0UmtBMHVjSVUzY3hiUmVMZkZCRQpiSkdZWENCdlNGcWd0VDlvZTFldVpMVmFOd0tCZ1FERWdENzJENk81eGIweEQ1NDQ1M0RPMUJhZmd6aThCWDRTCk1SaVd2LzFUQ0w5N05sRWtoeXovNmtQd1owbXJRcE5CMzZFdkpKZFVteHdkU2MyWDhrOGcxMC85NVlLQkdWQWoKL3d0YVZYbE9WeEFvK0ZSelpZeFpyQ29uWWFSMHVwUzFybDRtenN4REhlZU9mUVZUTUgwUjdZN0pnbTA5dXQ4SwplanAvSXZBb1F3S0JnQjNaRWlRUWhvMVYrWjBTMlpiOG5KS0plMy9zMmxJTXFHM0ZkaS9RS3Q0eWViQWx6OGY5ClBZVXBzRmZEQTg5Z3grSU1nSm5sZVptdTk2ZnRXSjZmdmJSenllN216TG5zZU05TXZua1lHbGFGWmJRWnZubXMKN3ZoRmtzY3dHRlh4d21GMlBJZmU1Z3pNMDRBeVdjeTFIaVhLS2dNOXM3cGsxWUdyZGowZzdacmRBb0dCQUtLNApDR3MrbkRmMEZTMFJYOWFEWVJrRTdBNy9YUFhtSG5YMkRnU1h5N0Q4NTRPaWdTTWNoUmtPNTErbVNJejNQbllvCk41T1FXM2lHVVl1M1YvYmhnc0VSUzM1V2xmRk9BdDBzRUR5bjF5SVdXcDF5dG93d3BUNkVvUXVuZ2NYZjA5RjMKS1NROXowd3M4VmsvRWkvSFVXcU5LOWFXbU51cmFaT0ZqL2REK1ZkOUFvR0FMWFN3dEE3K043RDRkN0VEMURSRQpHTWdZNVd3OHFvdDZSdUNlNkpUY0FnU3B1MkhNU3JVY2dXclpiQnJZb09FUnVNQjFoMVJydk5ybU1qQlM0VW9FClgyZC8vbGhpOG1wL2VESWN3UDNRa2puanBJRFJWMFN1eWxrUkVaZURKZjVZb3R6eDdFdkJhbzFIbkQrWEg4eUIKVUtmWGJTaHZKVUdhRmgxT3Q1Y3JoM1k9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNxRENDQVpBQ0NRREVNZ1lZblFyQ29EQU5CZ2txaGtpRzl3MEJBUXNGQURBV01SUXdFZ1lEVlFRRERBdG0KYjI4dVltRnlMbU52YlRBZUZ3MHlNekF4TURVeE16UXpNalJhRncweU5EQXhNRFV4TXpRek1qUmFNQll4RkRBUwpCZ05WQkFNTUMyWnZieTVpWVhJdVkyOXRNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDCkFRRUFuZEh6d21wS2NUSUViamhGZ2RXd1RSTjc1Y3A4b3VsWnhMMUdydlI2SXc3ejdqaTBSNFcvTm85bkdmOU0KWVAyQ1JqaXN6NTFtd3hTeGVCcm9jTGVBK21reGkxK2lEdk5kQytyU0x4MTN6RUxTQ25xYnVzUHM3bUdmSlpxOAo5TGhlbmx5bzQzaDVjYTZINUxqTXd1L1JHVWlGMzFYck5yaVlGQlB2RTJyQitkd24vTkVrUTRoOFJxcXlwcmtuCkYvcWM5Sk1ZQVlGRld1VkNwa0lFbmRYMUN5dlFOT2FkZmN2cmd6dDV2SmwwT2kxQWdyaU5hWGJFUEdudWY3STQKcXBCSEdVWE5lMVdsOVdlVklxS1g0T2FFWERWQzZGQzdHOHptZWVMVzFBa1lFVm5pcFg2b1NCK0JjL1NIVlZOaApzQkxSbXRuc3pmTnRUMlFyZCttcGt4ODBaUUlEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ1VKOElDCkJveUVqT3V3enBHYVJoR044QjRqT1B6aHVDT0V0ZDM3UzAybHUwN09IenlCdmJzVEd6S3dCZ0x5bVdmR2tINEIKajdDTHNwOEZ6TkhLWnVhQmdwblo5SjZETE9Od2ZXZTJBWXA3TGRmT0tWQlVkTVhRaU9tN2pKOUhob0Ntdk1ONwpic2pjaFdKb013ckZmK3dkQUthdHowcUFQeWhMeWUvRnFtaVZ4a09SWmF3K1Q5bURaK0g0OXVBU2d1SnVOTXlRClY2RXlYNmd0Z1dxMzc2SHZhWE1TLzNoYW1Zb1ZXWEk1TXhpUE9ZeG5BQmtKQjRTQ2dJUmVqYkpmVmFRdG9RNGEKejAyaVVMZW5ESUllUU9Zb2JLY01CWGYxQjRQQVFtc2VocVZJYnpzUUNHaTU0VkRyczZiWmQvN0pzMXpDcHBncwpKaUQ1SXFNaktXRHdxN2FLCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K diff --git a/internal/gatewayapi/testdata/httproute-backend-request-timeout.out.yaml b/internal/gatewayapi/testdata/httproute-backend-request-timeout.out.yaml index a9dc0004735..d30ba8e8970 100644 --- a/internal/gatewayapi/testdata/httproute-backend-request-timeout.out.yaml +++ b/internal/gatewayapi/testdata/httproute-backend-request-timeout.out.yaml @@ -128,4 +128,6 @@ xdsIR: distinct: false name: "" prefix: / - timeout: 1s + timeout: + http: + requestTimeout: 1s diff --git a/internal/gatewayapi/testdata/httproute-request-timeout.out.yaml b/internal/gatewayapi/testdata/httproute-request-timeout.out.yaml index c25eae8d45e..6001280e097 100644 --- a/internal/gatewayapi/testdata/httproute-request-timeout.out.yaml +++ b/internal/gatewayapi/testdata/httproute-request-timeout.out.yaml @@ -128,4 +128,6 @@ xdsIR: distinct: false name: "" prefix: / - timeout: 5s + timeout: + http: + requestTimeout: 5s diff --git a/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-weights.in.yaml b/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-weights.in.yaml index 36acae06f4d..e3419de8d98 100644 --- a/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-weights.in.yaml +++ b/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-weights.in.yaml @@ -37,3 +37,6 @@ httpRoutes: - name: service-3 port: 8080 weight: 3 + - name: service-4 + port: 8080 + weight: 0 diff --git a/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-weights.out.yaml b/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-weights.out.yaml index ae4215a6c0f..8cb654878a7 100644 --- a/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-weights.out.yaml +++ b/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-weights.out.yaml @@ -61,6 +61,9 @@ httpRoutes: - name: service-3 port: 8080 weight: 3 + - name: service-4 + port: 8080 + weight: 0 matches: - path: value: / diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-group.out.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-group.out.yaml index 1e074acdf47..b276db33814 100644 --- a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-group.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-group.out.yaml @@ -71,7 +71,7 @@ httpRoutes: - lastTransitionTime: null message: Group is invalid, only the core API group (specified by omitting the group field or setting it to an empty string) and multicluster.x-k8s.io - is supported + are supported reason: InvalidKind status: "False" type: ResolvedRefs diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-kind.out.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-kind.out.yaml index a7b98493cb2..4a803481a22 100644 --- a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-kind.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-kind.out.yaml @@ -68,7 +68,7 @@ httpRoutes: status: "True" type: Accepted - lastTransitionTime: null - message: Kind is invalid, only Service and MCS ServiceImport is supported + message: Kind is invalid, only Service and MCS ServiceImport are supported reason: InvalidKind status: "False" type: ResolvedRefs diff --git a/internal/gatewayapi/testdata/securitypolicy-with-cors.in.yaml b/internal/gatewayapi/testdata/securitypolicy-with-cors.in.yaml index 82ed4671d6c..3b773726448 100644 --- a/internal/gatewayapi/testdata/securitypolicy-with-cors.in.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-cors.in.yaml @@ -27,6 +27,20 @@ gateways: allowedRoutes: namespaces: from: All +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-3 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All grpcRoutes: - apiVersion: gateway.networking.k8s.io/v1alpha2 kind: GRPCRoute @@ -62,12 +76,31 @@ httpRoutes: backendRefs: - name: service-1 port: 8080 +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-2 + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - namespace: envoy-gateway + name: gateway-3 + sectionName: http + rules: + - matches: + - path: + value: "/" + backendRefs: + - name: service-2 + port: 8080 securityPolicies: - apiVersion: gateway.envoyproxy.io/v1alpha1 kind: SecurityPolicy metadata: namespace: envoy-gateway - name: policy-for-gateway + name: policy-for-gateway-1 spec: targetRef: group: gateway.networking.k8s.io @@ -78,6 +111,7 @@ securityPolicies: allowOrigins: - "http://*.example.com" - "http://foo.bar.com" + - "https://*" allowMethods: - GET - POST @@ -92,7 +126,7 @@ securityPolicies: kind: SecurityPolicy metadata: namespace: default - name: policy-for-route + name: policy-for-route-1 spec: targetRef: group: gateway.networking.k8s.io @@ -113,3 +147,27 @@ securityPolicies: - "x-header-7" - "x-header-8" maxAge: 2000s +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + namespace: default + name: policy-for-route-2 + spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-2 + namespace: default + cors: + allowOrigins: + - "*" + allowMethods: + - GET + - POST + allowHeaders: + - "x-header-5" + - "x-header-6" + exposeHeaders: + - "x-header-7" + - "x-header-8" + maxAge: 2000s diff --git a/internal/gatewayapi/testdata/securitypolicy-with-cors.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-cors.out.yaml index 0de22c6369b..c50b5e03ad6 100644 --- a/internal/gatewayapi/testdata/securitypolicy-with-cors.out.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-cors.out.yaml @@ -79,6 +79,46 @@ gateways: kind: HTTPRoute - group: gateway.networking.k8s.io kind: GRPCRoute +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-3 + 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 grpcRoutes: - apiVersion: gateway.networking.k8s.io/v1alpha2 kind: GRPCRoute @@ -152,6 +192,44 @@ httpRoutes: name: gateway-2 namespace: envoy-gateway sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-2 + namespace: default + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - name: gateway-3 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-2 + 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-3 + namespace: envoy-gateway + sectionName: http infraIR: envoy-gateway/gateway-1: proxy: @@ -183,12 +261,27 @@ infraIR: gateway.envoyproxy.io/owning-gateway-name: gateway-2 gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway name: envoy-gateway/gateway-2 + envoy-gateway/gateway-3: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-3/http + ports: + - containerPort: 10080 + name: http + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-3 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-3 securityPolicies: - apiVersion: gateway.envoyproxy.io/v1alpha1 kind: SecurityPolicy metadata: creationTimestamp: null - name: policy-for-route + name: policy-for-route-1 namespace: default spec: cors: @@ -221,7 +314,39 @@ securityPolicies: kind: SecurityPolicy metadata: creationTimestamp: null - name: policy-for-gateway + name: policy-for-route-2 + namespace: default + spec: + cors: + allowHeaders: + - x-header-5 + - x-header-6 + allowMethods: + - GET + - POST + allowOrigins: + - '*' + exposeHeaders: + - x-header-7 + - x-header-8 + maxAge: 33m20s + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-2 + namespace: default + status: + conditions: + - lastTransitionTime: null + message: SecurityPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + creationTimestamp: null + name: policy-for-gateway-1 namespace: envoy-gateway spec: cors: @@ -234,6 +359,7 @@ securityPolicies: allowOrigins: - http://*.example.com - http://foo.bar.com + - https://* exposeHeaders: - x-header-3 - x-header-4 @@ -283,6 +409,9 @@ xdsIR: - distinct: false exact: http://foo.bar.com name: "" + - distinct: false + name: "" + safeRegex: https://.* exposeHeaders: - x-header-3 - x-header-4 @@ -349,3 +478,51 @@ xdsIR: distinct: false name: "" prefix: / + envoy-gateway/gateway-3: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-3/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - backendWeights: + invalid: 0 + valid: 0 + cors: + allowHeaders: + - x-header-5 + - x-header-6 + allowMethods: + - GET + - POST + allowOrigins: + - distinct: false + name: "" + safeRegex: .* + exposeHeaders: + - x-header-7 + - x-header-8 + maxAge: 33m20s + destination: + name: httproute/default/httproute-2/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: gateway.envoyproxy.io + name: httproute/default/httproute-2/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: / diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-matching-port.in.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-matching-port.in.yaml new file mode 100644 index 00000000000..9838d7d3776 --- /dev/null +++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-matching-port.in.yaml @@ -0,0 +1,65 @@ +gateways: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: default + name: gateway-1 + 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: + - www.foo.com + parentRefs: + - namespace: default + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: /foo + backendRefs: + - name: service-1 + port: 8080 +services: + - apiVersion: v1 + kind: Service + metadata: + namespace: default + name: http-backend + spec: + ports: + - port: 8080 +securityPolicies: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + namespace: default + name: policy-for-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: default + extAuth: + http: + backendRef: + Name: http-backend + Namespace: default + Port: 80 + headersToBackend: + - header1 + - header2 diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-matching-port.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-matching-port.out.yaml new file mode 100755 index 00000000000..d7acc9b0a32 --- /dev/null +++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-matching-port.out.yaml @@ -0,0 +1,159 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: default + 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: + - www.foo.com + parentRefs: + - name: gateway-1 + namespace: default + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: /foo + 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: default + sectionName: http +infraIR: + default/gateway-1: + proxy: + listeners: + - address: null + name: default/gateway-1/http + ports: + - containerPort: 10080 + name: http + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: default + name: default/gateway-1 +securityPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + creationTimestamp: null + name: policy-for-gateway + namespace: default + spec: + extAuth: + http: + backendRef: + name: http-backend + namespace: default + port: 80 + headersToBackend: + - header1 + - header2 + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: default + status: + conditions: + - lastTransitionTime: null + message: TCP Port 80 not found on service default/http-backend + reason: Invalid + status: "False" + type: Accepted +xdsIR: + default/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: default/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: www.foo.com + name: httproute/default/httproute-1/rule/0/match/0/www_foo_com + pathMatch: + distinct: false + name: "" + prefix: /foo diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-reference-grant.in.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-reference-grant.in.yaml new file mode 100644 index 00000000000..5664148bdb0 --- /dev/null +++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-reference-grant.in.yaml @@ -0,0 +1,65 @@ +gateways: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: default + name: gateway-1 + 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: + - www.foo.com + parentRefs: + - namespace: default + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: /foo + backendRefs: + - name: service-1 + port: 8080 +services: + - apiVersion: v1 + kind: Service + metadata: + namespace: envoy-gateway + name: http-backend + spec: + ports: + - port: 80 +securityPolicies: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + namespace: default + name: policy-for-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: default + extAuth: + http: + backendRef: + Name: http-backend + Namespace: envoy-gateway + Port: 80 + headersToBackend: + - header1 + - header2 diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-reference-grant.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-reference-grant.out.yaml new file mode 100755 index 00000000000..46f93304a50 --- /dev/null +++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-reference-grant.out.yaml @@ -0,0 +1,160 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: default + 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: + - www.foo.com + parentRefs: + - name: gateway-1 + namespace: default + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: /foo + 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: default + sectionName: http +infraIR: + default/gateway-1: + proxy: + listeners: + - address: null + name: default/gateway-1/http + ports: + - containerPort: 10080 + name: http + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: default + name: default/gateway-1 +securityPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + creationTimestamp: null + name: policy-for-gateway + namespace: default + spec: + extAuth: + http: + backendRef: + name: http-backend + namespace: envoy-gateway + port: 80 + headersToBackend: + - header1 + - header2 + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: default + status: + conditions: + - lastTransitionTime: null + message: Backend ref to Service envoy-gateway/http-backend not permitted by + any ReferenceGrant + reason: Invalid + status: "False" + type: Accepted +xdsIR: + default/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: default/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: www.foo.com + name: httproute/default/httproute-1/rule/0/match/0/www_foo_com + pathMatch: + distinct: false + name: "" + prefix: /foo diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-service.in.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-service.in.yaml new file mode 100644 index 00000000000..a74b1b099b6 --- /dev/null +++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-service.in.yaml @@ -0,0 +1,56 @@ +gateways: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: default + name: gateway-1 + 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: + - www.foo.com + parentRefs: + - namespace: default + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: /foo + backendRefs: + - name: service-1 + port: 8080 +securityPolicies: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + namespace: default + name: policy-for-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: default + extAuth: + http: + backendRef: + Name: http-backend + Namespace: default + Port: 80 + headersToBackend: + - header1 + - header2 diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-service.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-service.out.yaml new file mode 100755 index 00000000000..dfd4c3f88d1 --- /dev/null +++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-service.out.yaml @@ -0,0 +1,159 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: default + 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: + - www.foo.com + parentRefs: + - name: gateway-1 + namespace: default + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: /foo + 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: default + sectionName: http +infraIR: + default/gateway-1: + proxy: + listeners: + - address: null + name: default/gateway-1/http + ports: + - containerPort: 10080 + name: http + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: default + name: default/gateway-1 +securityPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + creationTimestamp: null + name: policy-for-gateway + namespace: default + spec: + extAuth: + http: + backendRef: + name: http-backend + namespace: default + port: 80 + headersToBackend: + - header1 + - header2 + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: default + status: + conditions: + - lastTransitionTime: null + message: Service default/http-backend not found + reason: Invalid + status: "False" + type: Accepted +xdsIR: + default/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: default/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: www.foo.com + name: httproute/default/httproute-1/rule/0/match/0/www_foo_com + pathMatch: + distinct: false + name: "" + prefix: /foo diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth.in.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth.in.yaml new file mode 100644 index 00000000000..12142460fa3 --- /dev/null +++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth.in.yaml @@ -0,0 +1,165 @@ +gateways: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: default + name: gateway-1 + 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: + - www.foo.com + parentRefs: + - namespace: default + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: /foo + backendRefs: + - name: service-1 + port: 8080 + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-2 + spec: + hostnames: + - www.bar.com + parentRefs: + - namespace: default + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: /bar + backendRefs: + - name: service-1 + port: 8080 +services: + - apiVersion: v1 + kind: Service + metadata: + namespace: envoy-gateway + name: http-backend + spec: + ports: + - port: 80 + name: http + protocol: TCP + - apiVersion: v1 + kind: Service + metadata: + namespace: default + name: grpc-backend + spec: + ports: + - port: 9000 + name: grpc + protocol: TCP +endpointSlices: + - apiVersion: discovery.k8s.io/v1 + kind: EndpointSlice + metadata: + name: endpointslice-http-backend + namespace: envoy-gateway + labels: + kubernetes.io/service-name: http-backend + addressType: IPv4 + ports: + - name: http + protocol: TCP + port: 80 + endpoints: + - addresses: + - 7.7.7.7 + conditions: + ready: true + - apiVersion: discovery.k8s.io/v1 + kind: EndpointSlice + metadata: + name: endpointslice-grpc-backend + namespace: default + labels: + kubernetes.io/service-name: grpc-backend + addressType: IPv4 + ports: + - name: grpc + protocol: TCP + port: 9000 + endpoints: + - addresses: + - 8.8.8.8 + conditions: + ready: true +referenceGrants: + - apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: ReferenceGrant + metadata: + namespace: envoy-gateway + name: referencegrant-1 + spec: + from: + - group: gateway.envoyproxy.io + kind: SecurityPolicy + namespace: default + to: + - group: '' + kind: Service +securityPolicies: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + namespace: default + name: policy-for-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: default + extAuth: + http: + backendRef: + Name: http-backend + Namespace: envoy-gateway + Port: 80 + Path: /auth + headersToBackend: + - header1 + - header2 + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + namespace: default + name: policy-for-http-route + spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + namespace: default + extAuth: + headersToExtAuth: + - header1 + - header2 + grpc: + backendRef: + name: grpc-backend + port: 9000 diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth.out.yaml new file mode 100755 index 00000000000..412c5643809 --- /dev/null +++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth.out.yaml @@ -0,0 +1,274 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: default + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 2 + 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: + - www.foo.com + parentRefs: + - name: gateway-1 + namespace: default + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: /foo + 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: default + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-2 + namespace: default + spec: + hostnames: + - www.bar.com + parentRefs: + - name: gateway-1 + namespace: default + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: /bar + 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: default + sectionName: http +infraIR: + default/gateway-1: + proxy: + listeners: + - address: null + name: default/gateway-1/http + ports: + - containerPort: 10080 + name: http + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: default + name: default/gateway-1 +securityPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + creationTimestamp: null + name: policy-for-http-route + namespace: default + spec: + extAuth: + grpc: + backendRef: + name: grpc-backend + port: 9000 + headersToExtAuth: + - header1 + - header2 + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + namespace: default + status: + conditions: + - lastTransitionTime: null + message: SecurityPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + creationTimestamp: null + name: policy-for-gateway + namespace: default + spec: + extAuth: + http: + backendRef: + name: http-backend + namespace: envoy-gateway + port: 80 + headersToBackend: + - header1 + - header2 + path: /auth + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: default + status: + conditions: + - lastTransitionTime: null + message: SecurityPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +xdsIR: + default/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: default/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + extAuth: + grpc: + authority: grpc-backend.default:9000 + destination: + name: securitypolicy/default/policy-for-http-route/grpc-backend + settings: + - addressType: IP + endpoints: + - host: 8.8.8.8 + port: 9000 + protocol: GRPC + weight: 1 + headersToExtAuth: + - header1 + - header2 + hostname: www.foo.com + name: httproute/default/httproute-1/rule/0/match/0/www_foo_com + pathMatch: + distinct: false + name: "" + prefix: /foo + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-2/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + extAuth: + http: + authority: http-backend.envoy-gateway:80 + destination: + name: securitypolicy/default/policy-for-gateway/http-backend + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 80 + protocol: HTTP + weight: 1 + headersToBackend: + - header1 + - header2 + path: /auth + hostname: www.bar.com + name: httproute/default/httproute-2/rule/0/match/0/www_bar_com + pathMatch: + distinct: false + name: "" + prefix: /bar diff --git a/internal/gatewayapi/testdata/securitypolicy-with-jwt-with-custom-extractor.in.yaml b/internal/gatewayapi/testdata/securitypolicy-with-jwt-with-custom-extractor.in.yaml index 96580c84971..4c43bc662e0 100644 --- a/internal/gatewayapi/testdata/securitypolicy-with-jwt-with-custom-extractor.in.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-jwt-with-custom-extractor.in.yaml @@ -117,5 +117,10 @@ securityPolicies: - header: three-route-example-key claim: claim3 extractFrom: + headers: + - name: Authorization + valuePrefix: 'Bearer ' cookies: - session_access_token + params: + - token diff --git a/internal/gatewayapi/testdata/securitypolicy-with-jwt-with-custom-extractor.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-jwt-with-custom-extractor.out.yaml index 6cf96952e41..10b9b7e2d4e 100644 --- a/internal/gatewayapi/testdata/securitypolicy-with-jwt-with-custom-extractor.out.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-jwt-with-custom-extractor.out.yaml @@ -201,6 +201,11 @@ securityPolicies: extractFrom: cookies: - session_access_token + headers: + - name: Authorization + valuePrefix: 'Bearer ' + params: + - token issuer: https://three.example.com name: example3 remoteJWKS: @@ -344,6 +349,11 @@ xdsIR: extractFrom: cookies: - session_access_token + headers: + - name: Authorization + valuePrefix: 'Bearer ' + params: + - token issuer: https://three.example.com name: example3 remoteJWKS: diff --git a/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-issuer.in.yaml b/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-issuer.in.yaml index 9f49012c528..169c7b94ecc 100644 --- a/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-issuer.in.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-issuer.in.yaml @@ -27,6 +27,7 @@ securityPolicies: metadata: namespace: default name: policy-non-exist-secretRef + uid: b8284d0f-de82-4c65-b204-96a0d3f258a1 spec: targetRef: group: gateway.networking.k8s.io diff --git a/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-issuer.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-issuer.out.yaml index 29fb726b11b..3a5ad95fc21 100644 --- a/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-issuer.out.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-issuer.out.yaml @@ -62,6 +62,7 @@ securityPolicies: creationTimestamp: null name: policy-non-exist-secretRef namespace: default + uid: b8284d0f-de82-4c65-b204-96a0d3f258a1 spec: oidc: clientID: client1.apps.foo.bar.com diff --git a/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-secretref.in.yaml b/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-secretref.in.yaml index c3c86142e0b..565159c0175 100644 --- a/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-secretref.in.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-secretref.in.yaml @@ -63,6 +63,7 @@ securityPolicies: metadata: namespace: default name: policy-non-exist-secretRef + uid: b8284d0f-de82-4c65-b204-96a0d3f258a1 spec: targetRef: group: gateway.networking.k8s.io @@ -81,6 +82,7 @@ securityPolicies: metadata: namespace: default name: policy-no-referenceGrant + uid: 08335a80-83ba-4592-888f-6ac0bba44ce4 spec: targetRef: group: gateway.networking.k8s.io diff --git a/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-secretref.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-secretref.out.yaml index 078fbd343ad..0afef222a9d 100644 --- a/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-secretref.out.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-oidc-invalid-secretref.out.yaml @@ -172,6 +172,7 @@ securityPolicies: creationTimestamp: null name: policy-non-exist-secretRef namespace: default + uid: b8284d0f-de82-4c65-b204-96a0d3f258a1 spec: oidc: clientID: client1.apps.googleusercontent.com @@ -200,6 +201,7 @@ securityPolicies: creationTimestamp: null name: policy-no-referenceGrant namespace: default + uid: 08335a80-83ba-4592-888f-6ac0bba44ce4 spec: oidc: clientID: client1.apps.googleusercontent.com diff --git a/internal/gatewayapi/testdata/securitypolicy-with-oidc.in.yaml b/internal/gatewayapi/testdata/securitypolicy-with-oidc.in.yaml index 91fae31ce82..086607d5939 100644 --- a/internal/gatewayapi/testdata/securitypolicy-with-oidc.in.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-oidc.in.yaml @@ -80,6 +80,7 @@ securityPolicies: metadata: namespace: envoy-gateway name: policy-for-gateway-discover-endpoints # This policy should attach httproute-2 + uid: b8284d0f-de82-4c65-b204-96a0d3f258a1 spec: targetRef: group: gateway.networking.k8s.io @@ -99,6 +100,7 @@ securityPolicies: metadata: namespace: default name: policy-for-http-route # This policy should attach httproute-1 + uid: 08335a80-83ba-4592-888f-6ac0bba44ce4 spec: targetRef: group: gateway.networking.k8s.io diff --git a/internal/gatewayapi/testdata/securitypolicy-with-oidc.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-oidc.out.yaml index bd2496ecb77..c08304d3ebd 100644 --- a/internal/gatewayapi/testdata/securitypolicy-with-oidc.out.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-oidc.out.yaml @@ -139,6 +139,7 @@ securityPolicies: creationTimestamp: null name: policy-for-http-route namespace: default + uid: 08335a80-83ba-4592-888f-6ac0bba44ce4 spec: oidc: clientID: client2.oauth.foo.com @@ -174,6 +175,7 @@ securityPolicies: creationTimestamp: null name: policy-for-gateway-discover-endpoints namespace: envoy-gateway + uid: b8284d0f-de82-4c65-b204-96a0d3f258a1 spec: oidc: clientID: client1.apps.googleusercontent.com @@ -230,6 +232,7 @@ xdsIR: oidc: clientID: client2.oauth.foo.com clientSecret: Y2xpZW50MTpzZWNyZXQK + cookieSuffix: 5F93C2E4 logoutPath: /foo/logout provider: authorizationEndpoint: https://oauth.foo.com/oauth2/v2/auth @@ -261,6 +264,7 @@ xdsIR: oidc: clientID: client1.apps.googleusercontent.com clientSecret: Y2xpZW50MTpzZWNyZXQK + cookieSuffix: B0A1B740 logoutPath: /bar/logout provider: authorizationEndpoint: https://accounts.google.com/o/oauth2/v2/auth diff --git a/internal/gatewayapi/testdata/tcproute-attaching-to-gateway-with-listener-tls-terminate.out.yaml b/internal/gatewayapi/testdata/tcproute-attaching-to-gateway-with-listener-tls-terminate.out.yaml index f70ca85e266..5a2f7ef478a 100644 --- a/internal/gatewayapi/testdata/tcproute-attaching-to-gateway-with-listener-tls-terminate.out.yaml +++ b/internal/gatewayapi/testdata/tcproute-attaching-to-gateway-with-listener-tls-terminate.out.yaml @@ -112,6 +112,6 @@ xdsIR: tls: terminate: certificates: - - name: envoy-gateway-tls-secret-1 + - name: envoy-gateway/tls-secret-1 privateKey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2QwZlBDYWtweE1nUnUKT0VXQjFiQk5FM3ZseW55aTZWbkV2VWF1OUhvakR2UHVPTFJIaGI4MmoyY1ovMHhnL1lKR09LelBuV2JERkxGNApHdWh3dDRENmFUR0xYNklPODEwTDZ0SXZIWGZNUXRJS2VwdTZ3K3p1WVo4bG1yejB1RjZlWEtqamVIbHhyb2ZrCnVNekM3OUVaU0lYZlZlczJ1SmdVRSs4VGFzSDUzQ2Y4MFNSRGlIeEdxckttdVNjWCtwejBreGdCZ1VWYTVVS20KUWdTZDFmVUxLOUEwNXAxOXkrdURPM204bVhRNkxVQ0N1STFwZHNROGFlNS9zamlxa0VjWlJjMTdWYVgxWjVVaQpvcGZnNW9SY05VTG9VTHNiek9aNTR0YlVDUmdSV2VLbGZxaElINEZ6OUlkVlUyR3dFdEdhMmV6TjgyMVBaQ3QzCjZhbVRIelJsQWdNQkFBRUNnZ0VBWTFGTUlLNDVXTkVNUHJ6RTZUY3NNdVV2RkdhQVZ4bVk5NW5SMEtwajdvb3IKY21CVys2ZXN0TTQ4S1AwaitPbXd3VFpMY29Cd3VoWGN0V1Bob1lXcDhteWUxRUlEdjNyaHRHMDdocEQ1NGg2dgpCZzh3ejdFYStzMk9sT0N6UnlKNzBSY281YlhjWDNGaGJjdnFlRWJwaFFyQnpOSEtLMjZ4cmZqNWZIT3p6T1FGCmJHdUZ3SDVic3JGdFhlajJXM3c4eW90N0ZQSDV3S3RpdnhvSWU5RjMyOXNnOU9EQnZqWnpiaG1LVTArckFTK1kKRGVield2bFJyaEUrbXVmQTN6M0N0QXhDOFJpNzNscFNoTDRQQWlvcG1SUXlxZXRXMjYzOFFxcnM0R3hnNzhwbApJUXJXTmNBc2s3Slg5d3RZenV6UFBXSXRWTTFscFJiQVRhNTJqdFl2NVFLQmdRRE5tMTFtZTRYam1ZSFV2cStZCmFTUzdwK2UybXZEMHVaOU9JeFluQnBWMGkrckNlYnFFMkE1Rm5hcDQ5Yld4QTgwUElldlVkeUpCL2pUUkoxcVMKRUpXQkpMWm1LVkg2K1QwdWw1ZUtOcWxFTFZHU0dCSXNpeE9SUXpDZHBoMkx0UmtBMHVjSVUzY3hiUmVMZkZCRQpiSkdZWENCdlNGcWd0VDlvZTFldVpMVmFOd0tCZ1FERWdENzJENk81eGIweEQ1NDQ1M0RPMUJhZmd6aThCWDRTCk1SaVd2LzFUQ0w5N05sRWtoeXovNmtQd1owbXJRcE5CMzZFdkpKZFVteHdkU2MyWDhrOGcxMC85NVlLQkdWQWoKL3d0YVZYbE9WeEFvK0ZSelpZeFpyQ29uWWFSMHVwUzFybDRtenN4REhlZU9mUVZUTUgwUjdZN0pnbTA5dXQ4SwplanAvSXZBb1F3S0JnQjNaRWlRUWhvMVYrWjBTMlpiOG5KS0plMy9zMmxJTXFHM0ZkaS9RS3Q0eWViQWx6OGY5ClBZVXBzRmZEQTg5Z3grSU1nSm5sZVptdTk2ZnRXSjZmdmJSenllN216TG5zZU05TXZua1lHbGFGWmJRWnZubXMKN3ZoRmtzY3dHRlh4d21GMlBJZmU1Z3pNMDRBeVdjeTFIaVhLS2dNOXM3cGsxWUdyZGowZzdacmRBb0dCQUtLNApDR3MrbkRmMEZTMFJYOWFEWVJrRTdBNy9YUFhtSG5YMkRnU1h5N0Q4NTRPaWdTTWNoUmtPNTErbVNJejNQbllvCk41T1FXM2lHVVl1M1YvYmhnc0VSUzM1V2xmRk9BdDBzRUR5bjF5SVdXcDF5dG93d3BUNkVvUXVuZ2NYZjA5RjMKS1NROXowd3M4VmsvRWkvSFVXcU5LOWFXbU51cmFaT0ZqL2REK1ZkOUFvR0FMWFN3dEE3K043RDRkN0VEMURSRQpHTWdZNVd3OHFvdDZSdUNlNkpUY0FnU3B1MkhNU3JVY2dXclpiQnJZb09FUnVNQjFoMVJydk5ybU1qQlM0VW9FClgyZC8vbGhpOG1wL2VESWN3UDNRa2puanBJRFJWMFN1eWxrUkVaZURKZjVZb3R6eDdFdkJhbzFIbkQrWEg4eUIKVUtmWGJTaHZKVUdhRmgxT3Q1Y3JoM1k9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNxRENDQVpBQ0NRREVNZ1lZblFyQ29EQU5CZ2txaGtpRzl3MEJBUXNGQURBV01SUXdFZ1lEVlFRRERBdG0KYjI4dVltRnlMbU52YlRBZUZ3MHlNekF4TURVeE16UXpNalJhRncweU5EQXhNRFV4TXpRek1qUmFNQll4RkRBUwpCZ05WQkFNTUMyWnZieTVpWVhJdVkyOXRNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDCkFRRUFuZEh6d21wS2NUSUViamhGZ2RXd1RSTjc1Y3A4b3VsWnhMMUdydlI2SXc3ejdqaTBSNFcvTm85bkdmOU0KWVAyQ1JqaXN6NTFtd3hTeGVCcm9jTGVBK21reGkxK2lEdk5kQytyU0x4MTN6RUxTQ25xYnVzUHM3bUdmSlpxOAo5TGhlbmx5bzQzaDVjYTZINUxqTXd1L1JHVWlGMzFYck5yaVlGQlB2RTJyQitkd24vTkVrUTRoOFJxcXlwcmtuCkYvcWM5Sk1ZQVlGRld1VkNwa0lFbmRYMUN5dlFOT2FkZmN2cmd6dDV2SmwwT2kxQWdyaU5hWGJFUEdudWY3STQKcXBCSEdVWE5lMVdsOVdlVklxS1g0T2FFWERWQzZGQzdHOHptZWVMVzFBa1lFVm5pcFg2b1NCK0JjL1NIVlZOaApzQkxSbXRuc3pmTnRUMlFyZCttcGt4ODBaUUlEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ1VKOElDCkJveUVqT3V3enBHYVJoR044QjRqT1B6aHVDT0V0ZDM3UzAybHUwN09IenlCdmJzVEd6S3dCZ0x5bVdmR2tINEIKajdDTHNwOEZ6TkhLWnVhQmdwblo5SjZETE9Od2ZXZTJBWXA3TGRmT0tWQlVkTVhRaU9tN2pKOUhob0Ntdk1ONwpic2pjaFdKb013ckZmK3dkQUthdHowcUFQeWhMeWUvRnFtaVZ4a09SWmF3K1Q5bURaK0g0OXVBU2d1SnVOTXlRClY2RXlYNmd0Z1dxMzc2SHZhWE1TLzNoYW1Zb1ZXWEk1TXhpUE9ZeG5BQmtKQjRTQ2dJUmVqYkpmVmFRdG9RNGEKejAyaVVMZW5ESUllUU9Zb2JLY01CWGYxQjRQQVFtc2VocVZJYnpzUUNHaTU0VkRyczZiWmQvN0pzMXpDcHBncwpKaUQ1SXFNaktXRHdxN2FLCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K diff --git a/internal/gatewayapi/translator.go b/internal/gatewayapi/translator.go index 2783b22d048..5163deca337 100644 --- a/internal/gatewayapi/translator.go +++ b/internal/gatewayapi/translator.go @@ -15,19 +15,21 @@ import ( ) const ( - KindEnvoyProxy = "EnvoyProxy" - KindGateway = "Gateway" - KindGatewayClass = "GatewayClass" - KindGRPCRoute = "GRPCRoute" - KindHTTPRoute = "HTTPRoute" - KindNamespace = "Namespace" - KindTLSRoute = "TLSRoute" - KindTCPRoute = "TCPRoute" - KindUDPRoute = "UDPRoute" - KindService = "Service" - KindServiceImport = "ServiceImport" - KindSecret = "Secret" - KindSecurityPolicy = "SecurityPolicy" + KindConfigMap = "ConfigMap" + KindClientTrafficPolicy = "ClientTrafficPolicy" + KindEnvoyProxy = "EnvoyProxy" + KindGateway = "Gateway" + KindGatewayClass = "GatewayClass" + KindGRPCRoute = "GRPCRoute" + KindHTTPRoute = "HTTPRoute" + KindNamespace = "Namespace" + KindTLSRoute = "TLSRoute" + KindTCPRoute = "TCPRoute" + KindUDPRoute = "UDPRoute" + KindService = "Service" + KindServiceImport = "ServiceImport" + KindSecret = "Secret" + KindSecurityPolicy = "SecurityPolicy" GroupMultiClusterService = "multicluster.x-k8s.io" // OwningGatewayNamespaceLabel is the owner reference label used for managed infra. @@ -81,6 +83,10 @@ type Translator struct { // should be merged under the parent GatewayClass. MergeGateways bool + // EnvoyPatchPolicyEnabled when the EnvoyPatchPolicy + // feature is enabled. + EnvoyPatchPolicyEnabled bool + // ExtensionGroupKinds stores the group/kind for all resources // introduced by an Extension so that the translator can // store referenced resources in the IR for later use. @@ -148,7 +154,7 @@ func (t *Translator) Translate(resources *Resources) *TranslateResult { t.ProcessEnvoyPatchPolicies(resources.EnvoyPatchPolicies, xdsIR) // Process ClientTrafficPolicies - clientTrafficPolicies := t.ProcessClientTrafficPolicies(resources.ClientTrafficPolicies, gateways, xdsIR, infraIR) + clientTrafficPolicies := t.ProcessClientTrafficPolicies(resources, gateways, xdsIR, infraIR) // Process all Addresses for all relevant Gateways. t.ProcessAddresses(gateways, xdsIR, infraIR, resources) diff --git a/internal/gatewayapi/translator_test.go b/internal/gatewayapi/translator_test.go index 1887f39ecc1..c67500dceba 100644 --- a/internal/gatewayapi/translator_test.go +++ b/internal/gatewayapi/translator_test.go @@ -43,6 +43,16 @@ func mustUnmarshal(t *testing.T, val []byte, out interface{}) { } func TestTranslate(t *testing.T) { + testCasesConfig := []struct { + name string + EnvoyPatchPolicyEnabled bool + }{ + { + name: "envoypatchpolicy-invalid-feature-disabled", + EnvoyPatchPolicyEnabled: false, + }, + } + inputFiles, err := filepath.Glob(filepath.Join("testdata", "*.in.yaml")) require.NoError(t, err) @@ -54,15 +64,23 @@ func TestTranslate(t *testing.T) { resources := &Resources{} mustUnmarshal(t, input, resources) + envoyPatchPolicyEnabled := true + + for _, config := range testCasesConfig { + if config.name == strings.Split(filepath.Base(inputFile), ".")[0] { + envoyPatchPolicyEnabled = config.EnvoyPatchPolicyEnabled + } + } translator := &Translator{ - GatewayControllerName: egv1a1.GatewayControllerName, - GatewayClassName: "envoy-gateway-class", - GlobalRateLimitEnabled: true, + GatewayControllerName: egv1a1.GatewayControllerName, + GatewayClassName: "envoy-gateway-class", + GlobalRateLimitEnabled: true, + EnvoyPatchPolicyEnabled: envoyPatchPolicyEnabled, } // Add common test fixtures - for i := 1; i <= 3; i++ { + for i := 1; i <= 4; i++ { svcName := "service-" + strconv.Itoa(i) epSliceName := "endpointslice-" + strconv.Itoa(i) resources.Services = append(resources.Services, @@ -524,9 +542,9 @@ func TestIsValidHostname(t *testing.T) { t.Run(tc.name, func(t *testing.T) { err := translator.validateHostname(tc.hostname) if tc.err == "" { - assert.Nil(t, err) + require.NoError(t, err) } else { - assert.EqualError(t, err, tc.err) + require.EqualError(t, err, tc.err) } }) } diff --git a/internal/gatewayapi/validate.go b/internal/gatewayapi/validate.go index fce666cfb0a..e694f1f9e7a 100644 --- a/internal/gatewayapi/validate.go +++ b/internal/gatewayapi/validate.go @@ -18,6 +18,8 @@ import ( gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" gwapiv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" + + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" ) func (t *Translator) validateBackendRef(backendRef *gwapiv1a2.BackendRef, parentRef *RouteParentContext, route RouteContext, @@ -58,7 +60,7 @@ func (t *Translator) validateBackendRefGroup(backendRef *gwapiv1a2.BackendRef, p gwapiv1.RouteConditionResolvedRefs, metav1.ConditionFalse, gwapiv1.RouteReasonInvalidKind, - fmt.Sprintf("Group is invalid, only the core API group (specified by omitting the group field or setting it to an empty string) and %s is supported", GroupMultiClusterService), + fmt.Sprintf("Group is invalid, only the core API group (specified by omitting the group field or setting it to an empty string) and %s are supported", GroupMultiClusterService), ) return false } @@ -71,7 +73,7 @@ func (t *Translator) validateBackendRefKind(backendRef *gwapiv1a2.BackendRef, pa gwapiv1.RouteConditionResolvedRefs, metav1.ConditionFalse, gwapiv1.RouteReasonInvalidKind, - "Kind is invalid, only Service and MCS ServiceImport is supported", + "Kind is invalid, only Service and MCS ServiceImport are supported", ) return false } @@ -733,23 +735,76 @@ func (t *Translator) validateHostname(hostname string) error { func (t *Translator) validateSecretRef( allowCrossNamespace bool, from crossNamespaceFrom, - secretRef gwapiv1b1.SecretObjectReference, + secretObjRef gwapiv1b1.SecretObjectReference, resources *Resources) (*v1.Secret, error) { - if secretRef.Group != nil && string(*secretRef.Group) != "" { - return nil, errors.New("secret ref group must be unspecified/empty") - } - if secretRef.Kind != nil && string(*secretRef.Kind) != KindSecret { - return nil, fmt.Errorf("secret ref kind must be %s", KindSecret) + if err := t.validateSecretObjectRef(allowCrossNamespace, from, secretObjRef, resources); err != nil { + return nil, err } secretNamespace := from.namespace + if secretObjRef.Namespace != nil { + secretNamespace = string(*secretObjRef.Namespace) + } + secret := resources.GetSecret(secretNamespace, string(secretObjRef.Name)) + + if secret == nil { + return nil, fmt.Errorf( + "secret %s/%s does not exist", secretNamespace, secretObjRef.Name) + } + + return secret, nil +} + +func (t *Translator) validateConfigMapRef( + allowCrossNamespace bool, + from crossNamespaceFrom, + secretObjRef gwapiv1b1.SecretObjectReference, + resources *Resources) (*v1.ConfigMap, error) { + + if err := t.validateSecretObjectRef(allowCrossNamespace, from, secretObjRef, resources); err != nil { + return nil, err + } + + configMapNamespace := from.namespace + if secretObjRef.Namespace != nil { + configMapNamespace = string(*secretObjRef.Namespace) + } + configMap := resources.GetConfigMap(configMapNamespace, string(secretObjRef.Name)) + + if configMap == nil { + return nil, fmt.Errorf( + "configmap %s/%s does not exist", configMapNamespace, secretObjRef.Name) + } + + return configMap, nil +} + +func (t *Translator) validateSecretObjectRef( + allowCrossNamespace bool, + from crossNamespaceFrom, + secretRef gwapiv1b1.SecretObjectReference, + resources *Resources) error { + var kind string + if secretRef.Group != nil && string(*secretRef.Group) != "" { + return errors.New("secret ref group must be unspecified/empty") + } + + if secretRef.Kind == nil { // nolint + kind = KindSecret + } else if string(*secretRef.Kind) == KindSecret { + kind = KindSecret + } else if string(*secretRef.Kind) == KindConfigMap { + kind = KindConfigMap + } else { + return fmt.Errorf("secret ref kind must be %s", KindSecret) + } if secretRef.Namespace != nil && string(*secretRef.Namespace) != "" && string(*secretRef.Namespace) != from.namespace { if !allowCrossNamespace { - return nil, fmt.Errorf( + return fmt.Errorf( "secret ref namespace must be unspecified/empty or %s", from.namespace) } @@ -758,27 +813,101 @@ func (t *Translator) validateSecretRef( from, crossNamespaceTo{ group: "", - kind: KindSecret, + kind: kind, namespace: string(*secretRef.Namespace), name: string(secretRef.Name), }, resources.ReferenceGrants, ) { - return nil, - fmt.Errorf( - "certificate ref to secret %s/%s not permitted by any ReferenceGrant", - *secretRef.Namespace, secretRef.Name) + return fmt.Errorf( + "certificate ref to secret %s/%s not permitted by any ReferenceGrant", + *secretRef.Namespace, secretRef.Name) } - secretNamespace = string(*secretRef.Namespace) } - secret := resources.GetSecret(secretNamespace, string(secretRef.Name)) + return nil +} - if secret == nil { - return nil, fmt.Errorf( - "secret %s/%s does not exist", secretNamespace, secretRef.Name) +// TODO: zhaohuabing combine this function with the one in the route translator +// validateExtServiceBackendReference validates the backend reference for an +// external service referenced by an EG policy. +// This can also be used for the other external services deployed in the cluster, +// such as the external processing filter, gRPC Access Log Service, etc. +// It checks: +// 1. The group is nil or empty, indicating the core API group. +// 2. The kind is Service. +// 3. The port is specified. +// 4. The service exists and the specified port is found. +// 5. The cross-namespace reference is permitted by the ReferenceGrants if the +// namespace is different from the policy's namespace. +func (t *Translator) validateExtServiceBackendReference( + backendRef *gwapiv1.BackendObjectReference, + ownerNamespace string, + resources *Resources) error { + + // These are sanity checks, they should never happen because the API server + // should have caught them + if backendRef.Group != nil && *backendRef.Group != "" { + return errors.New( + "group is invalid, only the core API group (specified by omitting" + + " the group field or setting it to an empty string) is supported") + } + if backendRef.Kind != nil && *backendRef.Kind != KindService { + return errors.New("kind is invalid, only Service (specified by omitting " + + "the kind field or setting it to 'Service') is supported") + } + if backendRef.Port == nil { + return errors.New("a valid port number corresponding to a port on the Service must be specified") } - return secret, nil + // check if the service is valid + serviceNamespace := NamespaceDerefOr(backendRef.Namespace, ownerNamespace) + service := resources.GetService(serviceNamespace, string(backendRef.Name)) + if service == nil { + return fmt.Errorf("service %s/%s not found", serviceNamespace, backendRef.Name) + } + var portFound bool + for _, port := range service.Spec.Ports { + portProtocol := port.Protocol + if port.Protocol == "" { // Default protocol is TCP + portProtocol = v1.ProtocolTCP + } + // currently only HTTP and GRPC are supported, both of which are TCP + if port.Port == int32(*backendRef.Port) && portProtocol == v1.ProtocolTCP { + portFound = true + break + } + } + + if !portFound { + return fmt.Errorf( + "TCP Port %d not found on service %s/%s", + *backendRef.Port, serviceNamespace, string(backendRef.Name), + ) + } + + // check if the cross-namespace reference is permitted + if backendRef.Namespace != nil && string(*backendRef.Namespace) != "" && + string(*backendRef.Namespace) != ownerNamespace { + if !t.validateCrossNamespaceRef( + crossNamespaceFrom{ + group: egv1a1.GroupName, + kind: KindSecurityPolicy, + namespace: ownerNamespace, + }, + crossNamespaceTo{ + group: GroupDerefOr(backendRef.Group, ""), + kind: KindDerefOr(backendRef.Kind, KindService), + namespace: string(*backendRef.Namespace), + name: string(backendRef.Name), + }, + resources.ReferenceGrants, + ) { + return fmt.Errorf( + "backend ref to %s %s/%s not permitted by any ReferenceGrant", + KindService, *backendRef.Namespace, backendRef.Name) + } + } + return nil } diff --git a/internal/gatewayapi/zz_generated.deepcopy.go b/internal/gatewayapi/zz_generated.deepcopy.go index 56335dc5bc9..eb31a82d5e9 100644 --- a/internal/gatewayapi/zz_generated.deepcopy.go +++ b/internal/gatewayapi/zz_generated.deepcopy.go @@ -160,6 +160,17 @@ func (in *Resources) DeepCopyInto(out *Resources) { } } } + if in.ConfigMaps != nil { + in, out := &in.ConfigMaps, &out.ConfigMaps + *out = make([]*corev1.ConfigMap, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(corev1.ConfigMap) + (*in).DeepCopyInto(*out) + } + } + } if in.EnvoyProxy != nil { in, out := &in.EnvoyProxy, &out.EnvoyProxy *out = new(apiv1alpha1.EnvoyProxy) diff --git a/internal/infrastructure/kubernetes/proxy/resource.go b/internal/infrastructure/kubernetes/proxy/resource.go index b4ccc760286..7bedbd9cb23 100644 --- a/internal/infrastructure/kubernetes/proxy/resource.go +++ b/internal/infrastructure/kubernetes/proxy/resource.go @@ -173,6 +173,10 @@ func expectedProxyContainers(infra *ir.ProxyInfra, args = append(args, fmt.Sprintf("--component-log-level %s", componentsLogLevel)) } + if infra.Config != nil { + args = append(args, infra.Config.Spec.ExtraArgs...) + } + containers := []corev1.Container{ { Name: envoyContainerName, diff --git a/internal/infrastructure/kubernetes/proxy/resource_provider.go b/internal/infrastructure/kubernetes/proxy/resource_provider.go index 358350400dc..7ed28fb75b8 100644 --- a/internal/infrastructure/kubernetes/proxy/resource_provider.go +++ b/internal/infrastructure/kubernetes/proxy/resource_provider.go @@ -46,7 +46,7 @@ func (r *ResourceRender) Name() string { func (r *ResourceRender) ServiceAccount() (*corev1.ServiceAccount, error) { // Set the labels based on the owning gateway name. labels := envoyLabels(r.infra.GetProxyMetadata().Labels) - if (len(labels[gatewayapi.OwningGatewayNameLabel]) == 0 || len(labels[gatewayapi.OwningGatewayNamespaceLabel]) == 0) && len(labels[gatewayapi.OwningGatewayClassLabel]) == 0 { + if OwningGatewayLabelsAbsent(labels) { return nil, fmt.Errorf("missing owning gateway labels") } @@ -99,7 +99,7 @@ func (r *ResourceRender) Service() (*corev1.Service, error) { // Set the labels based on the owning gatewayclass name. labels := envoyLabels(r.infra.GetProxyMetadata().Labels) - if (len(labels[gatewayapi.OwningGatewayNameLabel]) == 0 || len(labels[gatewayapi.OwningGatewayNamespaceLabel]) == 0) && len(labels[gatewayapi.OwningGatewayClassLabel]) == 0 { + if OwningGatewayLabelsAbsent(labels) { return nil, fmt.Errorf("missing owning gateway labels") } @@ -120,7 +120,18 @@ func (r *ResourceRender) Service() (*corev1.Service, error) { serviceSpec := resource.ExpectedServiceSpec(envoyServiceConfig) serviceSpec.Ports = ports serviceSpec.Selector = resource.GetSelector(labels).MatchLabels - serviceSpec.ExternalIPs = r.infra.Addresses + + if (*envoyServiceConfig.Type) == egv1a1.ServiceTypeClusterIP { + if len(r.infra.Addresses) > 0 { + // Since K8s Service requires specify no more than one IP for each IP family + // So we only use the first address + // if address is not set, the automatically assigned clusterIP is used + serviceSpec.ClusterIP = r.infra.Addresses[0] + serviceSpec.ClusterIPs = r.infra.Addresses[0:1] + } + } else { + serviceSpec.ExternalIPs = r.infra.Addresses + } svc := &corev1.Service{ TypeMeta: metav1.TypeMeta{ @@ -143,7 +154,7 @@ func (r *ResourceRender) Service() (*corev1.Service, error) { func (r *ResourceRender) ConfigMap() (*corev1.ConfigMap, error) { // Set the labels based on the owning gateway name. labels := envoyLabels(r.infra.GetProxyMetadata().Labels) - if (len(labels[gatewayapi.OwningGatewayNameLabel]) == 0 || len(labels[gatewayapi.OwningGatewayNamespaceLabel]) == 0) && len(labels[gatewayapi.OwningGatewayClassLabel]) == 0 { + if OwningGatewayLabelsAbsent(labels) { return nil, fmt.Errorf("missing owning gateway labels") } @@ -184,7 +195,7 @@ func (r *ResourceRender) Deployment() (*appsv1.Deployment, error) { dpAnnotations := r.infra.GetProxyMetadata().Annotations labels := r.infra.GetProxyMetadata().Labels dpLabels := envoyLabels(labels) - if (len(dpLabels[gatewayapi.OwningGatewayNameLabel]) == 0 || len(dpLabels[gatewayapi.OwningGatewayNamespaceLabel]) == 0) && len(dpLabels[gatewayapi.OwningGatewayClassLabel]) == 0 { + if OwningGatewayLabelsAbsent(dpLabels) { return nil, fmt.Errorf("missing owning gateway labels") } @@ -294,3 +305,10 @@ func (r *ResourceRender) HorizontalPodAutoscaler() (*autoscalingv2.HorizontalPod return hpa, nil } + +// OwningGatewayLabelsAbsent Check if labels are missing some OwningGatewayLabels +func OwningGatewayLabelsAbsent(labels map[string]string) bool { + return (len(labels[gatewayapi.OwningGatewayNameLabel]) == 0 || + len(labels[gatewayapi.OwningGatewayNamespaceLabel]) == 0) && + len(labels[gatewayapi.OwningGatewayClassLabel]) == 0 +} diff --git a/internal/infrastructure/kubernetes/proxy/resource_provider_test.go b/internal/infrastructure/kubernetes/proxy/resource_provider_test.go index 185084ec22e..8a41fba535c 100644 --- a/internal/infrastructure/kubernetes/proxy/resource_provider_test.go +++ b/internal/infrastructure/kubernetes/proxy/resource_provider_test.go @@ -42,6 +42,13 @@ func newTestInfraWithAnnotations(annotations map[string]string) *ir.Infra { return newTestInfraWithAnnotationsAndLabels(annotations, nil) } +func newTestInfraWithAddresses(addresses []string) *ir.Infra { + infra := newTestInfraWithAnnotationsAndLabels(nil, nil) + infra.Proxy.Addresses = addresses + + return infra +} + func newTestInfraWithAnnotationsAndLabels(annotations, labels map[string]string) *ir.Infra { i := ir.NewInfra() @@ -83,6 +90,7 @@ func TestDeployment(t *testing.T) { bootstrap string telemetry *egv1a1.ProxyTelemetry concurrency *int32 + extraArgs []string }{ { caseName: "default", @@ -423,6 +431,11 @@ func TestDeployment(t *testing.T) { }, }, }, + { + caseName: "with-extra-args", + infra: newTestInfra(), + extraArgs: []string{"--key1 val1", "--key2 val2"}, + }, } for _, tc := range cases { t.Run(tc.caseName, func(t *testing.T) { @@ -461,6 +474,10 @@ func TestDeployment(t *testing.T) { tc.infra.Proxy.Config.Spec.Concurrency = tc.concurrency } + if len(tc.extraArgs) > 0 { + tc.infra.Proxy.Config.Spec.ExtraArgs = tc.extraArgs + } + r := NewResourceRender(cfg.Namespace, tc.infra.GetProxyInfra()) dp, err := r.Deployment() require.NoError(t, err) @@ -538,6 +555,15 @@ func TestService(t *testing.T) { }, }, }, + { + caseName: "clusterIP-custom-addresses", + infra: newTestInfraWithAddresses([]string{ + "10.102.168.100", + }), + service: &egv1a1.KubernetesServiceSpec{ + Type: &svcType, + }, + }, } for _, tc := range cases { t.Run(tc.caseName, func(t *testing.T) { @@ -736,3 +762,55 @@ func loadHPA(caseName string) (*autoscalingv2.HorizontalPodAutoscaler, error) { _ = yaml.Unmarshal(hpaYAML, hpa) return hpa, nil } + +func TestOwningGatewayLabelsAbsent(t *testing.T) { + + cases := []struct { + caseName string + labels map[string]string + expect bool + }{ + { + caseName: "OwningGatewayClassLabel exist, but lack OwningGatewayNameLabel or OwningGatewayNamespaceLabel", + labels: map[string]string{ + "gateway.envoyproxy.io/owning-gatewayclass": "eg-class", + }, + expect: false, + }, + { + caseName: "OwningGatewayNameLabel and OwningGatewayNamespaceLabel exist, but lack OwningGatewayClassLabel", + labels: map[string]string{ + "gateway.envoyproxy.io/owning-gateway-name": "eg", + "gateway.envoyproxy.io/owning-gateway-namespace": "default", + }, + expect: false, + }, + { + caseName: "OwningGatewayNameLabel exist, but lack OwningGatewayClassLabel and OwningGatewayNamespaceLabel", + labels: map[string]string{ + "gateway.envoyproxy.io/owning-gateway-name": "eg", + }, + expect: true, + }, + { + caseName: "OwningGatewayNamespaceLabel exist, but lack OwningGatewayClassLabel and OwningGatewayNameLabel", + labels: map[string]string{ + "gateway.envoyproxy.io/owning-gateway-namespace": "default", + }, + expect: true, + }, + { + caseName: "lack all labels", + labels: map[string]string{}, + expect: true, + }, + } + + for _, tc := range cases { + t.Run(tc.caseName, func(t *testing.T) { + actual := OwningGatewayLabelsAbsent(tc.labels) + require.Equal(t, tc.expect, actual) + }) + } + +} diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml index 3edbc78328a..be74dfcff76 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml @@ -50,7 +50,7 @@ spec: fieldRef: apiVersion: v1 fieldPath: metadata.name - image: envoyproxy/envoy-dev:latest + image: envoyproxy/envoy:distroless-dev imagePullPolicy: IfNotPresent name: envoy ports: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml index a8532b8dbbb..93b5a6f2f2e 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml @@ -51,7 +51,7 @@ spec: fieldRef: apiVersion: v1 fieldPath: metadata.name - image: envoyproxy/envoy-dev:latest + image: envoyproxy/envoy:distroless-dev imagePullPolicy: IfNotPresent name: envoy ports: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml index dfec805cd7c..98428f0a37d 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml @@ -55,6 +55,8 @@ spec: - 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 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 496954f905d..2b141eca671 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml @@ -54,6 +54,8 @@ spec: - 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 diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml index bb5f0855fbf..08b6d412883 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml @@ -52,6 +52,8 @@ spec: - 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 diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml index 9287d989dab..8479979b552 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml @@ -50,6 +50,8 @@ spec: - 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 @@ -149,7 +151,7 @@ spec: fieldRef: apiVersion: v1 fieldPath: metadata.name - image: envoyproxy/envoy-dev:latest + image: envoyproxy/envoy:distroless-dev imagePullPolicy: IfNotPresent name: envoy ports: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/enable-prometheus.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/enable-prometheus.yaml index 2ea1e80535f..811717c40fe 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/enable-prometheus.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/enable-prometheus.yaml @@ -54,6 +54,8 @@ spec: - 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 @@ -175,7 +177,7 @@ spec: fieldRef: apiVersion: v1 fieldPath: metadata.name - image: envoyproxy/envoy-dev:latest + image: envoyproxy/envoy:distroless-dev imagePullPolicy: IfNotPresent name: envoy ports: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml index a8cf77eae24..553cb1733b7 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml @@ -52,6 +52,8 @@ spec: - 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 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 a959265e023..6d5dce5112f 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 @@ -62,6 +62,8 @@ spec: - 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 @@ -161,7 +163,7 @@ spec: fieldRef: apiVersion: v1 fieldPath: metadata.name - image: envoyproxy/envoy-dev:latest + image: envoyproxy/envoy:distroless-dev imagePullPolicy: IfNotPresent name: envoy ports: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml index 4f77ef6f0df..c285f7aab2e 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml @@ -52,6 +52,8 @@ spec: - 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 diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml index 6fabe74a77c..8975df8b435 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml @@ -56,6 +56,8 @@ spec: - 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 @@ -155,7 +157,7 @@ spec: fieldRef: apiVersion: v1 fieldPath: metadata.name - image: envoyproxy/envoy-dev:latest + image: envoyproxy/envoy:distroless-dev imagePullPolicy: IfNotPresent name: envoy ports: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml index 3e7f505702d..3c60a423cb1 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml @@ -51,7 +51,7 @@ spec: fieldRef: apiVersion: v1 fieldPath: metadata.name - image: envoyproxy/envoy-dev:latest + image: envoyproxy/envoy:distroless-dev imagePullPolicy: IfNotPresent name: envoy ports: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml new file mode 100644 index 00000000000..f850773cb4d --- /dev/null +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml @@ -0,0 +1,208 @@ +apiVersion: apps/v1 +kind: Deployment +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: default + gateway.envoyproxy.io/owning-gateway-namespace: default + name: envoy-default-37a8eec1 + namespace: envoy-gateway-system +spec: + replicas: 1 + strategy: + type: RollingUpdate + selector: + matchLabels: + app.kubernetes.io/name: envoy + app.kubernetes.io/component: proxy + app.kubernetes.io/managed-by: envoy-gateway + gateway.envoyproxy.io/owning-gateway-name: default + gateway.envoyproxy.io/owning-gateway-namespace: default + template: + 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: default + gateway.envoyproxy.io/owning-gateway-namespace: default + spec: + automountServiceAccountToken: false + containers: + - args: + - --service-cluster default + - --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 + 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-ready-0.0.0.0-19001 + address: + socket_address: + address: 0.0.0.0 + port_value: 19001 + protocol: TCP + 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-ready-http + route_config: + name: local_route + http_filters: + - name: envoy.filters.http.health_check + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.health_check.v3.HealthCheck + pass_through_mode: false + headers: + - name: ":path" + string_match: + exact: /ready + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + clusters: + - 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 + 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 + 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 + tls_certificate_sds_secret_configs: + - name: xds_certificate + sds_config: + path_config_source: + path: "/sds/xds-certificate.json" + resource_api_version: V3 + validation_context_sds_secret_config: + name: xds_trusted_ca + sds_config: + path_config_source: + path: "/sds/xds-trusted-ca.json" + resource_api_version: V3 + - --log-level warn + - --cpuset-threads + - --key1 val1 + - --key2 val2 + command: + - envoy + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + image: envoyproxy/envoy:distroless-dev + imagePullPolicy: IfNotPresent + name: envoy + ports: + - containerPort: 8080 + name: EnvoyH-d76a15e2 + protocol: TCP + - containerPort: 8443 + name: EnvoyH-6658f727 + protocol: TCP + resources: + requests: + cpu: 100m + memory: 512Mi + readinessProbe: + httpGet: + path: /ready + port: 19001 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /certs + name: certs + readOnly: true + - mountPath: /sds + name: sds + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + serviceAccountName: envoy-default-37a8eec1 + terminationGracePeriodSeconds: 300 + volumes: + - name: certs + secret: + secretName: envoy + defaultMode: 420 + - configMap: + defaultMode: 420 + items: + - key: xds-trusted-ca.json + path: xds-trusted-ca.json + - key: xds-certificate.json + path: xds-certificate.json + name: envoy-default-37a8eec1 + optional: false + name: sds + revisionHistoryLimit: 10 + progressDeadlineSeconds: 600 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 71adf745f02..3e488693099 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 @@ -50,6 +50,8 @@ spec: - 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 @@ -149,7 +151,7 @@ spec: fieldRef: apiVersion: v1 fieldPath: metadata.name - image: envoyproxy/envoy-dev:latest + image: envoyproxy/envoy:distroless-dev imagePullPolicy: IfNotPresent name: envoy ports: 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 01c1390e55d..c8fde97892f 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml @@ -50,6 +50,8 @@ spec: - 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 @@ -149,7 +151,7 @@ spec: fieldRef: apiVersion: v1 fieldPath: metadata.name - image: envoyproxy/envoy-dev:latest + image: envoyproxy/envoy:distroless-dev imagePullPolicy: IfNotPresent name: envoy ports: 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 88ff315efdf..7233f15ebd5 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 @@ -50,6 +50,8 @@ spec: - 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 @@ -149,7 +151,7 @@ spec: fieldRef: apiVersion: v1 fieldPath: metadata.name - image: envoyproxy/envoy-dev:latest + image: envoyproxy/envoy:distroless-dev imagePullPolicy: IfNotPresent name: envoy ports: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/services/clusterIP-custom-addresses.yaml b/internal/infrastructure/kubernetes/proxy/testdata/services/clusterIP-custom-addresses.yaml new file mode 100644 index 00000000000..336e3fe8ee0 --- /dev/null +++ b/internal/infrastructure/kubernetes/proxy/testdata/services/clusterIP-custom-addresses.yaml @@ -0,0 +1,32 @@ +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: default + gateway.envoyproxy.io/owning-gateway-namespace: default + name: envoy-default-37a8eec1 + namespace: envoy-gateway-system +spec: + clusterIP: 10.102.168.100 + clusterIPs: + - 10.102.168.100 + ports: + - name: envoy-EnvoyHTTPPort-d76a15e2 + port: 0 + protocol: TCP + targetPort: 8080 + - name: envoy-EnvoyHTTPSPort-6658f727 + 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: default + gateway.envoyproxy.io/owning-gateway-namespace: default + sessionAffinity: None + type: ClusterIP diff --git a/internal/infrastructure/kubernetes/proxy_serviceaccount_test.go b/internal/infrastructure/kubernetes/proxy_serviceaccount_test.go index dbba0492d43..0cde399a2df 100644 --- a/internal/infrastructure/kubernetes/proxy_serviceaccount_test.go +++ b/internal/infrastructure/kubernetes/proxy_serviceaccount_test.go @@ -194,7 +194,7 @@ func TestCreateOrUpdateProxyServiceAccount(t *testing.T) { require.NoError(t, kube.Client.Get(context.Background(), client.ObjectKeyFromObject(actual), actual)) opts := cmpopts.IgnoreFields(metav1.ObjectMeta{}, "ResourceVersion") - assert.Equal(t, true, cmp.Equal(tc.want, actual, opts)) + assert.True(t, cmp.Equal(tc.want, actual, opts)) }) } } diff --git a/internal/infrastructure/kubernetes/ratelimit_serviceaccount_test.go b/internal/infrastructure/kubernetes/ratelimit_serviceaccount_test.go index 1ddf5cd4d8a..215c091fb36 100644 --- a/internal/infrastructure/kubernetes/ratelimit_serviceaccount_test.go +++ b/internal/infrastructure/kubernetes/ratelimit_serviceaccount_test.go @@ -121,7 +121,7 @@ func TestCreateOrUpdateRateLimitServiceAccount(t *testing.T) { require.NoError(t, kube.Client.Get(context.Background(), client.ObjectKeyFromObject(actual), actual)) opts := cmpopts.IgnoreFields(metav1.ObjectMeta{}, "ResourceVersion") - assert.Equal(t, true, cmp.Equal(tc.want, actual, opts)) + assert.True(t, cmp.Equal(tc.want, actual, opts)) }) } } diff --git a/internal/ir/infra.go b/internal/ir/infra.go index 3432505df3e..5c2a95505a8 100644 --- a/internal/ir/infra.go +++ b/internal/ir/infra.go @@ -13,6 +13,7 @@ import ( "golang.org/x/exp/slices" utilerrors "k8s.io/apimachinery/pkg/util/errors" + "sigs.k8s.io/yaml" "github.com/envoyproxy/gateway/api/v1alpha1" ) @@ -28,6 +29,11 @@ type Infra struct { Proxy *ProxyInfra `json:"proxy" yaml:"proxy"` } +func (i Infra) YAMLString() string { + y, _ := yaml.Marshal(&i) + return string(y) +} + // ProxyInfra defines managed proxy infrastructure. // +k8s:deepcopy-gen=true type ProxyInfra struct { diff --git a/internal/ir/xds.go b/internal/ir/xds.go index aa24e746802..bb2a9d36096 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -8,56 +8,59 @@ package ir import ( "cmp" "errors" - "net" "net/http" + "net/netip" "reflect" - "github.com/tetratelabs/multierror" "golang.org/x/exp/slices" - apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/util/validation" + "sigs.k8s.io/yaml" egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" egv1a1validation "github.com/envoyproxy/gateway/api/v1alpha1/validation" ) var ( - ErrListenerNameEmpty = errors.New("field Name must be specified") - ErrListenerAddressInvalid = errors.New("field Address must be a valid IP address") - ErrListenerPortInvalid = errors.New("field Port specified is invalid") - ErrHTTPListenerHostnamesEmpty = errors.New("field Hostnames must be specified with at least a single hostname entry") - ErrTCPListenerSNIsEmpty = errors.New("field SNIs must be specified with at least a single server name entry") - ErrTLSServerCertEmpty = errors.New("field ServerCertificate must be specified") - ErrTLSPrivateKey = errors.New("field PrivateKey must be specified") - ErrHTTPRouteNameEmpty = errors.New("field Name must be specified") - ErrHTTPRouteHostnameEmpty = errors.New("field Hostname must be specified") - ErrDestinationNameEmpty = errors.New("field Name must be specified") - ErrDestEndpointHostInvalid = errors.New("field Address must be a valid IP or FQDN address") - ErrDestEndpointPortInvalid = errors.New("field Port specified is invalid") - ErrStringMatchConditionInvalid = errors.New("only one of the Exact, Prefix, SafeRegex or Distinct fields must be set") - ErrStringMatchNameIsEmpty = errors.New("field Name must be specified") - ErrDirectResponseStatusInvalid = errors.New("only HTTP status codes 100 - 599 are supported for DirectResponse") - ErrRedirectUnsupportedStatus = errors.New("only HTTP status codes 301 and 302 are supported for redirect filters") - ErrRedirectUnsupportedScheme = errors.New("only http and https are supported for the scheme in redirect filters") - ErrHTTPPathModifierDoubleReplace = errors.New("redirect filter cannot have a path modifier that supplies both fullPathReplace and prefixMatchReplace") - ErrHTTPPathModifierNoReplace = errors.New("redirect filter cannot have a path modifier that does not supply either fullPathReplace or prefixMatchReplace") - ErrAddHeaderEmptyName = errors.New("header modifier filter cannot configure a header without a name to be added") - ErrAddHeaderDuplicate = errors.New("header modifier filter attempts to add the same header more than once (case insensitive)") - ErrRemoveHeaderDuplicate = errors.New("header modifier filter attempts to remove the same header more than once (case insensitive)") - ErrLoadBalancerInvalid = errors.New("loadBalancer setting is invalid, only one setting can be set") - ErrHealthCheckTimeoutInvalid = errors.New("field HealthCheck.Timeout must be specified") - ErrHealthCheckIntervalInvalid = errors.New("field HealthCheck.Interval must be specified") - ErrHealthCheckUnhealthyThresholdInvalid = errors.New("field HealthCheck.UnhealthyThreshold should be greater than 0") - ErrHealthCheckHealthyThresholdInvalid = errors.New("field HealthCheck.HealthyThreshold should be greater than 0") - ErrHealthCheckerInvalid = errors.New("health checker setting is invalid, only one health checker can be set") - ErrHCHTTPPathInvalid = errors.New("field HTTPHealthChecker.Path should be specified") - ErrHCHTTPMethodInvalid = errors.New("only one of the GET, HEAD, POST, DELETE, OPTIONS, TRACE, PATCH of HTTPHealthChecker.Method could be set") - ErrHCHTTPExpectedStatusesInvalid = errors.New("field HTTPHealthChecker.ExpectedStatuses should be specified") - ErrHealthCheckPayloadInvalid = errors.New("one of Text, Binary fields must be set in payload") - ErrHTTPStatusInvalid = errors.New("HTTPStatus should be in [200,600)") + ErrListenerNameEmpty = errors.New("field Name must be specified") + ErrListenerAddressInvalid = errors.New("field Address must be a valid IP address") + ErrListenerPortInvalid = errors.New("field Port specified is invalid") + ErrHTTPListenerHostnamesEmpty = errors.New("field Hostnames must be specified with at least a single hostname entry") + ErrTCPListenerSNIsEmpty = errors.New("field SNIs must be specified with at least a single server name entry") + ErrTLSServerCertEmpty = errors.New("field ServerCertificate must be specified") + ErrTLSPrivateKey = errors.New("field PrivateKey must be specified") + ErrHTTPRouteNameEmpty = errors.New("field Name must be specified") + ErrHTTPRouteHostnameEmpty = errors.New("field Hostname must be specified") + ErrDestinationNameEmpty = errors.New("field Name must be specified") + ErrDestEndpointHostInvalid = errors.New("field Address must be a valid IP or FQDN address") + ErrDestEndpointPortInvalid = errors.New("field Port specified is invalid") + ErrStringMatchConditionInvalid = errors.New("only one of the Exact, Prefix, SafeRegex or Distinct fields must be set") + ErrStringMatchNameIsEmpty = errors.New("field Name must be specified") + ErrDirectResponseStatusInvalid = errors.New("only HTTP status codes 100 - 599 are supported for DirectResponse") + ErrRedirectUnsupportedStatus = errors.New("only HTTP status codes 301 and 302 are supported for redirect filters") + ErrRedirectUnsupportedScheme = errors.New("only http and https are supported for the scheme in redirect filters") + ErrHTTPPathModifierDoubleReplace = errors.New("redirect filter cannot have a path modifier that supplies both fullPathReplace and prefixMatchReplace") + ErrHTTPPathModifierNoReplace = errors.New("redirect filter cannot have a path modifier that does not supply either fullPathReplace or prefixMatchReplace") + ErrAddHeaderEmptyName = errors.New("header modifier filter cannot configure a header without a name to be added") + ErrAddHeaderDuplicate = errors.New("header modifier filter attempts to add the same header more than once (case insensitive)") + ErrRemoveHeaderDuplicate = errors.New("header modifier filter attempts to remove the same header more than once (case insensitive)") + ErrLoadBalancerInvalid = errors.New("loadBalancer setting is invalid, only one setting can be set") + ErrHealthCheckTimeoutInvalid = errors.New("field HealthCheck.Timeout must be specified") + ErrHealthCheckIntervalInvalid = errors.New("field HealthCheck.Interval must be specified") + ErrHealthCheckUnhealthyThresholdInvalid = errors.New("field HealthCheck.UnhealthyThreshold should be greater than 0") + ErrHealthCheckHealthyThresholdInvalid = errors.New("field HealthCheck.HealthyThreshold should be greater than 0") + ErrHealthCheckerInvalid = errors.New("health checker setting is invalid, only one health checker can be set") + ErrHCHTTPPathInvalid = errors.New("field HTTPHealthChecker.Path should be specified") + ErrHCHTTPMethodInvalid = errors.New("only one of the GET, HEAD, POST, DELETE, OPTIONS, TRACE, PATCH of HTTPHealthChecker.Method could be set") + ErrHCHTTPExpectedStatusesInvalid = errors.New("field HTTPHealthChecker.ExpectedStatuses should be specified") + ErrHealthCheckPayloadInvalid = errors.New("one of Text, Binary fields must be set in payload") + ErrHTTPStatusInvalid = errors.New("HTTPStatus should be in [200,600)") + ErrOutlierDetectionBaseEjectionTimeInvalid = errors.New("field OutlierDetection.BaseEjectionTime must be specified") + ErrOutlierDetectionIntervalInvalid = errors.New("field OutlierDetection.Interval must be specified") + + redacted = []byte("[redacted]") ) // Xds holds the intermediate representation of a Gateway and is @@ -113,17 +116,17 @@ func (x Xds) Validate() error { var errs error for _, http := range x.HTTP { if err := http.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } for _, tcp := range x.TCP { if err := tcp.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } for _, udp := range x.UDP { if err := udp.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } return errs @@ -156,20 +159,29 @@ func (x Xds) GetUDPListener(name string) *UDPListener { return nil } +func (x Xds) YAMLString() string { + y, _ := yaml.Marshal(x.Printable()) + return string(y) +} + // Printable returns a deep copy of the resource that can be safely logged. func (x Xds) Printable() *Xds { out := x.DeepCopy() for _, listener := range out.HTTP { // Omit field - listener.TLS = nil + if listener.TLS != nil { + for i := range listener.TLS.Certificates { + listener.TLS.Certificates[i].PrivateKey = redacted + } + } for _, route := range listener.Routes { // Omit field if route.OIDC != nil { - route.OIDC.ClientSecret = []byte{} + route.OIDC.ClientSecret = redacted } if route.BasicAuth != nil { - route.BasicAuth.Users = []byte{} + route.BasicAuth.Users = redacted } } } @@ -199,41 +211,47 @@ type HTTPListener struct { IsHTTP2 bool `json:"isHTTP2" yaml:"isHTTP2"` // TCPKeepalive configuration for the listener TCPKeepalive *TCPKeepalive `json:"tcpKeepalive,omitempty" yaml:"tcpKeepalive,omitempty"` - // SuppressEnvoyHeaders controls if "x-envoy-" headers are suppressed by the HTTP Router filter - // Refer to https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/router/v3/router.proto#extensions-filters-http-router-v3-router - SuppressEnvoyHeaders bool `json:"suppressEnvoyHeaders,omitempty" yaml:"suppressEnvoyHeaders,omitempty"` + // Headers configures special header management for the listener + Headers *HeaderSettings `json:"headers,omitempty" yaml:"headers,omitempty"` // EnableProxyProtocol enables the listener to interpret proxy protocol header EnableProxyProtocol bool `json:"enableProxyProtocol,omitempty" yaml:"enableProxyProtocol,omitempty"` + // ClientIPDetection controls how the original client IP address is determined for requests. + ClientIPDetection *ClientIPDetectionSettings `json:"clientIPDetection,omitempty" yaml:"clientIPDetection,omitempty"` // HTTP3 provides HTTP/3 configuration on the listener. // +optional HTTP3 *HTTP3Settings `json:"http3,omitempty"` // Path contains settings for path URI manipulations Path PathSettings `json:"path,omitempty"` + // HTTP1 provides HTTP/1 configuration on the listener + // +optional + HTTP1 *HTTP1Settings `json:"http1,omitempty" yaml:"http1,omitempty"` + // ClientTimeout sets the timeout configuration for downstream connections + Timeout *ClientTimeout `json:"timeout,omitempty" yaml:"clientTimeout,omitempty"` } // Validate the fields within the HTTPListener structure func (h HTTPListener) Validate() error { var errs error if h.Name == "" { - errs = multierror.Append(errs, ErrListenerNameEmpty) + errs = errors.Join(errs, ErrListenerNameEmpty) } - if ip := net.ParseIP(h.Address); ip == nil { - errs = multierror.Append(errs, ErrListenerAddressInvalid) + if _, err := netip.ParseAddr(h.Address); err != nil { + errs = errors.Join(errs, ErrListenerAddressInvalid) } if h.Port == 0 { - errs = multierror.Append(errs, ErrListenerPortInvalid) + errs = errors.Join(errs, ErrListenerPortInvalid) } if len(h.Hostnames) == 0 { - errs = multierror.Append(errs, ErrHTTPListenerHostnamesEmpty) + errs = errors.Join(errs, ErrHTTPListenerHostnamesEmpty) } if h.TLS != nil { if err := h.TLS.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } for _, route := range h.Routes { if err := route.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } return errs @@ -259,6 +277,8 @@ const ( type TLSConfig struct { // Certificates contains the set of certificates associated with this listener Certificates []TLSCertificate `json:"certificates,omitempty" yaml:"certificates,omitempty"` + // CACertificate to verify the client + CACertificate *TLSCACertificate `json:"caCertificate,omitempty" yaml:"caCertificate,omitempty"` // MinVersion defines the minimal version of the TLS protocol supported by this listener. MinVersion *TLSVersion `json:"minVersion,omitempty" yaml:"version,omitempty"` // MaxVersion defines the maximal version of the TLS protocol supported by this listener. @@ -284,13 +304,22 @@ type TLSCertificate struct { PrivateKey []byte `json:"privateKey,omitempty" yaml:"privateKey,omitempty"` } +// TLSCACertificate holds CA Certificate to validate clients +// +k8s:deepcopy-gen=true +type TLSCACertificate struct { + // Name of the Secret object. + Name string `json:"name" yaml:"name"` + // Certificate content. + Certificate []byte `json:"certificate,omitempty" yaml:"certificate,omitempty"` +} + func (t TLSCertificate) Validate() error { var errs error if len(t.ServerCertificate) == 0 { - errs = multierror.Append(errs, ErrTLSServerCertEmpty) + errs = errors.Join(errs, ErrTLSServerCertEmpty) } if len(t.PrivateKey) == 0 { - errs = multierror.Append(errs, ErrTLSPrivateKey) + errs = errors.Join(errs, ErrTLSPrivateKey) } return errs } @@ -300,7 +329,7 @@ func (t TLSConfig) Validate() error { var errs error for _, cert := range t.Certificates { if err := cert.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } // Correct values for cipher suites, ECDH curves, and signature algorithms are @@ -327,12 +356,56 @@ type PathSettings struct { EscapedSlashesAction PathEscapedSlashAction `json:"escapedSlashesAction" yaml:"escapedSlashesAction"` } +// ClientIPDetectionSettings provides configuration for determining the original client IP address for requests. +// +k8s:deepcopy-gen=true +type ClientIPDetectionSettings egv1a1.ClientIPDetectionSettings + // BackendWeights stores the weights of valid and invalid backends for the route so that 500 error responses can be returned in the same proportions type BackendWeights struct { Valid uint32 `json:"valid" yaml:"valid"` Invalid uint32 `json:"invalid" yaml:"invalid"` } +// HTTP1Settings provides HTTP/1 configuration on the listener. +// +k8s:deepcopy-gen=true +type HTTP1Settings struct { + EnableTrailers bool `json:"enableTrailers,omitempty" yaml:"enableTrailers,omitempty"` + PreserveHeaderCase bool `json:"preserveHeaderCase,omitempty" yaml:"preserveHeaderCase,omitempty"` + HTTP10 *HTTP10Settings `json:"http10,omitempty" yaml:"http10,omitempty"` +} + +// HTTP10Settings provides HTTP/1.0 configuration on the listener. +// +k8s:deepcopy-gen=true +type HTTP10Settings struct { + // defaultHost is set to the default host that should be injected for HTTP10. If the hostname shouldn't + // be set, then defaultHost will be nil + DefaultHost *string `json:"defaultHost,omitempty" yaml:"defaultHost,omitempty"` +} + +// HeaderSettings provides configuration related to header processing on the listener. +// +k8s:deepcopy-gen=true +type HeaderSettings struct { + // EnableEnvoyHeaders controls if "x-envoy-" headers are added by the HTTP Router filter. + // The default is to suppress these headers. + // Refer to https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/router/v3/router.proto#extensions-filters-http-router-v3-router + EnableEnvoyHeaders bool `json:"enableEnvoyHeaders,omitempty" yaml:"enableEnvoyHeaders,omitempty"` +} + +// ClientTimeout sets the timeout configuration for downstream connections +// +k8s:deepcopy-gen=true +type ClientTimeout struct { + // Timeout settings for HTTP. + HTTP *HTTPClientTimeout `json:"http,omitempty" yaml:"http,omitempty"` +} + +// HTTPClientTimeout set the configuration for client HTTP. +// +k8s:deepcopy-gen=true +type HTTPClientTimeout struct { + // The duration envoy waits for the complete request reception. This timer starts upon request + // initiation and stops when either the last byte of the request is sent upstream or when the response begins. + RequestReceivedTimeout *metav1.Duration `json:"requestReceivedTimeout,omitempty" yaml:"requestReceivedTimeout,omitempty"` +} + // HTTPRoute holds the route information associated with the HTTP Route // +k8s:deepcopy-gen=true type HTTPRoute struct { @@ -369,8 +442,6 @@ type HTTPRoute struct { // RateLimit defines the more specific match conditions as well as limits for ratelimiting // the requests on this route. RateLimit *RateLimit `json:"rateLimit,omitempty" yaml:"rateLimit,omitempty"` - // Timeout is the time until which entire response is received from the upstream. - Timeout *metav1.Duration `json:"timeout,omitempty" yaml:"timeout,omitempty"` // load balancer policy to use when routing to the backend endpoints. LoadBalancer *LoadBalancer `json:"loadBalancer,omitempty" yaml:"loadBalancer,omitempty"` // CORS policy for the route. @@ -383,7 +454,9 @@ type HTTPRoute struct { ProxyProtocol *ProxyProtocol `json:"proxyProtocol,omitempty" yaml:"proxyProtocol,omitempty"` // BasicAuth defines the schema for the HTTP Basic Authentication. BasicAuth *BasicAuth `json:"basicAuth,omitempty" yaml:"basicAuth,omitempty"` - // HealthCheck defines the configuration for active health checking on the upstream. + // ExtAuth defines the schema for the external authorization. + ExtAuth *ExtAuth `json:"extAuth,omitempty" yaml:"extAuth,omitempty"` + // HealthCheck defines the configuration for health checking on the upstream. HealthCheck *HealthCheck `json:"healthCheck,omitempty" yaml:"healthCheck,omitempty"` // FaultInjection defines the schema for injecting faults into HTTP requests. FaultInjection *FaultInjection `json:"faultInjection,omitempty" yaml:"faultInjection,omitempty"` @@ -391,6 +464,10 @@ type HTTPRoute struct { ExtensionRefs []*UnstructuredRef `json:"extensionRefs,omitempty" yaml:"extensionRefs,omitempty"` // Circuit Breaker Settings CircuitBreaker *CircuitBreaker `json:"circuitBreaker,omitempty" yaml:"circuitBreaker,omitempty"` + // Request and connection timeout settings + Timeout *Timeout `json:"timeout,omitempty" yaml:"timeout,omitempty"` + // TcpKeepalive settings associated with the upstream client connection. + TCPKeepalive *TCPKeepalive `json:"tcpKeepalive,omitempty" yaml:"tcpKeepalive,omitempty"` } // UnstructuredRef holds unstructured data for an arbitrary k8s resource introduced by an extension @@ -461,6 +538,20 @@ type OIDC struct { // The path to log a user out, clearing their credential cookies. LogoutPath string `json:"logoutPath,omitempty"` + + // CookieSuffix will be added to the name of the cookies set by the oauth filter. + // Adding a suffix avoids multiple oauth filters from overwriting each other's cookies. + // These cookies are set by the oauth filter, including: BearerToken, + // OauthHMAC, OauthExpires, IdToken, and RefreshToken. + CookieSuffix string `json:"cookieSuffix,omitempty"` +} + +type OIDCProvider struct { + // The OIDC Provider's [authorization endpoint](https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint). + AuthorizationEndpoint string `json:"authorizationEndpoint,omitempty"` + + // The OIDC Provider's [token endpoint](https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint). + TokenEndpoint string `json:"tokenEndpoint,omitempty"` } // BasicAuth defines the schema for the HTTP Basic Authentication. @@ -471,12 +562,65 @@ type BasicAuth struct { Users []byte `json:"users,omitempty" yaml:"users,omitempty"` } -type OIDCProvider struct { - // The OIDC Provider's [authorization endpoint](https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint). - AuthorizationEndpoint string `json:"authorizationEndpoint,omitempty"` +// ExtAuth defines the schema for the external authorization. +// +// +k8s:deepcopy-gen=true +type ExtAuth struct { + // GRPC defines the gRPC External Authorization service. + // Only one of GRPCService or HTTPService may be specified. + GRPC *GRPCExtAuthService `json:"grpc,omitempty"` + + // HTTP defines the HTTP External Authorization service. + // Only one of GRPCService or HTTPService may be specified. + HTTP *HTTPExtAuthService `json:"http,omitempty"` + + // HeadersToExtAuth defines the client request headers that will be included + // in the request to the external authorization service. + // Note: If not specified, the default behavior for gRPC and HTTP external + // authorization services is different due to backward compatibility reasons. + // All headers will be included in the check request to a gRPC authorization server. + // Only the following headers will be included in the check request to an HTTP + // authorization server: Host, Method, Path, Content-Length, and Authorization. + // And these headers will always be included to the check request to an HTTP + // authorization server by default, no matter whether they are specified + // in HeadersToExtAuth or not. + // +optional + HeadersToExtAuth []string `json:"headersToExtAuth,omitempty"` +} - // The OIDC Provider's [token endpoint](https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint). - TokenEndpoint string `json:"tokenEndpoint,omitempty"` +// HTTPExtAuthService defines the HTTP External Authorization service +// +k8s:deepcopy-gen=true +type HTTPExtAuthService struct { + // Destination defines the destination for the HTTP External Authorization service. + Destination RouteDestination `json:"destination"` + + // Authority is the hostname:port of the HTTP External Authorization service. + Authority string `json:"authority"` + + // Path is the path of the HTTP External Authorization service. + // If path is not empty, the authorization request will be sent to that path, + // or else the authorization request will be sent to the root path. + Path string `json:"path"` + + // HeadersToBackend are the authorization response headers that will be added + // to the original client request before sending it to the backend server. + // Note that coexisting headers will be overridden. + // If not specified, no authorization response headers will be added to the + // original client request. + // +optional + HeadersToBackend []string `json:"headersToBackend,omitempty"` +} + +// GRPCExtAuthService defines the gRPC External Authorization service +// The authorization request message is defined in +// https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto +// +k8s:deepcopy-gen=true +type GRPCExtAuthService struct { + // Destination defines the destination for the gRPC External Authorization service. + Destination RouteDestination `json:"destination"` + + // Authority is the hostname:port of the gRPC External Authorization service. + Authority string `json:"authority"` } // FaultInjection defines the schema for injecting faults into requests. @@ -515,50 +659,50 @@ type FaultInjectionAbort struct { func (h HTTPRoute) Validate() error { var errs error if h.Name == "" { - errs = multierror.Append(errs, ErrHTTPRouteNameEmpty) + errs = errors.Join(errs, ErrHTTPRouteNameEmpty) } if h.Hostname == "" { - errs = multierror.Append(errs, ErrHTTPRouteHostnameEmpty) + errs = errors.Join(errs, ErrHTTPRouteHostnameEmpty) } if h.PathMatch != nil { if err := h.PathMatch.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } for _, hMatch := range h.HeaderMatches { if err := hMatch.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } for _, qMatch := range h.QueryParamMatches { if err := qMatch.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } if h.Destination != nil { if err := h.Destination.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } if h.Redirect != nil { if err := h.Redirect.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } if h.DirectResponse != nil { if err := h.DirectResponse.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } if h.URLRewrite != nil { if err := h.URLRewrite.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } if h.Mirrors != nil { for _, mirror := range h.Mirrors { if err := mirror.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } } @@ -566,12 +710,12 @@ func (h HTTPRoute) Validate() error { occurred := map[string]bool{} for _, header := range h.AddRequestHeaders { if err := header.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } if !occurred[header.Name] { occurred[header.Name] = true } else { - errs = multierror.Append(errs, ErrAddHeaderDuplicate) + errs = errors.Join(errs, ErrAddHeaderDuplicate) break } } @@ -582,7 +726,7 @@ func (h HTTPRoute) Validate() error { if !occurred[header] { occurred[header] = true } else { - errs = multierror.Append(errs, ErrRemoveHeaderDuplicate) + errs = errors.Join(errs, ErrRemoveHeaderDuplicate) break } } @@ -591,12 +735,12 @@ func (h HTTPRoute) Validate() error { occurred := map[string]bool{} for _, header := range h.AddResponseHeaders { if err := header.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } if !occurred[header.Name] { occurred[header.Name] = true } else { - errs = multierror.Append(errs, ErrAddHeaderDuplicate) + errs = errors.Join(errs, ErrAddHeaderDuplicate) break } } @@ -607,24 +751,24 @@ func (h HTTPRoute) Validate() error { if !occurred[header] { occurred[header] = true } else { - errs = multierror.Append(errs, ErrRemoveHeaderDuplicate) + errs = errors.Join(errs, ErrRemoveHeaderDuplicate) break } } } if h.LoadBalancer != nil { if err := h.LoadBalancer.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } if h.JWT != nil { if err := h.JWT.validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } if h.HealthCheck != nil { if err := h.HealthCheck.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } @@ -635,7 +779,7 @@ func (j *JWT) validate() error { var errs error if err := egv1a1validation.ValidateJWTProvider(j.Providers); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } return errs @@ -655,11 +799,11 @@ type RouteDestination struct { func (r RouteDestination) Validate() error { var errs error if len(r.Name) == 0 { - errs = multierror.Append(errs, ErrDestinationNameEmpty) + errs = errors.Join(errs, ErrDestinationNameEmpty) } for _, s := range r.Settings { if err := s.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } @@ -684,7 +828,7 @@ func (d DestinationSetting) Validate() error { var errs error for _, ep := range d.Endpoints { if err := ep.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } @@ -714,14 +858,14 @@ func (d DestinationEndpoint) Validate() error { var errs error err := validation.IsDNS1123Subdomain(d.Host) - ip := net.ParseIP(d.Host) + _, pErr := netip.ParseAddr(d.Host) - if err != nil && ip == nil { - errs = multierror.Append(errs, ErrDestEndpointHostInvalid) + if err != nil && pErr != nil { + errs = errors.Join(errs, ErrDestEndpointHostInvalid) } if d.Port == 0 { - errs = multierror.Append(errs, ErrDestEndpointPortInvalid) + errs = errors.Join(errs, ErrDestEndpointPortInvalid) } return errs @@ -747,7 +891,7 @@ type AddHeader struct { func (h AddHeader) Validate() error { var errs error if h.Name == "" { - errs = multierror.Append(errs, ErrAddHeaderEmptyName) + errs = errors.Join(errs, ErrAddHeaderEmptyName) } return errs @@ -767,7 +911,7 @@ type DirectResponse struct { func (r DirectResponse) Validate() error { var errs error if status := r.StatusCode; status > 599 || status < 100 { - errs = multierror.Append(errs, ErrDirectResponseStatusInvalid) + errs = errors.Join(errs, ErrDirectResponseStatusInvalid) } return errs @@ -788,7 +932,7 @@ func (r URLRewrite) Validate() error { if r.Path != nil { if err := r.Path.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } @@ -816,19 +960,19 @@ func (r Redirect) Validate() error { if r.Scheme != nil { if *r.Scheme != "http" && *r.Scheme != "https" { - errs = multierror.Append(errs, ErrRedirectUnsupportedScheme) + errs = errors.Join(errs, ErrRedirectUnsupportedScheme) } } if r.Path != nil { if err := r.Path.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } if r.StatusCode != nil { if *r.StatusCode != 301 && *r.StatusCode != 302 { - errs = multierror.Append(errs, ErrRedirectUnsupportedStatus) + errs = errors.Join(errs, ErrRedirectUnsupportedStatus) } } @@ -849,11 +993,11 @@ func (r HTTPPathModifier) Validate() error { var errs error if r.FullReplace != nil && r.PrefixMatchReplace != nil { - errs = multierror.Append(errs, ErrHTTPPathModifierDoubleReplace) + errs = errors.Join(errs, ErrHTTPPathModifierDoubleReplace) } if r.FullReplace == nil && r.PrefixMatchReplace == nil { - errs = multierror.Append(errs, ErrHTTPPathModifierNoReplace) + errs = errors.Join(errs, ErrHTTPPathModifierNoReplace) } return errs @@ -896,13 +1040,13 @@ func (s StringMatch) Validate() error { } if s.Distinct { if s.Name == "" { - errs = multierror.Append(errs, ErrStringMatchNameIsEmpty) + errs = errors.Join(errs, ErrStringMatchNameIsEmpty) } matchCount++ } if matchCount != 1 { - errs = multierror.Append(errs, ErrStringMatchConditionInvalid) + errs = errors.Join(errs, ErrStringMatchConditionInvalid) } return errs @@ -939,29 +1083,29 @@ type TLS struct { func (h TCPListener) Validate() error { var errs error if h.Name == "" { - errs = multierror.Append(errs, ErrListenerNameEmpty) + errs = errors.Join(errs, ErrListenerNameEmpty) } - if ip := net.ParseIP(h.Address); ip == nil { - errs = multierror.Append(errs, ErrListenerAddressInvalid) + if _, err := netip.ParseAddr(h.Address); err != nil { + errs = errors.Join(errs, ErrListenerAddressInvalid) } if h.Port == 0 { - errs = multierror.Append(errs, ErrListenerPortInvalid) + errs = errors.Join(errs, ErrListenerPortInvalid) } if h.TLS != nil && h.TLS.Passthrough != nil { if err := h.TLS.Passthrough.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } if h.TLS != nil && h.TLS.Terminate != nil { if err := h.TLS.Terminate.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } if h.Destination != nil { if err := h.Destination.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } return errs @@ -981,7 +1125,7 @@ type TLSInspectorConfig struct { func (t TLSInspectorConfig) Validate() error { var errs error if len(t.SNIs) == 0 { - errs = multierror.Append(errs, ErrTCPListenerSNIsEmpty) + errs = errors.Join(errs, ErrTCPListenerSNIsEmpty) } return errs } @@ -1003,17 +1147,17 @@ type UDPListener struct { func (h UDPListener) Validate() error { var errs error if h.Name == "" { - errs = multierror.Append(errs, ErrListenerNameEmpty) + errs = errors.Join(errs, ErrListenerNameEmpty) } - if ip := net.ParseIP(h.Address); ip == nil { - errs = multierror.Append(errs, ErrListenerAddressInvalid) + if _, err := netip.ParseAddr(h.Address); err != nil { + errs = errors.Join(errs, ErrListenerAddressInvalid) } if h.Port == 0 { - errs = multierror.Append(errs, ErrListenerPortInvalid) + errs = errors.Join(errs, ErrListenerPortInvalid) } if h.Destination != nil { if err := h.Destination.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } @@ -1157,8 +1301,13 @@ type JSONPatchOperation struct { // Path is the location of the target document/field where the operation will be performed // Refer to https://datatracker.ietf.org/doc/html/rfc6901 for more details. Path string `json:"path" yaml:"path"` + // From is the source location of the value to be copied or moved. Only valid + // for move or copy operations + // Refer to https://datatracker.ietf.org/doc/html/rfc6901 for more details. + // +optional + From *string `json:"from,omitempty" yaml:"from,omitempty"` // Value is the new value of the path location. - Value apiextensionsv1.JSON `json:"value" yaml:"value"` + Value *apiextensionsv1.JSON `json:"value,omitempty" yaml:"value,omitempty"` } // Tracing defines the configuration for tracing a Envoy xDS Resource @@ -1221,7 +1370,7 @@ func (l *LoadBalancer) Validate() error { matchCount++ } if matchCount != 1 { - errs = multierror.Append(errs, ErrLoadBalancerInvalid) + errs = errors.Join(errs, ErrLoadBalancerInvalid) } return errs @@ -1288,14 +1437,44 @@ type CircuitBreaker struct { // The maximum number of parallel requests that Envoy will make. MaxParallelRequests *uint32 `json:"maxParallelRequests,omitempty" yaml:"maxParallelRequests,omitempty"` + + // The maximum number of parallel requests that Envoy will make. + MaxRequestsPerConnection *uint32 `json:"maxRequestsPerConnection,omitempty" yaml:"maxRequestsPerConnection,omitempty"` } // HealthCheck defines health check settings // +k8s:deepcopy-gen=true type HealthCheck struct { + Active *ActiveHealthCheck `json:"active,omitempty" yaml:"active,omitempty"` + + Passive *OutlierDetection `json:"passive,omitempty" yaml:"passive,omitempty"` +} + +// OutlierDetection defines passive health check settings +// +k8s:deepcopy-gen=true +type OutlierDetection struct { + // Interval defines the time between passive health checks. + Interval *metav1.Duration `json:"interval,omitempty"` + // SplitExternalLocalOriginErrors enables splitting of errors between external and local origin. + SplitExternalLocalOriginErrors *bool `json:"splitExternalLocalOriginErrors,omitempty" yaml:"splitExternalLocalOriginErrors,omitempty"` + // ConsecutiveLocalOriginFailures sets the number of consecutive local origin failures triggering ejection. + ConsecutiveLocalOriginFailures *uint32 `json:"consecutiveLocalOriginFailures,omitempty" yaml:"consecutiveLocalOriginFailures,omitempty"` + // ConsecutiveGatewayErrors sets the number of consecutive gateway errors triggering ejection. + ConsecutiveGatewayErrors *uint32 `json:"consecutiveGatewayErrors,omitempty" yaml:"consecutiveGatewayErrors,omitempty"` + // Consecutive5xxErrors sets the number of consecutive 5xx errors triggering ejection. + Consecutive5xxErrors *uint32 `json:"consecutive5XxErrors,omitempty" yaml:"consecutive5XxErrors,omitempty"` + // BaseEjectionTime defines the base duration for which a host will be ejected on consecutive failures. + BaseEjectionTime *metav1.Duration `json:"baseEjectionTime,omitempty" yaml:"baseEjectionTime,omitempty"` + // MaxEjectionPercent sets the maximum percentage of hosts in a cluster that can be ejected. + MaxEjectionPercent *int32 `json:"maxEjectionPercent,omitempty" yaml:"maxEjectionPercent,omitempty"` +} + +// ActiveHealthCheck defines active health check settings +// +k8s:deepcopy-gen=true +type ActiveHealthCheck struct { // Timeout defines the time to wait for a health check response. Timeout *metav1.Duration `json:"timeout"` - // Interval defines the time between health checks. + // Interval defines the time between active health checks. Interval *metav1.Duration `json:"interval"` // UnhealthyThreshold defines the number of unhealthy health checks required before a backend host is marked unhealthy. UnhealthyThreshold *uint32 `json:"unhealthyThreshold"` @@ -1310,39 +1489,50 @@ type HealthCheck struct { // Validate the fields within the HealthCheck structure. func (h *HealthCheck) Validate() error { var errs error + if h.Active != nil { + if h.Active.Timeout != nil && h.Active.Timeout.Duration == 0 { + errs = errors.Join(errs, ErrHealthCheckTimeoutInvalid) + } + if h.Active.Interval != nil && h.Active.Interval.Duration == 0 { + errs = errors.Join(errs, ErrHealthCheckIntervalInvalid) + } + if h.Active.UnhealthyThreshold != nil && *h.Active.UnhealthyThreshold == 0 { + errs = errors.Join(errs, ErrHealthCheckUnhealthyThresholdInvalid) + } + if h.Active.HealthyThreshold != nil && *h.Active.HealthyThreshold == 0 { + errs = errors.Join(errs, ErrHealthCheckHealthyThresholdInvalid) + } - if h.Timeout != nil && h.Timeout.Duration == 0 { - errs = multierror.Append(errs, ErrHealthCheckTimeoutInvalid) - } - if h.Interval != nil && h.Interval.Duration == 0 { - errs = multierror.Append(errs, ErrHealthCheckIntervalInvalid) - } - if h.UnhealthyThreshold != nil && *h.UnhealthyThreshold == 0 { - errs = multierror.Append(errs, ErrHealthCheckUnhealthyThresholdInvalid) - } - if h.HealthyThreshold != nil && *h.HealthyThreshold == 0 { - errs = multierror.Append(errs, ErrHealthCheckHealthyThresholdInvalid) - } + matchCount := 0 + if h.Active.HTTP != nil { + matchCount++ + } + if h.Active.TCP != nil { + matchCount++ + } + if matchCount > 1 { + errs = errors.Join(errs, ErrHealthCheckerInvalid) + } - matchCount := 0 - if h.HTTP != nil { - matchCount++ - } - if h.TCP != nil { - matchCount++ - } - if matchCount != 1 { - errs = multierror.Append(errs, ErrHealthCheckerInvalid) + if h.Active.HTTP != nil { + if err := h.Active.HTTP.Validate(); err != nil { + errs = errors.Join(errs, err) + } + } + if h.Active.TCP != nil { + if err := h.Active.TCP.Validate(); err != nil { + errs = errors.Join(errs, err) + } + } } - if h.HTTP != nil { - if err := h.HTTP.Validate(); err != nil { - errs = multierror.Append(errs, err) + if h.Passive != nil { + if h.Passive.BaseEjectionTime != nil && h.Passive.BaseEjectionTime.Duration == 0 { + errs = errors.Join(errs, ErrOutlierDetectionBaseEjectionTimeInvalid) } - } - if h.TCP != nil { - if err := h.TCP.Validate(); err != nil { - errs = multierror.Append(errs, err) + + if h.Passive.Interval != nil && h.Passive.Interval.Duration == 0 { + errs = errors.Join(errs, ErrOutlierDetectionIntervalInvalid) } } @@ -1366,7 +1556,7 @@ type HTTPHealthChecker struct { func (c *HTTPHealthChecker) Validate() error { var errs error if c.Path == "" { - errs = multierror.Append(errs, ErrHCHTTPPathInvalid) + errs = errors.Join(errs, ErrHCHTTPPathInvalid) } if c.Method != nil { switch *c.Method { @@ -1380,20 +1570,20 @@ func (c *HTTPHealthChecker) Validate() error { case http.MethodPatch: case "": default: - errs = multierror.Append(errs, ErrHCHTTPMethodInvalid) + errs = errors.Join(errs, ErrHCHTTPMethodInvalid) } } if len(c.ExpectedStatuses) == 0 { - errs = multierror.Append(errs, ErrHCHTTPExpectedStatusesInvalid) + errs = errors.Join(errs, ErrHCHTTPExpectedStatusesInvalid) } for _, r := range c.ExpectedStatuses { if err := r.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } if c.ExpectedResponse != nil { if err := c.ExpectedResponse.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } return errs @@ -1421,12 +1611,12 @@ func (c *TCPHealthChecker) Validate() error { var errs error if c.Send != nil { if err := c.Send.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } if c.Receive != nil { if err := c.Receive.Validate(); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } return errs @@ -1452,7 +1642,35 @@ func (p *HealthCheckPayload) Validate() error { matchCount++ } if matchCount != 1 { - errs = multierror.Append(errs, ErrHealthCheckPayloadInvalid) + errs = errors.Join(errs, ErrHealthCheckPayloadInvalid) } return errs } + +// Backend connection timeout settings +// +k8s:deepcopy-gen=true +type Timeout struct { + // Timeout settings for TCP. + TCP *TCPTimeout `json:"tcp,omitempty" yaml:"tcp,omitempty"` + + // Timeout settings for HTTP. + HTTP *HTTPTimeout `json:"http,omitempty" yaml:"tcp,omitempty"` +} + +// +k8s:deepcopy-gen=true +type TCPTimeout struct { + // The timeout for network connection establishment, including TCP and TLS handshakes. + ConnectTimeout *metav1.Duration `json:"connectTimeout,omitempty" yaml:"connectTimeout,omitempty"` +} + +// +k8s:deepcopy-gen=true +type HTTPTimeout struct { + // RequestTimeout is the time until which entire response is received from the upstream. + RequestTimeout *metav1.Duration `json:"requestTimeout,omitempty" yaml:"requestTimeout,omitempty"` + + // The idle timeout for an HTTP connection. Idle time is defined as a period in which there are no active requests in the connection. + ConnectionIdleTimeout *metav1.Duration `json:"connectionIdleTimeout,omitempty" yaml:"connectionIdleTimeout,omitempty"` + + // The maximum duration of an HTTP connection. + MaxConnectionDuration *metav1.Duration `json:"maxConnectionDuration,omitempty" yaml:"maxConnectionDuration,omitempty"` +} diff --git a/internal/ir/xds_test.go b/internal/ir/xds_test.go index 009783361c6..c9f2bed7411 100644 --- a/internal/ir/xds_test.go +++ b/internal/ir/xds_test.go @@ -42,6 +42,20 @@ var ( }}}, Routes: []*HTTPRoute{&happyHTTPRoute}, } + redactedHappyHTTPSListener = HTTPListener{ + Name: "happy", + Address: "0.0.0.0", + Port: 80, + Hostnames: []string{"example.com"}, + TLS: &TLSConfig{ + Certificates: []TLSCertificate{{ + + Name: "happy", + ServerCertificate: []byte{1, 2, 3}, + PrivateKey: redacted, + }}}, + Routes: []*HTTPRoute{&happyHTTPRoute}, + } invalidAddrHTTPListener = HTTPListener{ Name: "invalid-addr", Address: "1.0.0", @@ -525,7 +539,7 @@ func TestValidateXds(t *testing.T) { } else { got := test.input.Validate() for _, w := range test.want { - assert.ErrorContains(t, got, w.Error()) + require.ErrorContains(t, got, w.Error()) } } }) @@ -576,7 +590,7 @@ func TestValidateHTTPListener(t *testing.T) { } else { got := test.input.Validate() for _, w := range test.want { - assert.ErrorContains(t, got, w.Error()) + require.ErrorContains(t, got, w.Error()) } } }) @@ -623,7 +637,7 @@ func TestValidateTCPListener(t *testing.T) { } else { got := test.input.Validate() for _, w := range test.want { - assert.ErrorContains(t, got, w.Error()) + require.ErrorContains(t, got, w.Error()) } } }) @@ -783,7 +797,7 @@ func TestValidateUDPListener(t *testing.T) { } else { got := test.input.Validate() for _, w := range test.want { - assert.ErrorContains(t, got, w.Error()) + require.ErrorContains(t, got, w.Error()) } } }) @@ -935,7 +949,7 @@ func TestValidateHTTPRoute(t *testing.T) { } else { got := test.input.Validate() for _, w := range test.want { - assert.ErrorContains(t, got, w.Error()) + require.ErrorContains(t, got, w.Error()) } } }) @@ -1217,7 +1231,7 @@ func TestPrintable(t *testing.T) { HTTP: []*HTTPListener{&happyHTTPSListener}, }, want: &Xds{ - HTTP: []*HTTPListener{&happyHTTPListener}, + HTTP: []*HTTPListener{&redactedHappyHTTPSListener}, }, }, } @@ -1237,7 +1251,7 @@ func TestValidateHealthCheck(t *testing.T) { }{ { name: "invalid timeout", - input: HealthCheck{ + input: HealthCheck{&ActiveHealthCheck{ Timeout: &metav1.Duration{Duration: time.Duration(0)}, Interval: &metav1.Duration{Duration: time.Second}, UnhealthyThreshold: ptr.To[uint32](3), @@ -1246,12 +1260,14 @@ func TestValidateHealthCheck(t *testing.T) { Path: "/healthz", ExpectedStatuses: []HTTPStatus{200, 400}, }, + }, + &OutlierDetection{}, }, want: ErrHealthCheckTimeoutInvalid, }, { name: "invalid interval", - input: HealthCheck{ + input: HealthCheck{&ActiveHealthCheck{ Timeout: &metav1.Duration{Duration: time.Second}, Interval: &metav1.Duration{Duration: time.Duration(0)}, UnhealthyThreshold: ptr.To[uint32](3), @@ -1261,12 +1277,14 @@ func TestValidateHealthCheck(t *testing.T) { Method: ptr.To(http.MethodGet), ExpectedStatuses: []HTTPStatus{200, 400}, }, + }, + &OutlierDetection{}, }, want: ErrHealthCheckIntervalInvalid, }, { name: "invalid unhealthy threshold", - input: HealthCheck{ + input: HealthCheck{&ActiveHealthCheck{ Timeout: &metav1.Duration{Duration: time.Second}, Interval: &metav1.Duration{Duration: time.Second}, UnhealthyThreshold: ptr.To[uint32](0), @@ -1276,12 +1294,14 @@ func TestValidateHealthCheck(t *testing.T) { Method: ptr.To(http.MethodPatch), ExpectedStatuses: []HTTPStatus{200, 400}, }, + }, + &OutlierDetection{}, }, want: ErrHealthCheckUnhealthyThresholdInvalid, }, { name: "invalid healthy threshold", - input: HealthCheck{ + input: HealthCheck{&ActiveHealthCheck{ Timeout: &metav1.Duration{Duration: time.Second}, Interval: &metav1.Duration{Duration: time.Second}, UnhealthyThreshold: ptr.To[uint32](3), @@ -1291,12 +1311,14 @@ func TestValidateHealthCheck(t *testing.T) { Method: ptr.To(http.MethodPost), ExpectedStatuses: []HTTPStatus{200, 400}, }, + }, + &OutlierDetection{}, }, want: ErrHealthCheckHealthyThresholdInvalid, }, { name: "http-health-check: invalid path", - input: HealthCheck{ + input: HealthCheck{&ActiveHealthCheck{ Timeout: &metav1.Duration{Duration: time.Second}, Interval: &metav1.Duration{Duration: time.Second}, UnhealthyThreshold: ptr.To[uint32](3), @@ -1306,12 +1328,14 @@ func TestValidateHealthCheck(t *testing.T) { Method: ptr.To(http.MethodPut), ExpectedStatuses: []HTTPStatus{200, 400}, }, + }, + &OutlierDetection{}, }, want: ErrHCHTTPPathInvalid, }, { name: "http-health-check: invalid method", - input: HealthCheck{ + input: HealthCheck{&ActiveHealthCheck{ Timeout: &metav1.Duration{Duration: time.Second}, Interval: &metav1.Duration{Duration: time.Second}, UnhealthyThreshold: ptr.To(uint32(3)), @@ -1321,12 +1345,14 @@ func TestValidateHealthCheck(t *testing.T) { Method: ptr.To(http.MethodConnect), ExpectedStatuses: []HTTPStatus{200, 400}, }, + }, + &OutlierDetection{}, }, want: ErrHCHTTPMethodInvalid, }, { name: "http-health-check: invalid expected-statuses", - input: HealthCheck{ + input: HealthCheck{&ActiveHealthCheck{ Timeout: &metav1.Duration{Duration: time.Second}, Interval: &metav1.Duration{Duration: time.Second}, UnhealthyThreshold: ptr.To(uint32(3)), @@ -1336,12 +1362,14 @@ func TestValidateHealthCheck(t *testing.T) { Method: ptr.To(http.MethodDelete), ExpectedStatuses: []HTTPStatus{}, }, + }, + &OutlierDetection{}, }, want: ErrHCHTTPExpectedStatusesInvalid, }, { name: "http-health-check: invalid range", - input: HealthCheck{ + input: HealthCheck{&ActiveHealthCheck{ Timeout: &metav1.Duration{Duration: time.Second}, Interval: &metav1.Duration{Duration: time.Second}, UnhealthyThreshold: ptr.To(uint32(3)), @@ -1351,12 +1379,14 @@ func TestValidateHealthCheck(t *testing.T) { Method: ptr.To(http.MethodHead), ExpectedStatuses: []HTTPStatus{100, 600}, }, + }, + &OutlierDetection{}, }, want: ErrHTTPStatusInvalid, }, { name: "http-health-check: invalid expected-responses", - input: HealthCheck{ + input: HealthCheck{&ActiveHealthCheck{ Timeout: &metav1.Duration{Duration: time.Second}, Interval: &metav1.Duration{Duration: time.Second}, UnhealthyThreshold: ptr.To(uint32(3)), @@ -1370,12 +1400,14 @@ func TestValidateHealthCheck(t *testing.T) { Binary: []byte{'f', 'o', 'o'}, }, }, + }, + &OutlierDetection{}, }, want: ErrHealthCheckPayloadInvalid, }, { name: "tcp-health-check: invalid send payload", - input: HealthCheck{ + input: HealthCheck{&ActiveHealthCheck{ Timeout: &metav1.Duration{Duration: time.Second}, Interval: &metav1.Duration{Duration: time.Second}, UnhealthyThreshold: ptr.To(uint32(3)), @@ -1389,12 +1421,14 @@ func TestValidateHealthCheck(t *testing.T) { Text: ptr.To("foo"), }, }, + }, + &OutlierDetection{}, }, want: ErrHealthCheckPayloadInvalid, }, { name: "tcp-health-check: invalid receive payload", - input: HealthCheck{ + input: HealthCheck{&ActiveHealthCheck{ Timeout: &metav1.Duration{Duration: time.Second}, Interval: &metav1.Duration{Duration: time.Second}, UnhealthyThreshold: ptr.To(uint32(3)), @@ -1408,9 +1442,31 @@ func TestValidateHealthCheck(t *testing.T) { Binary: []byte{'f', 'o', 'o'}, }, }, + }, + &OutlierDetection{}, }, want: ErrHealthCheckPayloadInvalid, }, + { + name: "OutlierDetection invalid interval", + input: HealthCheck{&ActiveHealthCheck{}, + &OutlierDetection{ + Interval: &metav1.Duration{Duration: time.Duration(0)}, + BaseEjectionTime: &metav1.Duration{Duration: time.Second}, + }, + }, + want: ErrOutlierDetectionIntervalInvalid, + }, + { + name: "OutlierDetection invalid BaseEjectionTime", + input: HealthCheck{&ActiveHealthCheck{}, + &OutlierDetection{ + Interval: &metav1.Duration{Duration: time.Second}, + BaseEjectionTime: &metav1.Duration{Duration: time.Duration(0)}, + }, + }, + want: ErrOutlierDetectionBaseEjectionTimeInvalid, + }, } for i := range tests { test := tests[i] diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go index e905756dbc2..1f07711beb1 100644 --- a/internal/ir/zz_generated.deepcopy.go +++ b/internal/ir/zz_generated.deepcopy.go @@ -11,6 +11,7 @@ package ir import ( "github.com/envoyproxy/gateway/api/v1alpha1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -62,6 +63,51 @@ func (in *AccessLog) DeepCopy() *AccessLog { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActiveHealthCheck) DeepCopyInto(out *ActiveHealthCheck) { + *out = *in + if in.Timeout != nil { + in, out := &in.Timeout, &out.Timeout + *out = new(v1.Duration) + **out = **in + } + if in.Interval != nil { + in, out := &in.Interval, &out.Interval + *out = new(v1.Duration) + **out = **in + } + if in.UnhealthyThreshold != nil { + in, out := &in.UnhealthyThreshold, &out.UnhealthyThreshold + *out = new(uint32) + **out = **in + } + if in.HealthyThreshold != nil { + in, out := &in.HealthyThreshold, &out.HealthyThreshold + *out = new(uint32) + **out = **in + } + if in.HTTP != nil { + in, out := &in.HTTP, &out.HTTP + *out = new(HTTPHealthChecker) + (*in).DeepCopyInto(*out) + } + if in.TCP != nil { + in, out := &in.TCP, &out.TCP + *out = new(TCPHealthChecker) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveHealthCheck. +func (in *ActiveHealthCheck) DeepCopy() *ActiveHealthCheck { + if in == nil { + return nil + } + out := new(ActiveHealthCheck) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AddHeader) DeepCopyInto(out *AddHeader) { *out = *in @@ -161,6 +207,11 @@ func (in *CircuitBreaker) DeepCopyInto(out *CircuitBreaker) { *out = new(uint32) **out = **in } + if in.MaxRequestsPerConnection != nil { + in, out := &in.MaxRequestsPerConnection, &out.MaxRequestsPerConnection + *out = new(uint32) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CircuitBreaker. @@ -173,6 +224,51 @@ func (in *CircuitBreaker) DeepCopy() *CircuitBreaker { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClientIPDetectionSettings) DeepCopyInto(out *ClientIPDetectionSettings) { + *out = *in + if in.XForwardedFor != nil { + in, out := &in.XForwardedFor, &out.XForwardedFor + *out = new(v1alpha1.XForwardedForSettings) + (*in).DeepCopyInto(*out) + } + if in.CustomHeader != nil { + in, out := &in.CustomHeader, &out.CustomHeader + *out = new(v1alpha1.CustomHeaderExtensionSettings) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClientIPDetectionSettings. +func (in *ClientIPDetectionSettings) DeepCopy() *ClientIPDetectionSettings { + if in == nil { + return nil + } + out := new(ClientIPDetectionSettings) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClientTimeout) DeepCopyInto(out *ClientTimeout) { + *out = *in + if in.HTTP != nil { + in, out := &in.HTTP, &out.HTTP + *out = new(HTTPClientTimeout) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClientTimeout. +func (in *ClientTimeout) DeepCopy() *ClientTimeout { + if in == nil { + return nil + } + out := new(ClientTimeout) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ConsistentHash) DeepCopyInto(out *ConsistentHash) { *out = *in @@ -311,6 +407,36 @@ func (in *EnvoyPatchPolicyStatus) DeepCopy() *EnvoyPatchPolicyStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExtAuth) DeepCopyInto(out *ExtAuth) { + *out = *in + if in.GRPC != nil { + in, out := &in.GRPC, &out.GRPC + *out = new(GRPCExtAuthService) + (*in).DeepCopyInto(*out) + } + if in.HTTP != nil { + in, out := &in.HTTP, &out.HTTP + *out = new(HTTPExtAuthService) + (*in).DeepCopyInto(*out) + } + if in.HeadersToExtAuth != nil { + in, out := &in.HeadersToExtAuth, &out.HeadersToExtAuth + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtAuth. +func (in *ExtAuth) DeepCopy() *ExtAuth { + if in == nil { + return nil + } + out := new(ExtAuth) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FaultInjection) DeepCopyInto(out *FaultInjection) { *out = *in @@ -391,6 +517,22 @@ func (in *FaultInjectionDelay) DeepCopy() *FaultInjectionDelay { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GRPCExtAuthService) DeepCopyInto(out *GRPCExtAuthService) { + *out = *in + in.Destination.DeepCopyInto(&out.Destination) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCExtAuthService. +func (in *GRPCExtAuthService) DeepCopy() *GRPCExtAuthService { + if in == nil { + return nil + } + out := new(GRPCExtAuthService) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GlobalRateLimit) DeepCopyInto(out *GlobalRateLimit) { *out = *in @@ -417,6 +559,87 @@ func (in *GlobalRateLimit) DeepCopy() *GlobalRateLimit { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTP10Settings) DeepCopyInto(out *HTTP10Settings) { + *out = *in + if in.DefaultHost != nil { + in, out := &in.DefaultHost, &out.DefaultHost + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTP10Settings. +func (in *HTTP10Settings) DeepCopy() *HTTP10Settings { + if in == nil { + return nil + } + out := new(HTTP10Settings) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTP1Settings) DeepCopyInto(out *HTTP1Settings) { + *out = *in + if in.HTTP10 != nil { + in, out := &in.HTTP10, &out.HTTP10 + *out = new(HTTP10Settings) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTP1Settings. +func (in *HTTP1Settings) DeepCopy() *HTTP1Settings { + if in == nil { + return nil + } + out := new(HTTP1Settings) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPClientTimeout) DeepCopyInto(out *HTTPClientTimeout) { + *out = *in + if in.RequestReceivedTimeout != nil { + in, out := &in.RequestReceivedTimeout, &out.RequestReceivedTimeout + *out = new(v1.Duration) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPClientTimeout. +func (in *HTTPClientTimeout) DeepCopy() *HTTPClientTimeout { + if in == nil { + return nil + } + out := new(HTTPClientTimeout) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPExtAuthService) DeepCopyInto(out *HTTPExtAuthService) { + *out = *in + in.Destination.DeepCopyInto(&out.Destination) + if in.HeadersToBackend != nil { + in, out := &in.HeadersToBackend, &out.HeadersToBackend + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPExtAuthService. +func (in *HTTPExtAuthService) DeepCopy() *HTTPExtAuthService { + if in == nil { + return nil + } + out := new(HTTPExtAuthService) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HTTPHealthChecker) DeepCopyInto(out *HTTPHealthChecker) { *out = *in @@ -476,12 +699,32 @@ func (in *HTTPListener) DeepCopyInto(out *HTTPListener) { *out = new(TCPKeepalive) (*in).DeepCopyInto(*out) } + if in.Headers != nil { + in, out := &in.Headers, &out.Headers + *out = new(HeaderSettings) + **out = **in + } + if in.ClientIPDetection != nil { + in, out := &in.ClientIPDetection, &out.ClientIPDetection + *out = new(ClientIPDetectionSettings) + (*in).DeepCopyInto(*out) + } if in.HTTP3 != nil { in, out := &in.HTTP3, &out.HTTP3 *out = new(HTTP3Settings) **out = **in } out.Path = in.Path + if in.HTTP1 != nil { + in, out := &in.HTTP1, &out.HTTP1 + *out = new(HTTP1Settings) + (*in).DeepCopyInto(*out) + } + if in.Timeout != nil { + in, out := &in.Timeout, &out.Timeout + *out = new(ClientTimeout) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPListener. @@ -606,11 +849,6 @@ func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) { *out = new(RateLimit) (*in).DeepCopyInto(*out) } - if in.Timeout != nil { - in, out := &in.Timeout, &out.Timeout - *out = new(v1.Duration) - **out = **in - } if in.LoadBalancer != nil { in, out := &in.LoadBalancer, &out.LoadBalancer *out = new(LoadBalancer) @@ -641,6 +879,11 @@ func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) { *out = new(BasicAuth) (*in).DeepCopyInto(*out) } + if in.ExtAuth != nil { + in, out := &in.ExtAuth, &out.ExtAuth + *out = new(ExtAuth) + (*in).DeepCopyInto(*out) + } if in.HealthCheck != nil { in, out := &in.HealthCheck, &out.HealthCheck *out = new(HealthCheck) @@ -667,6 +910,16 @@ func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) { *out = new(CircuitBreaker) (*in).DeepCopyInto(*out) } + if in.Timeout != nil { + in, out := &in.Timeout, &out.Timeout + *out = new(Timeout) + (*in).DeepCopyInto(*out) + } + if in.TCPKeepalive != nil { + in, out := &in.TCPKeepalive, &out.TCPKeepalive + *out = new(TCPKeepalive) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRoute. @@ -680,36 +933,61 @@ func (in *HTTPRoute) DeepCopy() *HTTPRoute { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *HealthCheck) DeepCopyInto(out *HealthCheck) { +func (in *HTTPTimeout) DeepCopyInto(out *HTTPTimeout) { *out = *in - if in.Timeout != nil { - in, out := &in.Timeout, &out.Timeout + if in.RequestTimeout != nil { + in, out := &in.RequestTimeout, &out.RequestTimeout *out = new(v1.Duration) **out = **in } - if in.Interval != nil { - in, out := &in.Interval, &out.Interval + if in.ConnectionIdleTimeout != nil { + in, out := &in.ConnectionIdleTimeout, &out.ConnectionIdleTimeout *out = new(v1.Duration) **out = **in } - if in.UnhealthyThreshold != nil { - in, out := &in.UnhealthyThreshold, &out.UnhealthyThreshold - *out = new(uint32) + if in.MaxConnectionDuration != nil { + in, out := &in.MaxConnectionDuration, &out.MaxConnectionDuration + *out = new(v1.Duration) **out = **in } - if in.HealthyThreshold != nil { - in, out := &in.HealthyThreshold, &out.HealthyThreshold - *out = new(uint32) - **out = **in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPTimeout. +func (in *HTTPTimeout) DeepCopy() *HTTPTimeout { + if in == nil { + return nil } - if in.HTTP != nil { - in, out := &in.HTTP, &out.HTTP - *out = new(HTTPHealthChecker) + out := new(HTTPTimeout) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HeaderSettings) DeepCopyInto(out *HeaderSettings) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HeaderSettings. +func (in *HeaderSettings) DeepCopy() *HeaderSettings { + if in == nil { + return nil + } + out := new(HeaderSettings) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HealthCheck) DeepCopyInto(out *HealthCheck) { + *out = *in + if in.Active != nil { + in, out := &in.Active, &out.Active + *out = new(ActiveHealthCheck) (*in).DeepCopyInto(*out) } - if in.TCP != nil { - in, out := &in.TCP, &out.TCP - *out = new(TCPHealthChecker) + if in.Passive != nil { + in, out := &in.Passive, &out.Passive + *out = new(OutlierDetection) (*in).DeepCopyInto(*out) } } @@ -839,7 +1117,16 @@ func (in *JSONPatchConfig) DeepCopy() *JSONPatchConfig { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *JSONPatchOperation) DeepCopyInto(out *JSONPatchOperation) { *out = *in - in.Value.DeepCopyInto(&out.Value) + if in.From != nil { + in, out := &in.From, &out.From + *out = new(string) + **out = **in + } + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = new(apiextensionsv1.JSON) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONPatchOperation. @@ -1046,6 +1333,56 @@ func (in *OpenTelemetryAccessLog) DeepCopy() *OpenTelemetryAccessLog { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OutlierDetection) DeepCopyInto(out *OutlierDetection) { + *out = *in + if in.Interval != nil { + in, out := &in.Interval, &out.Interval + *out = new(v1.Duration) + **out = **in + } + if in.SplitExternalLocalOriginErrors != nil { + in, out := &in.SplitExternalLocalOriginErrors, &out.SplitExternalLocalOriginErrors + *out = new(bool) + **out = **in + } + if in.ConsecutiveLocalOriginFailures != nil { + in, out := &in.ConsecutiveLocalOriginFailures, &out.ConsecutiveLocalOriginFailures + *out = new(uint32) + **out = **in + } + if in.ConsecutiveGatewayErrors != nil { + in, out := &in.ConsecutiveGatewayErrors, &out.ConsecutiveGatewayErrors + *out = new(uint32) + **out = **in + } + if in.Consecutive5xxErrors != nil { + in, out := &in.Consecutive5xxErrors, &out.Consecutive5xxErrors + *out = new(uint32) + **out = **in + } + if in.BaseEjectionTime != nil { + in, out := &in.BaseEjectionTime, &out.BaseEjectionTime + *out = new(v1.Duration) + **out = **in + } + if in.MaxEjectionPercent != nil { + in, out := &in.MaxEjectionPercent, &out.MaxEjectionPercent + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OutlierDetection. +func (in *OutlierDetection) DeepCopy() *OutlierDetection { + if in == nil { + return nil + } + out := new(OutlierDetection) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PathSettings) DeepCopyInto(out *PathSettings) { *out = *in @@ -1460,6 +1797,26 @@ func (in *TCPListener) DeepCopy() *TCPListener { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TCPTimeout) DeepCopyInto(out *TCPTimeout) { + *out = *in + if in.ConnectTimeout != nil { + in, out := &in.ConnectTimeout, &out.ConnectTimeout + *out = new(v1.Duration) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPTimeout. +func (in *TCPTimeout) DeepCopy() *TCPTimeout { + if in == nil { + return nil + } + out := new(TCPTimeout) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TLS) DeepCopyInto(out *TLS) { *out = *in @@ -1485,6 +1842,26 @@ func (in *TLS) DeepCopy() *TLS { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TLSCACertificate) DeepCopyInto(out *TLSCACertificate) { + *out = *in + if in.Certificate != nil { + in, out := &in.Certificate, &out.Certificate + *out = make([]byte, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSCACertificate. +func (in *TLSCACertificate) DeepCopy() *TLSCACertificate { + if in == nil { + return nil + } + out := new(TLSCACertificate) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TLSCertificate) DeepCopyInto(out *TLSCertificate) { *out = *in @@ -1520,6 +1897,11 @@ func (in *TLSConfig) DeepCopyInto(out *TLSConfig) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.CACertificate != nil { + in, out := &in.CACertificate, &out.CACertificate + *out = new(TLSCACertificate) + (*in).DeepCopyInto(*out) + } if in.MinVersion != nil { in, out := &in.MinVersion, &out.MinVersion *out = new(TLSVersion) @@ -1602,6 +1984,31 @@ func (in *TextAccessLog) DeepCopy() *TextAccessLog { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Timeout) DeepCopyInto(out *Timeout) { + *out = *in + if in.TCP != nil { + in, out := &in.TCP, &out.TCP + *out = new(TCPTimeout) + (*in).DeepCopyInto(*out) + } + if in.HTTP != nil { + in, out := &in.HTTP, &out.HTTP + *out = new(HTTPTimeout) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Timeout. +func (in *Timeout) DeepCopy() *Timeout { + if in == nil { + return nil + } + out := new(Timeout) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Tracing) DeepCopyInto(out *Tracing) { *out = *in diff --git a/internal/logging/log_test.go b/internal/logging/log_test.go index d71bee8b6b4..788d47cc3ac 100644 --- a/internal/logging/log_test.go +++ b/internal/logging/log_test.go @@ -11,6 +11,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "go.uber.org/zap" "go.uber.org/zap/zapcore" @@ -38,8 +39,8 @@ func TestLogger(t *testing.T) { logger.WithName(string(v1alpha1.LogComponentGlobalRateLimitRunner)).WithValues("runner", v1alpha1.LogComponentGlobalRateLimitRunner).Info("msg", "k", "v") defaultLogger := DefaultLogger(v1alpha1.LogLevelInfo) - assert.True(t, defaultLogger.logging != nil) - assert.True(t, defaultLogger.sugaredLogger != nil) + assert.NotNil(t, defaultLogger.logging) + assert.NotNil(t, defaultLogger.sugaredLogger) } func TestLoggerWithName(t *testing.T) { @@ -51,7 +52,7 @@ func TestLoggerWithName(t *testing.T) { // Restore the original stdout and close the pipe os.Stdout = originalStdout err := w.Close() - assert.NoError(t, err) + require.NoError(t, err) }() config := v1alpha1.DefaultEnvoyGatewayLogging() @@ -64,7 +65,7 @@ func TestLoggerWithName(t *testing.T) { // Read from the pipe (captured stdout) outputBytes := make([]byte, 200) _, err := r.Read(outputBytes) - assert.NoError(t, err) + require.NoError(t, err) capturedOutput := string(outputBytes) assert.Contains(t, capturedOutput, string(v1alpha1.LogComponentInfrastructureRunner)) assert.Contains(t, capturedOutput, "info message") diff --git a/internal/message/types.go b/internal/message/types.go index 1825a8f033e..1328c2a853c 100644 --- a/internal/message/types.go +++ b/internal/message/types.go @@ -21,7 +21,7 @@ import ( type ProviderResources struct { // GatewayAPIResources is a map from a GatewayClass name to // a group of gateway API and other related resources. - GatewayAPIResources watchable.Map[string, *gatewayapi.Resources] + GatewayAPIResources watchable.Map[string, *gatewayapi.GatewayClassResources] // GatewayAPIStatuses is a group of gateway api // resource statuses maps. @@ -31,7 +31,7 @@ type ProviderResources struct { PolicyStatuses } -func (p *ProviderResources) GetResources() *gatewayapi.Resources { +func (p *ProviderResources) GetResources() *gatewayapi.GatewayClassResources { if p.GatewayAPIResources.Len() == 0 { return nil } diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go index f9bca7f01a1..af42d4c178b 100644 --- a/internal/provider/kubernetes/controller.go +++ b/internal/provider/kubernetes/controller.go @@ -13,6 +13,7 @@ import ( corev1 "k8s.io/api/core/v1" discoveryv1 "k8s.io/api/discovery/v1" kerrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/runtime/schema" @@ -30,7 +31,7 @@ import ( gwapiv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" mcsapi "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1" - "github.com/envoyproxy/gateway/api/v1alpha1" + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/api/v1alpha1/validation" "github.com/envoyproxy/gateway/internal/envoygateway/config" "github.com/envoyproxy/gateway/internal/gatewayapi" @@ -41,22 +42,6 @@ import ( "github.com/envoyproxy/gateway/internal/utils/slice" ) -const ( - classGatewayIndex = "classGatewayIndex" - gatewayTLSRouteIndex = "gatewayTLSRouteIndex" - gatewayHTTPRouteIndex = "gatewayHTTPRouteIndex" - gatewayGRPCRouteIndex = "gatewayGRPCRouteIndex" - gatewayTCPRouteIndex = "gatewayTCPRouteIndex" - gatewayUDPRouteIndex = "gatewayUDPRouteIndex" - secretGatewayIndex = "secretGatewayIndex" - targetRefGrantRouteIndex = "targetRefGrantRouteIndex" - backendHTTPRouteIndex = "backendHTTPRouteIndex" - backendGRPCRouteIndex = "backendGRPCRouteIndex" - backendTLSRouteIndex = "backendTLSRouteIndex" - backendTCPRouteIndex = "backendTCPRouteIndex" - backendUDPRouteIndex = "backendUDPRouteIndex" -) - type gatewayAPIReconciler struct { client client.Client log logging.Logger @@ -64,12 +49,11 @@ type gatewayAPIReconciler struct { classController gwapiv1.GatewayController store *kubernetesProviderStore namespace string - namespaceLabels []string - envoyGateway *v1alpha1.EnvoyGateway - mergeGateways bool - - resources *message.ProviderResources - extGVKs []schema.GroupVersionKind + namespaceLabel *metav1.LabelSelector + envoyGateway *egv1a1.EnvoyGateway + mergeGateways map[string]bool + resources *message.ProviderResources + extGVKs []schema.GroupVersionKind } // newGatewayAPIController @@ -86,27 +70,28 @@ func newGatewayAPIController(mgr manager.Manager, cfg *config.Server, su status. } } - var namespaceLabels []string byNamespaceSelector := cfg.EnvoyGateway.Provider != nil && cfg.EnvoyGateway.Provider.Kubernetes != nil && cfg.EnvoyGateway.Provider.Kubernetes.Watch != nil && - cfg.EnvoyGateway.Provider.Kubernetes.Watch.Type == v1alpha1.KubernetesWatchModeTypeNamespaceSelectors && - len(cfg.EnvoyGateway.Provider.Kubernetes.Watch.NamespaceSelectors) != 0 - if byNamespaceSelector { - namespaceLabels = cfg.EnvoyGateway.Provider.Kubernetes.Watch.NamespaceSelectors - } + cfg.EnvoyGateway.Provider.Kubernetes.Watch.Type == egv1a1.KubernetesWatchModeTypeNamespaceSelector && + (cfg.EnvoyGateway.Provider.Kubernetes.Watch.NamespaceSelector.MatchLabels != nil || + len(cfg.EnvoyGateway.Provider.Kubernetes.Watch.NamespaceSelector.MatchExpressions) > 0) r := &gatewayAPIReconciler{ client: mgr.GetClient(), log: cfg.Logger, classController: gwapiv1.GatewayController(cfg.EnvoyGateway.Gateway.ControllerName), namespace: cfg.Namespace, - namespaceLabels: namespaceLabels, statusUpdater: su, resources: resources, extGVKs: extGVKs, store: newProviderStore(), envoyGateway: cfg.EnvoyGateway, + mergeGateways: map[string]bool{}, + } + + if byNamespaceSelector { + r.namespaceLabel = cfg.EnvoyGateway.Provider.Kubernetes.Watch.NamespaceSelector } c, err := controller.New("gatewayapi", mgr, controller.Options{Reconciler: r}) @@ -130,7 +115,7 @@ type resourceMappings struct { allAssociatedNamespaces map[string]struct{} // Map for storing backendRefs' NamespaceNames referred by various Route objects. allAssociatedBackendRefs map[gwapiv1.BackendObjectReference]struct{} - // Map for storing referenceGrant NamespaceNames for BackendRefs, SecretRefs. + // Map for storing referenceGrant NamespaceNames for BackendRefs, SecretRefs, ConfigMapRefs. allAssociatedRefGrants map[types.NamespacedName]*gwapiv1b1.ReferenceGrant // extensionRefFilters is a map of filters managed by an extension. // The key is the namespaced name of the filter and the value is the @@ -169,9 +154,6 @@ func (r *gatewayAPIReconciler) Reconcile(ctx context.Context, _ reconcile.Reques !slice.ContainsString(gwClass.Finalizers, gatewayClassFinalizer) { r.log.Info("gatewayclass marked for deletion") cc.removeMatch(&gwClass) - - // Delete the gatewayclass from the watchable map. - r.resources.GatewayAPIResources.Delete(gwClass.Name) continue } @@ -180,94 +162,88 @@ func (r *gatewayAPIReconciler) Reconcile(ctx context.Context, _ reconcile.Reques } // The gatewayclass was already deleted/finalized and there are stale queue entries. - acceptedGC := cc.acceptedClass() - if acceptedGC == nil { + acceptedGCs := cc.matchedClasses + if acceptedGCs == nil { + r.resources.GatewayAPIResources.Delete(string(r.classController)) r.log.Info("no accepted gatewayclass") return reconcile.Result{}, nil } - // Update status for all gateway classes - for _, gc := range cc.notAcceptedClasses() { - if err := r.gatewayClassUpdater(ctx, gc, false, string(status.ReasonOlderGatewayClassExists), - status.MsgOlderGatewayClassExists); err != nil { - r.resources.GatewayAPIResources.Delete(acceptedGC.Name) + resourcesMap := make(gatewayapi.GatewayClassResources) + for _, acceptedGC := range acceptedGCs { + // Initialize resource types. + acceptedGC := acceptedGC + resourcesMap[acceptedGC.Name] = gatewayapi.NewResources() + resourceMappings := newResourceMapping() + + if err := r.processGateways(ctx, acceptedGC, resourceMappings, resourcesMap[acceptedGC.Name]); err != nil { return reconcile.Result{}, err } - } - - // Initialize resource types. - resourceTree := gatewayapi.NewResources() - resourceMap := newResourceMapping() - - if err := r.processGateways(ctx, acceptedGC, resourceMap, resourceTree); err != nil { - return reconcile.Result{}, err - } - for backendRef := range resourceMap.allAssociatedBackendRefs { - backendRefKind := gatewayapi.KindDerefOr(backendRef.Kind, gatewayapi.KindService) - r.log.Info("processing Backend", "kind", backendRefKind, "namespace", string(*backendRef.Namespace), - "name", string(backendRef.Name)) - - var endpointSliceLabelKey string - switch backendRefKind { - case gatewayapi.KindService: - service := new(corev1.Service) - err := r.client.Get(ctx, types.NamespacedName{Namespace: string(*backendRef.Namespace), Name: string(backendRef.Name)}, service) - if err != nil { - r.log.Error(err, "failed to get Service", "namespace", string(*backendRef.Namespace), - "name", string(backendRef.Name)) - } else { - resourceMap.allAssociatedNamespaces[service.Namespace] = struct{}{} - resourceTree.Services = append(resourceTree.Services, service) - r.log.Info("added Service to resource tree", "namespace", string(*backendRef.Namespace), - "name", string(backendRef.Name)) + for backendRef := range resourceMappings.allAssociatedBackendRefs { + backendRefKind := gatewayapi.KindDerefOr(backendRef.Kind, gatewayapi.KindService) + r.log.Info("processing Backend", "kind", backendRefKind, "namespace", string(*backendRef.Namespace), + "name", string(backendRef.Name)) + + var endpointSliceLabelKey string + switch backendRefKind { + case gatewayapi.KindService: + service := new(corev1.Service) + err := r.client.Get(ctx, types.NamespacedName{Namespace: string(*backendRef.Namespace), Name: string(backendRef.Name)}, service) + if err != nil { + r.log.Error(err, "failed to get Service", "namespace", string(*backendRef.Namespace), + "name", string(backendRef.Name)) + } else { + resourceMappings.allAssociatedNamespaces[service.Namespace] = struct{}{} + resourcesMap[acceptedGC.Name].Services = append(resourcesMap[acceptedGC.Name].Services, service) + r.log.Info("added Service to resource tree", "namespace", string(*backendRef.Namespace), + "name", string(backendRef.Name)) + } + endpointSliceLabelKey = discoveryv1.LabelServiceName + + case gatewayapi.KindServiceImport: + serviceImport := new(mcsapi.ServiceImport) + err := r.client.Get(ctx, types.NamespacedName{Namespace: string(*backendRef.Namespace), Name: string(backendRef.Name)}, serviceImport) + if err != nil { + r.log.Error(err, "failed to get ServiceImport", "namespace", string(*backendRef.Namespace), + "name", string(backendRef.Name)) + } else { + resourceMappings.allAssociatedNamespaces[serviceImport.Namespace] = struct{}{} + resourcesMap[acceptedGC.Name].ServiceImports = append(resourcesMap[acceptedGC.Name].ServiceImports, serviceImport) + r.log.Info("added ServiceImport to resource tree", "namespace", string(*backendRef.Namespace), + "name", string(backendRef.Name)) + } + endpointSliceLabelKey = mcsapi.LabelServiceName } - endpointSliceLabelKey = discoveryv1.LabelServiceName - case gatewayapi.KindServiceImport: - serviceImport := new(mcsapi.ServiceImport) - err := r.client.Get(ctx, types.NamespacedName{Namespace: string(*backendRef.Namespace), Name: string(backendRef.Name)}, serviceImport) - if err != nil { - r.log.Error(err, "failed to get ServiceImport", "namespace", string(*backendRef.Namespace), - "name", string(backendRef.Name)) + // Retrieve the EndpointSlices associated with the service + endpointSliceList := new(discoveryv1.EndpointSliceList) + opts := []client.ListOption{ + client.MatchingLabels(map[string]string{ + endpointSliceLabelKey: string(backendRef.Name), + }), + client.InNamespace(string(*backendRef.Namespace)), + } + if err := r.client.List(ctx, endpointSliceList, opts...); err != nil { + r.log.Error(err, "failed to get EndpointSlices", "namespace", string(*backendRef.Namespace), + backendRefKind, string(backendRef.Name)) } else { - resourceMap.allAssociatedNamespaces[serviceImport.Namespace] = struct{}{} - resourceTree.ServiceImports = append(resourceTree.ServiceImports, serviceImport) - r.log.Info("added ServiceImport to resource tree", "namespace", string(*backendRef.Namespace), - "name", string(backendRef.Name)) + for _, endpointSlice := range endpointSliceList.Items { + endpointSlice := endpointSlice + r.log.Info("added EndpointSlice to resource tree", "namespace", endpointSlice.Namespace, + "name", endpointSlice.Name) + resourcesMap[acceptedGC.Name].EndpointSlices = append(resourcesMap[acceptedGC.Name].EndpointSlices, &endpointSlice) + } } - endpointSliceLabelKey = mcsapi.LabelServiceName } - // Retrieve the EndpointSlices associated with the service - endpointSliceList := new(discoveryv1.EndpointSliceList) - opts := []client.ListOption{ - client.MatchingLabels(map[string]string{ - endpointSliceLabelKey: string(backendRef.Name), - }), - client.InNamespace(string(*backendRef.Namespace)), + // Add all ReferenceGrants to the resourceTree + for _, referenceGrant := range resourceMappings.allAssociatedRefGrants { + resourcesMap[acceptedGC.Name].ReferenceGrants = append(resourcesMap[acceptedGC.Name].ReferenceGrants, referenceGrant) } - if err := r.client.List(ctx, endpointSliceList, opts...); err != nil { - r.log.Error(err, "failed to get EndpointSlices", "namespace", string(*backendRef.Namespace), - backendRefKind, string(backendRef.Name)) - } else { - for _, endpointSlice := range endpointSliceList.Items { - endpointSlice := endpointSlice - r.log.Info("added EndpointSlice to resource tree", "namespace", endpointSlice.Namespace, - "name", endpointSlice.Name) - resourceTree.EndpointSlices = append(resourceTree.EndpointSlices, &endpointSlice) - } - } - } - - // Add all ReferenceGrants to the resourceTree - for _, referenceGrant := range resourceMap.allAssociatedRefGrants { - resourceTree.ReferenceGrants = append(resourceTree.ReferenceGrants, referenceGrant) - } - // Add all EnvoyPatchPolicies - if r.envoyGateway.ExtensionAPIs != nil && r.envoyGateway.ExtensionAPIs.EnableEnvoyPatchPolicy { - envoyPatchPolicies := v1alpha1.EnvoyPatchPolicyList{} + // Add all EnvoyPatchPolicies + envoyPatchPolicies := egv1a1.EnvoyPatchPolicyList{} if err := r.client.List(ctx, &envoyPatchPolicies); err != nil { return reconcile.Result{}, fmt.Errorf("error listing EnvoyPatchPolicies: %w", err) } @@ -276,116 +252,118 @@ func (r *gatewayAPIReconciler) Reconcile(ctx context.Context, _ reconcile.Reques policy := policy // Discard Status to reduce memory consumption in watchable // It will be recomputed by the gateway-api layer - policy.Status = v1alpha1.EnvoyPatchPolicyStatus{} - resourceTree.EnvoyPatchPolicies = append(resourceTree.EnvoyPatchPolicies, &policy) - } - } + policy.Status = egv1a1.EnvoyPatchPolicyStatus{} - // Add all ClientTrafficPolicies - clientTrafficPolicies := v1alpha1.ClientTrafficPolicyList{} - if err := r.client.List(ctx, &clientTrafficPolicies); err != nil { - return reconcile.Result{}, fmt.Errorf("error listing ClientTrafficPolicies: %w", err) - } + resourcesMap[acceptedGC.Name].EnvoyPatchPolicies = append(resourcesMap[acceptedGC.Name].EnvoyPatchPolicies, &policy) + } - for _, policy := range clientTrafficPolicies.Items { - policy := policy - // Discard Status to reduce memory consumption in watchable - // It will be recomputed by the gateway-api layer - policy.Status = v1alpha1.ClientTrafficPolicyStatus{} - resourceTree.ClientTrafficPolicies = append(resourceTree.ClientTrafficPolicies, &policy) + // Add all ClientTrafficPolicies + clientTrafficPolicies := egv1a1.ClientTrafficPolicyList{} + if err := r.client.List(ctx, &clientTrafficPolicies); err != nil { + return reconcile.Result{}, fmt.Errorf("error listing ClientTrafficPolicies: %w", err) + } - } + for _, policy := range clientTrafficPolicies.Items { + policy := policy + // Discard Status to reduce memory consumption in watchable + // It will be recomputed by the gateway-api layer + policy.Status = egv1a1.ClientTrafficPolicyStatus{} + resourcesMap[acceptedGC.Name].ClientTrafficPolicies = append(resourcesMap[acceptedGC.Name].ClientTrafficPolicies, &policy) - // Add all BackendTrafficPolicies - backendTrafficPolicies := v1alpha1.BackendTrafficPolicyList{} - if err := r.client.List(ctx, &backendTrafficPolicies); err != nil { - return reconcile.Result{}, fmt.Errorf("error listing BackendTrafficPolicies: %w", err) - } + } - for _, policy := range backendTrafficPolicies.Items { - policy := policy - // Discard Status to reduce memory consumption in watchable - // It will be recomputed by the gateway-api layer - policy.Status = v1alpha1.BackendTrafficPolicyStatus{} - resourceTree.BackendTrafficPolicies = append(resourceTree.BackendTrafficPolicies, &policy) - } + // Add the referenced ConfigMaps in ClientTrafficPolicies to the resourceTree + r.processCtpConfigMapRefs(ctx, resourcesMap[acceptedGC.Name], resourceMappings) - // Add all SecurityPolicies - securityPolicies := v1alpha1.SecurityPolicyList{} - if err := r.client.List(ctx, &securityPolicies); err != nil { - return reconcile.Result{}, fmt.Errorf("error listing SecurityPolicies: %w", err) - } + // Add all BackendTrafficPolicies + backendTrafficPolicies := egv1a1.BackendTrafficPolicyList{} + if err := r.client.List(ctx, &backendTrafficPolicies); err != nil { + return reconcile.Result{}, fmt.Errorf("error listing BackendTrafficPolicies: %w", err) + } - for _, policy := range securityPolicies.Items { - policy := policy - // Discard Status to reduce memory consumption in watchable - // It will be recomputed by the gateway-api layer - policy.Status = v1alpha1.SecurityPolicyStatus{} - resourceTree.SecurityPolicies = append(resourceTree.SecurityPolicies, &policy) - } + for _, policy := range backendTrafficPolicies.Items { + policy := policy + // Discard Status to reduce memory consumption in watchable + // It will be recomputed by the gateway-api layer + policy.Status = egv1a1.BackendTrafficPolicyStatus{} + resourcesMap[acceptedGC.Name].BackendTrafficPolicies = append(resourcesMap[acceptedGC.Name].BackendTrafficPolicies, &policy) + } - // Add the referenced Secrets in SecurityPolicies to the resourceTree - r.processSecurityPolicySecretRefs(ctx, resourceTree, resourceMap) + // Add all SecurityPolicies + securityPolicies := egv1a1.SecurityPolicyList{} + if err := r.client.List(ctx, &securityPolicies); err != nil { + return reconcile.Result{}, fmt.Errorf("error listing SecurityPolicies: %w", err) + } - // For this particular Gateway, and all associated objects, check whether the - // namespace exists. Add to the resourceTree. - for ns := range resourceMap.allAssociatedNamespaces { - namespace, err := r.getNamespace(ctx, ns) - if err != nil { - r.log.Error(err, "unable to find the namespace") - if kerrors.IsNotFound(err) { - return reconcile.Result{}, nil - } - return reconcile.Result{}, err + for _, policy := range securityPolicies.Items { + policy := policy + // Discard Status to reduce memory consumption in watchable + // It will be recomputed by the gateway-api layer + policy.Status = egv1a1.SecurityPolicyStatus{} + resourcesMap[acceptedGC.Name].SecurityPolicies = append(resourcesMap[acceptedGC.Name].SecurityPolicies, &policy) } - resourceTree.Namespaces = append(resourceTree.Namespaces, namespace) - } + // Add the referenced Secrets in SecurityPolicies to the resourceTree + r.processSecurityPolicySecretRefs(ctx, resourcesMap[acceptedGC.Name], resourceMappings) - // Process the parametersRef of the accepted GatewayClass. - if acceptedGC.Spec.ParametersRef != nil && acceptedGC.DeletionTimestamp == nil { - if err := r.processParamsRef(ctx, acceptedGC, resourceTree); err != nil { - msg := fmt.Sprintf("%s: %v", status.MsgGatewayClassInvalidParams, err) - if err := r.gatewayClassUpdater(ctx, acceptedGC, false, string(gwapiv1.GatewayClassReasonInvalidParameters), msg); err != nil { - r.log.Error(err, "unable to update GatewayClass status") + // For this particular Gateway, and all associated objects, check whether the + // namespace exists. Add to the resourceTree. + for ns := range resourceMappings.allAssociatedNamespaces { + namespace, err := r.getNamespace(ctx, ns) + if err != nil { + r.log.Error(err, "unable to find the namespace") + if kerrors.IsNotFound(err) { + return reconcile.Result{}, nil + } + return reconcile.Result{}, err } - r.log.Error(err, "failed to process parametersRef for gatewayclass", "name", acceptedGC.Name) - return reconcile.Result{}, err - } - } - if resourceTree.EnvoyProxy != nil && resourceTree.EnvoyProxy.Spec.MergeGateways != nil { - r.mergeGateways = *resourceTree.EnvoyProxy.Spec.MergeGateways - } + resourcesMap[acceptedGC.Name].Namespaces = append(resourcesMap[acceptedGC.Name].Namespaces, namespace) + } - if err := r.gatewayClassUpdater(ctx, acceptedGC, true, string(gwapiv1.GatewayClassReasonAccepted), status.MsgValidGatewayClass); err != nil { - r.log.Error(err, "unable to update GatewayClass status") - return reconcile.Result{}, err - } + // Process the parametersRef of the accepted GatewayClass. + if acceptedGC.Spec.ParametersRef != nil && acceptedGC.DeletionTimestamp == nil { + if err := r.processParamsRef(ctx, acceptedGC, resourcesMap[acceptedGC.Name]); err != nil { + msg := fmt.Sprintf("%s: %v", status.MsgGatewayClassInvalidParams, err) + if err := r.updateStatusForGatewayClass(ctx, acceptedGC, false, string(gwapiv1.GatewayClassReasonInvalidParameters), msg); err != nil { + r.log.Error(err, "unable to update GatewayClass status") + } + r.log.Error(err, "failed to process parametersRef for gatewayclass", "name", acceptedGC.Name) + return reconcile.Result{}, err + } + } - // Update finalizer on the gateway class based on the resource tree. - if len(resourceTree.Gateways) == 0 { - r.log.Info("No gateways found for accepted gatewayclass") + if resourcesMap[acceptedGC.Name].EnvoyProxy != nil && resourcesMap[acceptedGC.Name].EnvoyProxy.Spec.MergeGateways != nil { + r.mergeGateways[acceptedGC.Name] = *resourcesMap[acceptedGC.Name].EnvoyProxy.Spec.MergeGateways + } - // If needed, remove the finalizer from the accepted GatewayClass. - if err := r.removeFinalizer(ctx, acceptedGC); err != nil { - r.log.Error(err, fmt.Sprintf("failed to remove finalizer from gatewayclass %s", - acceptedGC.Name)) + if err := r.updateStatusForGatewayClass(ctx, acceptedGC, true, string(gwapiv1.GatewayClassReasonAccepted), status.MsgValidGatewayClass); err != nil { + r.log.Error(err, "unable to update GatewayClass status") return reconcile.Result{}, err } - } else { - // finalize the accepted GatewayClass. - if err := r.addFinalizer(ctx, acceptedGC); err != nil { - r.log.Error(err, fmt.Sprintf("failed adding finalizer to gatewayclass %s", - acceptedGC.Name)) - return reconcile.Result{}, err + + if len(resourcesMap[acceptedGC.Name].Gateways) == 0 { + r.log.Info("No gateways found for accepted gatewayclass") + + // If needed, remove the finalizer from the accepted GatewayClass. + if err := r.removeFinalizer(ctx, acceptedGC); err != nil { + r.log.Error(err, fmt.Sprintf("failed to remove finalizer from gatewayclass %s", + acceptedGC.Name)) + return reconcile.Result{}, err + } + } else { + // finalize the accepted GatewayClass. + if err := r.addFinalizer(ctx, acceptedGC); err != nil { + r.log.Error(err, fmt.Sprintf("failed adding finalizer to gatewayclass %s", + acceptedGC.Name)) + return reconcile.Result{}, err + } } } - // The Store is triggered even when there are no Gateways associated to the // GatewayClass. This would happen in case the last Gateway is removed and the // Store will be required to trigger a cleanup of envoy infra resources. - r.resources.GatewayAPIResources.Store(acceptedGC.Name, resourceTree) + r.resources.GatewayAPIResources.Store(string(r.classController), resourcesMap.DeepCopy()) r.log.Info("reconciled gateways successfully") return reconcile.Result{}, nil @@ -490,28 +468,104 @@ func (r *gatewayAPIReconciler) processSecretRef( return nil } -func (r *gatewayAPIReconciler) gatewayClassUpdater(ctx context.Context, gc *gwapiv1.GatewayClass, accepted bool, reason, msg string) error { - if r.statusUpdater != nil { - r.statusUpdater.Send(status.Update{ - NamespacedName: types.NamespacedName{Name: gc.Name}, - Resource: &gwapiv1.GatewayClass{}, - Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - gc, ok := obj.(*gwapiv1.GatewayClass) - if !ok { - panic(fmt.Sprintf("unsupported object type %T", obj)) +// processCtpConfigMapRefs adds the referenced ConfigMaps in ClientTrafficPolicies +// to the resourceTree +func (r *gatewayAPIReconciler) processCtpConfigMapRefs( + ctx context.Context, resourceTree *gatewayapi.Resources, resourceMap *resourceMappings) { + for _, policy := range resourceTree.ClientTrafficPolicies { + tls := policy.Spec.TLS + + if tls != nil && tls.ClientValidation != nil { + for _, caCertRef := range tls.ClientValidation.CACertificateRefs { + if caCertRef.Kind != nil && string(*caCertRef.Kind) == gatewayapi.KindConfigMap { + if err := r.processConfigMapRef( + ctx, + resourceMap, + resourceTree, + gatewayapi.KindClientTrafficPolicy, + policy.Namespace, + policy.Name, + caCertRef); err != nil { + // we don't return an error here, because we want to continue + // reconciling the rest of the ClientTrafficPolicies despite that this + // reference is invalid. + // This ClientTrafficPolicy will be marked as invalid in its status + // when translating to IR because the referenced configmap can't be + // found. + r.log.Error(err, + "failed to process CACertificateRef for ClientTrafficPolicy", + "policy", policy, "caCertificateRef", caCertRef.Name) + } + } else if caCertRef.Kind == nil || string(*caCertRef.Kind) == gatewayapi.KindSecret { + if err := r.processSecretRef( + ctx, + resourceMap, + resourceTree, + gatewayapi.KindClientTrafficPolicy, + policy.Namespace, + policy.Name, + caCertRef); err != nil { + r.log.Error(err, + "failed to process CACertificateRef for SecurityPolicy", + "policy", policy, "caCertificateRef", caCertRef.Name) + } } + } + } + } +} - return status.SetGatewayClassAccepted(gc.DeepCopy(), accepted, reason, msg) - }), - }) - } else { - // this branch makes testing easier by not going through the status.Updater. - duplicate := status.SetGatewayClassAccepted(gc.DeepCopy(), accepted, reason, msg) +// processConfigMapRef adds the referenced ConfigMap to the resourceTree if it's valid. +// - If it exists in the same namespace as the owner. +// - If it exists in a different namespace, and there is a ReferenceGrant. +func (r *gatewayAPIReconciler) processConfigMapRef( + ctx context.Context, + resourceMap *resourceMappings, + resourceTree *gatewayapi.Resources, + ownerKind string, + ownerNS string, + ownerName string, + configMapRef gwapiv1b1.SecretObjectReference, +) error { + configMap := new(corev1.ConfigMap) + configMapNS := gatewayapi.NamespaceDerefOr(configMapRef.Namespace, ownerNS) + err := r.client.Get(ctx, + types.NamespacedName{Namespace: configMapNS, Name: string(configMapRef.Name)}, + configMap, + ) + if err != nil && !kerrors.IsNotFound(err) { + return fmt.Errorf("unable to find the ConfigMap: %s/%s", configMapNS, string(configMapRef.Name)) + } - if err := r.client.Status().Update(ctx, duplicate); err != nil && !kerrors.IsNotFound(err) { - return fmt.Errorf("error updating status of gatewayclass %s: %w", duplicate.Name, err) + if configMapNS != ownerNS { + from := ObjectKindNamespacedName{ + kind: ownerKind, + namespace: ownerNS, + name: ownerName, + } + to := ObjectKindNamespacedName{ + kind: gatewayapi.KindConfigMap, + namespace: configMapNS, + name: configMap.Name, + } + refGrant, err := r.findReferenceGrant(ctx, from, to) + switch { + case err != nil: + return fmt.Errorf("failed to find ReferenceGrant: %w", err) + case refGrant == nil: + return fmt.Errorf( + "no matching ReferenceGrants found: from %s/%s to %s/%s", + from.kind, from.namespace, to.kind, to.namespace) + default: + // RefGrant found + resourceMap.allAssociatedRefGrants[utils.NamespacedName(refGrant)] = refGrant + r.log.Info("added ReferenceGrant to resource map", "namespace", refGrant.Namespace, + "name", refGrant.Name) } } + resourceMap.allAssociatedNamespaces[configMapNS] = struct{}{} // TODO Zhaohuabing do we need this line? + resourceTree.ConfigMaps = append(resourceTree.ConfigMaps, configMap) + r.log.Info("processing ConfigMap", "namespace", configMapNS, "name", string(configMapRef.Name)) return nil } @@ -525,50 +579,6 @@ func (r *gatewayAPIReconciler) getNamespace(ctx context.Context, name string) (* return ns, nil } -func (r *gatewayAPIReconciler) statusUpdateForGateway(ctx context.Context, gtw *gwapiv1.Gateway) { - // nil check for unit tests. - if r.statusUpdater == nil { - return - } - - // Get deployment - deploy, err := r.envoyDeploymentForGateway(ctx, gtw) - if err != nil { - r.log.Info("failed to get Deployment for gateway", - "namespace", gtw.Namespace, "name", gtw.Name) - } - - // Get service - svc, err := r.envoyServiceForGateway(ctx, gtw) - if err != nil { - r.log.Info("failed to get Service for gateway", - "namespace", gtw.Namespace, "name", gtw.Name) - } - // update accepted condition - status.UpdateGatewayStatusAcceptedCondition(gtw, true) - // update address field and programmed condition - status.UpdateGatewayStatusProgrammedCondition(gtw, svc, deploy, r.store.listNodeAddresses()...) - - key := utils.NamespacedName(gtw) - - // publish status - r.statusUpdater.Send(status.Update{ - NamespacedName: key, - Resource: new(gwapiv1.Gateway), - Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - g, ok := obj.(*gwapiv1.Gateway) - if !ok { - panic(fmt.Sprintf("unsupported object type %T", obj)) - } - gCopy := g.DeepCopy() - gCopy.Status.Conditions = gtw.Status.Conditions - gCopy.Status.Addresses = gtw.Status.Addresses - gCopy.Status.Listeners = gtw.Status.Listeners - return gCopy - }), - }) -} - func (r *gatewayAPIReconciler) findReferenceGrant(ctx context.Context, from, to ObjectKindNamespacedName) (*gwapiv1b1.ReferenceGrant, error) { refGrantList := new(gwapiv1b1.ReferenceGrantList) opts := &client.ListOptions{FieldSelector: fields.OneTermEqualSelector(targetRefGrantRouteIndex, to.kind)} @@ -577,17 +587,14 @@ func (r *gatewayAPIReconciler) findReferenceGrant(ctx context.Context, from, to } refGrants := refGrantList.Items - if len(r.namespaceLabels) != 0 { + if r.namespaceLabel != nil { var rgs []gwapiv1b1.ReferenceGrant for _, refGrant := range refGrants { - ns := refGrant.GetNamespace() - ok, err := r.checkObjectNamespaceLabels(ns) - if err != nil { - // TODO: should return? or just proceed? - return nil, fmt.Errorf("failed to check namespace labels for ReferenceGrant %s in namespace %s: %w", refGrant.GetName(), ns, err) - } - if !ok { - // TODO: should log? + refGrant := refGrant + if ok, err := r.checkObjectNamespaceLabels(&refGrant); err != nil { + r.log.Error(err, "failed to check namespace labels for ReferenceGrant %s in namespace %s: %w", refGrant.GetName(), refGrant.GetNamespace()) + continue + } else if !ok { continue } rgs = append(rgs, refGrant) @@ -620,26 +627,16 @@ func (r *gatewayAPIReconciler) processGateways(ctx context.Context, acceptedGC * return err } - gateways := gatewayList.Items - if len(r.namespaceLabels) != 0 { - var gtws []gwapiv1.Gateway - for _, gtw := range gateways { - ns := gtw.GetNamespace() - ok, err := r.checkObjectNamespaceLabels(ns) - if err != nil { - // TODO: should return? or just proceed? - return fmt.Errorf("failed to check namespace labels for gateway %s in namespace %s: %w", gtw.GetName(), ns, err) - } - - if ok { - gtws = append(gtws, gtw) + for _, gtw := range gatewayList.Items { + gtw := gtw + if r.namespaceLabel != nil { + if ok, err := r.checkObjectNamespaceLabels(>w); err != nil { + r.log.Error(err, "failed to check namespace labels for gateway %s in namespace %s: %w", gtw.GetName(), gtw.GetNamespace()) + continue + } else if !ok { + continue } } - gateways = gtws - } - - for _, gtw := range gateways { - gtw := gtw r.log.Info("processing Gateway", "namespace", gtw.Namespace, "name", gtw.Name) resourceMap.allAssociatedNamespaces[gtw.Namespace] = struct{}{} @@ -699,319 +696,10 @@ func (r *gatewayAPIReconciler) processGateways(ctx context.Context, acceptedGC * gtw.Status = gwapiv1.GatewayStatus{} resourceTree.Gateways = append(resourceTree.Gateways, >w) } - return nil -} - -func addReferenceGrantIndexers(ctx context.Context, mgr manager.Manager) error { - if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1b1.ReferenceGrant{}, targetRefGrantRouteIndex, func(rawObj client.Object) []string { - refGrant := rawObj.(*gwapiv1b1.ReferenceGrant) - var referredServices []string - for _, target := range refGrant.Spec.To { - referredServices = append(referredServices, string(target.Kind)) - } - return referredServices - }); err != nil { - return err - } - return nil -} - -// addHTTPRouteIndexers adds indexing on HTTPRoute. -// - For Service, ServiceImports objects that are referenced in HTTPRoute objects via `.spec.rules.backendRefs`. -// This helps in querying for HTTPRoutes that are affected by a particular Service CRUD. -func addHTTPRouteIndexers(ctx context.Context, mgr manager.Manager) error { - if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1.HTTPRoute{}, gatewayHTTPRouteIndex, gatewayHTTPRouteIndexFunc); err != nil { - return err - } - - if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1.HTTPRoute{}, backendHTTPRouteIndex, backendHTTPRouteIndexFunc); err != nil { - return err - } - - return nil -} - -func gatewayHTTPRouteIndexFunc(rawObj client.Object) []string { - httproute := rawObj.(*gwapiv1.HTTPRoute) - var gateways []string - for _, parent := range httproute.Spec.ParentRefs { - if parent.Kind == nil || string(*parent.Kind) == gatewayapi.KindGateway { - // If an explicit Gateway namespace is not provided, use the HTTPRoute namespace to - // lookup the provided Gateway Name. - gateways = append(gateways, - types.NamespacedName{ - Namespace: gatewayapi.NamespaceDerefOr(parent.Namespace, httproute.Namespace), - Name: string(parent.Name), - }.String(), - ) - } - } - return gateways -} - -func backendHTTPRouteIndexFunc(rawObj client.Object) []string { - httproute := rawObj.(*gwapiv1.HTTPRoute) - var backendRefs []string - for _, rule := range httproute.Spec.Rules { - for _, backend := range rule.BackendRefs { - if backend.Kind == nil || string(*backend.Kind) == gatewayapi.KindService { - // If an explicit Backend namespace is not provided, use the HTTPRoute namespace to - // lookup the provided Gateway Name. - backendRefs = append(backendRefs, - types.NamespacedName{ - Namespace: gatewayapi.NamespaceDerefOr(backend.Namespace, httproute.Namespace), - Name: string(backend.Name), - }.String(), - ) - } - } - } - return backendRefs -} - -// addGRPCRouteIndexers adds indexing on GRPCRoute, for Service objects that are -// referenced in GRPCRoute objects via `.spec.rules.backendRefs`. This helps in -// querying for GRPCRoutes that are affected by a particular Service CRUD. -func addGRPCRouteIndexers(ctx context.Context, mgr manager.Manager) error { - if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1a2.GRPCRoute{}, gatewayGRPCRouteIndex, gatewayGRPCRouteIndexFunc); err != nil { - return err - } - - if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1a2.GRPCRoute{}, backendGRPCRouteIndex, backendGRPCRouteIndexFunc); err != nil { - return err - } return nil } -func gatewayGRPCRouteIndexFunc(rawObj client.Object) []string { - grpcroute := rawObj.(*gwapiv1a2.GRPCRoute) - var gateways []string - for _, parent := range grpcroute.Spec.ParentRefs { - if parent.Kind == nil || string(*parent.Kind) == gatewayapi.KindGateway { - // If an explicit Gateway namespace is not provided, use the GRPCRoute namespace to - // lookup the provided Gateway Name. - gateways = append(gateways, - types.NamespacedName{ - Namespace: gatewayapi.NamespaceDerefOr(parent.Namespace, grpcroute.Namespace), - Name: string(parent.Name), - }.String(), - ) - } - } - return gateways -} - -func backendGRPCRouteIndexFunc(rawObj client.Object) []string { - grpcroute := rawObj.(*gwapiv1a2.GRPCRoute) - var backendRefs []string - for _, rule := range grpcroute.Spec.Rules { - for _, backend := range rule.BackendRefs { - if backend.Kind == nil || string(*backend.Kind) == gatewayapi.KindService { - // If an explicit Backend namespace is not provided, use the GRPCRoute namespace to - // lookup the provided Gateway Name. - backendRefs = append(backendRefs, - types.NamespacedName{ - Namespace: gatewayapi.NamespaceDerefOr(backend.Namespace, grpcroute.Namespace), - Name: string(backend.Name), - }.String(), - ) - } - } - } - return backendRefs -} - -// addTLSRouteIndexers adds indexing on TLSRoute, for Service objects that are -// referenced in TLSRoute objects via `.spec.rules.backendRefs`. This helps in -// querying for TLSRoutes that are affected by a particular Service CRUD. -func addTLSRouteIndexers(ctx context.Context, mgr manager.Manager) error { - if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1a2.TLSRoute{}, gatewayTLSRouteIndex, func(rawObj client.Object) []string { - tlsRoute := rawObj.(*gwapiv1a2.TLSRoute) - var gateways []string - for _, parent := range tlsRoute.Spec.ParentRefs { - if string(*parent.Kind) == gatewayapi.KindGateway { - // If an explicit Gateway namespace is not provided, use the TLSRoute namespace to - // lookup the provided Gateway Name. - gateways = append(gateways, - types.NamespacedName{ - Namespace: gatewayapi.NamespaceDerefOrAlpha(parent.Namespace, tlsRoute.Namespace), - Name: string(parent.Name), - }.String(), - ) - } - } - return gateways - }); err != nil { - return err - } - - if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1a2.TLSRoute{}, backendTLSRouteIndex, backendTLSRouteIndexFunc); err != nil { - return err - } - return nil -} - -func backendTLSRouteIndexFunc(rawObj client.Object) []string { - tlsroute := rawObj.(*gwapiv1a2.TLSRoute) - var backendRefs []string - for _, rule := range tlsroute.Spec.Rules { - for _, backend := range rule.BackendRefs { - if backend.Kind == nil || string(*backend.Kind) == gatewayapi.KindService { - // If an explicit Backend namespace is not provided, use the TLSRoute namespace to - // lookup the provided Gateway Name. - backendRefs = append(backendRefs, - types.NamespacedName{ - Namespace: gatewayapi.NamespaceDerefOrAlpha(backend.Namespace, tlsroute.Namespace), - Name: string(backend.Name), - }.String(), - ) - } - } - } - return backendRefs -} - -// addTCPRouteIndexers adds indexing on TCPRoute, for Service objects that are -// referenced in TCPRoute objects via `.spec.rules.backendRefs`. This helps in -// querying for TCPRoutes that are affected by a particular Service CRUD. -func addTCPRouteIndexers(ctx context.Context, mgr manager.Manager) error { - if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1a2.TCPRoute{}, gatewayTCPRouteIndex, func(rawObj client.Object) []string { - tcpRoute := rawObj.(*gwapiv1a2.TCPRoute) - var gateways []string - for _, parent := range tcpRoute.Spec.ParentRefs { - if string(*parent.Kind) == gatewayapi.KindGateway { - // If an explicit Gateway namespace is not provided, use the TCPRoute namespace to - // lookup the provided Gateway Name. - gateways = append(gateways, - types.NamespacedName{ - Namespace: gatewayapi.NamespaceDerefOrAlpha(parent.Namespace, tcpRoute.Namespace), - Name: string(parent.Name), - }.String(), - ) - } - } - return gateways - }); err != nil { - return err - } - - if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1a2.TCPRoute{}, backendTCPRouteIndex, backendTCPRouteIndexFunc); err != nil { - return err - } - return nil -} - -func backendTCPRouteIndexFunc(rawObj client.Object) []string { - tcpRoute := rawObj.(*gwapiv1a2.TCPRoute) - var backendRefs []string - for _, rule := range tcpRoute.Spec.Rules { - for _, backend := range rule.BackendRefs { - if backend.Kind == nil || string(*backend.Kind) == gatewayapi.KindService { - // If an explicit Backend namespace is not provided, use the TCPRoute namespace to - // lookup the provided Gateway Name. - backendRefs = append(backendRefs, - types.NamespacedName{ - Namespace: gatewayapi.NamespaceDerefOrAlpha(backend.Namespace, tcpRoute.Namespace), - Name: string(backend.Name), - }.String(), - ) - } - } - } - return backendRefs -} - -// addUDPRouteIndexers adds indexing on UDPRoute, for Service objects that are -// referenced in UDPRoute objects via `.spec.rules.backendRefs`. This helps in -// querying for UDPRoutes that are affected by a particular Service CRUD. -func addUDPRouteIndexers(ctx context.Context, mgr manager.Manager) error { - if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1a2.UDPRoute{}, gatewayUDPRouteIndex, func(rawObj client.Object) []string { - udpRoute := rawObj.(*gwapiv1a2.UDPRoute) - var gateways []string - for _, parent := range udpRoute.Spec.ParentRefs { - if string(*parent.Kind) == gatewayapi.KindGateway { - // If an explicit Gateway namespace is not provided, use the UDPRoute namespace to - // lookup the provided Gateway Name. - gateways = append(gateways, - types.NamespacedName{ - Namespace: gatewayapi.NamespaceDerefOrAlpha(parent.Namespace, udpRoute.Namespace), - Name: string(parent.Name), - }.String(), - ) - } - } - return gateways - }); err != nil { - return err - } - - if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1a2.UDPRoute{}, backendUDPRouteIndex, backendUDPRouteIndexFunc); err != nil { - return err - } - return nil -} - -func backendUDPRouteIndexFunc(rawObj client.Object) []string { - udproute := rawObj.(*gwapiv1a2.UDPRoute) - var backendRefs []string - for _, rule := range udproute.Spec.Rules { - for _, backend := range rule.BackendRefs { - if backend.Kind == nil || string(*backend.Kind) == gatewayapi.KindService { - // If an explicit Backend namespace is not provided, use the UDPRoute namespace to - // lookup the provided Gateway Name. - backendRefs = append(backendRefs, - types.NamespacedName{ - Namespace: gatewayapi.NamespaceDerefOrAlpha(backend.Namespace, udproute.Namespace), - Name: string(backend.Name), - }.String(), - ) - } - } - } - return backendRefs -} - -// addGatewayIndexers adds indexing on Gateway, for Secret objects that are -// referenced in Gateway objects. This helps in querying for Gateways that are -// affected by a particular Secret CRUD. -func addGatewayIndexers(ctx context.Context, mgr manager.Manager) error { - if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1.Gateway{}, secretGatewayIndex, secretGatewayIndexFunc); err != nil { - return err - } - - if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1.Gateway{}, classGatewayIndex, func(rawObj client.Object) []string { - gateway := rawObj.(*gwapiv1.Gateway) - return []string{string(gateway.Spec.GatewayClassName)} - }); err != nil { - return err - } - return nil -} - -func secretGatewayIndexFunc(rawObj client.Object) []string { - gateway := rawObj.(*gwapiv1.Gateway) - var secretReferences []string - for _, listener := range gateway.Spec.Listeners { - if listener.TLS == nil || *listener.TLS.Mode != gwapiv1.TLSModeTerminate { - continue - } - for _, cert := range listener.TLS.CertificateRefs { - if *cert.Kind == gatewayapi.KindSecret { - // If an explicit Secret namespace is not provided, use the Gateway namespace to - // lookup the provided Secret Name. - secretReferences = append(secretReferences, - types.NamespacedName{ - Namespace: gatewayapi.NamespaceDerefOr(cert.Namespace, gateway.Namespace), - Name: string(cert.Name), - }.String(), - ) - } - } - } - return secretReferences -} - // removeFinalizer removes the gatewayclass finalizer from the provided gc, if it exists. func (r *gatewayAPIReconciler) removeFinalizer(ctx context.Context, gc *gwapiv1.GatewayClass) error { if slice.ContainsString(gc.Finalizers, gatewayClassFinalizer) { @@ -1036,303 +724,6 @@ func (r *gatewayAPIReconciler) addFinalizer(ctx context.Context, gc *gwapiv1.Gat return nil } -// subscribeAndUpdateStatus subscribes to gateway API object status updates and -// writes it into the Kubernetes API Server. -func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context) { - // Gateway object status updater - go func() { - message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "gateway-status"}, r.resources.GatewayStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *gwapiv1.GatewayStatus], errChan chan error) { - // skip delete updates. - if update.Delete { - return - } - // Get gateway object - gtw := new(gwapiv1.Gateway) - if err := r.client.Get(ctx, update.Key, gtw); err != nil { - r.log.Error(err, "gateway not found", "namespace", gtw.Namespace, "name", gtw.Name) - errChan <- err - return - } - // Set the updated Status and call the status update - gtw.Status = *update.Value - r.statusUpdateForGateway(ctx, gtw) - }, - ) - r.log.Info("gateway status subscriber shutting down") - }() - - // HTTPRoute object status updater - go func() { - message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "httproute-status"}, r.resources.HTTPRouteStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *gwapiv1.HTTPRouteStatus], errChan chan error) { - // skip delete updates. - if update.Delete { - return - } - key := update.Key - val := update.Value - r.statusUpdater.Send(status.Update{ - NamespacedName: key, - Resource: new(gwapiv1.HTTPRoute), - Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - h, ok := obj.(*gwapiv1.HTTPRoute) - if !ok { - err := fmt.Errorf("unsupported object type %T", obj) - errChan <- err - panic(err) - } - hCopy := h.DeepCopy() - hCopy.Status.Parents = val.Parents - return hCopy - }), - }) - }, - ) - r.log.Info("httpRoute status subscriber shutting down") - }() - - // GRPCRoute object status updater - go func() { - message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "grpcroute-status"}, r.resources.GRPCRouteStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *gwapiv1a2.GRPCRouteStatus], errChan chan error) { - // skip delete updates. - if update.Delete { - return - } - key := update.Key - val := update.Value - r.statusUpdater.Send(status.Update{ - NamespacedName: key, - Resource: new(gwapiv1a2.GRPCRoute), - Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - h, ok := obj.(*gwapiv1a2.GRPCRoute) - if !ok { - err := fmt.Errorf("unsupported object type %T", obj) - errChan <- err - panic(err) - } - hCopy := h.DeepCopy() - hCopy.Status.Parents = val.Parents - return hCopy - }), - }) - }, - ) - r.log.Info("grpcRoute status subscriber shutting down") - }() - - // TLSRoute object status updater - go func() { - message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "tlsroute-status"}, r.resources.TLSRouteStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *gwapiv1a2.TLSRouteStatus], errChan chan error) { - // skip delete updates. - if update.Delete { - return - } - key := update.Key - val := update.Value - r.statusUpdater.Send(status.Update{ - NamespacedName: key, - Resource: new(gwapiv1a2.TLSRoute), - Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - t, ok := obj.(*gwapiv1a2.TLSRoute) - if !ok { - err := fmt.Errorf("unsupported object type %T", obj) - errChan <- err - panic(err) - } - tCopy := t.DeepCopy() - tCopy.Status.Parents = val.Parents - return tCopy - }), - }) - }, - ) - r.log.Info("tlsRoute status subscriber shutting down") - }() - - // TCPRoute object status updater - go func() { - message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "tcproute-status"}, r.resources.TCPRouteStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *gwapiv1a2.TCPRouteStatus], errChan chan error) { - // skip delete updates. - if update.Delete { - return - } - key := update.Key - val := update.Value - r.statusUpdater.Send(status.Update{ - NamespacedName: key, - Resource: new(gwapiv1a2.TCPRoute), - Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - t, ok := obj.(*gwapiv1a2.TCPRoute) - if !ok { - err := fmt.Errorf("unsupported object type %T", obj) - errChan <- err - panic(err) - } - tCopy := t.DeepCopy() - tCopy.Status.Parents = val.Parents - return tCopy - }), - }) - }, - ) - r.log.Info("tcpRoute status subscriber shutting down") - }() - - // UDPRoute object status updater - go func() { - message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "udproute-status"}, r.resources.UDPRouteStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *gwapiv1a2.UDPRouteStatus], errChan chan error) { - // skip delete updates. - if update.Delete { - return - } - key := update.Key - val := update.Value - r.statusUpdater.Send(status.Update{ - NamespacedName: key, - Resource: new(gwapiv1a2.UDPRoute), - Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - t, ok := obj.(*gwapiv1a2.UDPRoute) - if !ok { - err := fmt.Errorf("unsupported object type %T", obj) - errChan <- err - panic(err) - } - tCopy := t.DeepCopy() - tCopy.Status.Parents = val.Parents - return tCopy - }), - }) - }, - ) - r.log.Info("udpRoute status subscriber shutting down") - }() - - // EnvoyPatchPolicy object status updater - go func() { - message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "envoypatchpolicy-status"}, r.resources.EnvoyPatchPolicyStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *v1alpha1.EnvoyPatchPolicyStatus], errChan chan error) { - // skip delete updates. - if update.Delete { - return - } - key := update.Key - val := update.Value - r.statusUpdater.Send(status.Update{ - NamespacedName: key, - Resource: new(v1alpha1.EnvoyPatchPolicy), - Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - t, ok := obj.(*v1alpha1.EnvoyPatchPolicy) - if !ok { - err := fmt.Errorf("unsupported object type %T", obj) - errChan <- err - panic(err) - } - tCopy := t.DeepCopy() - tCopy.Status = *val - return tCopy - }), - }) - }, - ) - r.log.Info("envoyPatchPolicy status subscriber shutting down") - }() - - // ClientTrafficPolicy object status updater - go func() { - message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "clienttrafficpolicy-status"}, r.resources.ClientTrafficPolicyStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *v1alpha1.ClientTrafficPolicyStatus], errChan chan error) { - // skip delete updates. - if update.Delete { - return - } - key := update.Key - val := update.Value - r.statusUpdater.Send(status.Update{ - NamespacedName: key, - Resource: new(v1alpha1.ClientTrafficPolicy), - Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - t, ok := obj.(*v1alpha1.ClientTrafficPolicy) - if !ok { - err := fmt.Errorf("unsupported object type %T", obj) - errChan <- err - panic(err) - } - tCopy := t.DeepCopy() - tCopy.Status = *val - return tCopy - }), - }) - }, - ) - r.log.Info("clientTrafficPolicy status subscriber shutting down") - }() - - // BackendTrafficPolicy object status updater - go func() { - message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "backendtrafficpolicy-status"}, r.resources.BackendTrafficPolicyStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *v1alpha1.BackendTrafficPolicyStatus], errChan chan error) { - // skip delete updates. - if update.Delete { - return - } - key := update.Key - val := update.Value - r.statusUpdater.Send(status.Update{ - NamespacedName: key, - Resource: new(v1alpha1.BackendTrafficPolicy), - Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - t, ok := obj.(*v1alpha1.BackendTrafficPolicy) - if !ok { - err := fmt.Errorf("unsupported object type %T", obj) - errChan <- err - panic(err) - } - tCopy := t.DeepCopy() - tCopy.Status = *val - return tCopy - }), - }) - }, - ) - r.log.Info("backendTrafficPolicy status subscriber shutting down") - }() - - // SecurityPolicy object status updater - go func() { - message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "securitypolicy-status"}, r.resources.SecurityPolicyStatuses.Subscribe(ctx), - func(update message.Update[types.NamespacedName, *v1alpha1.SecurityPolicyStatus], errChan chan error) { - // skip delete updates. - if update.Delete { - return - } - key := update.Key - val := update.Value - r.statusUpdater.Send(status.Update{ - NamespacedName: key, - Resource: new(v1alpha1.SecurityPolicy), - Mutator: status.MutatorFunc(func(obj client.Object) client.Object { - t, ok := obj.(*v1alpha1.SecurityPolicy) - if !ok { - err := fmt.Errorf("unsupported object type %T", obj) - errChan <- err - panic(err) - } - tCopy := t.DeepCopy() - tCopy.Status = *val - return tCopy - }), - }) - }, - ) - r.log.Info("securityPolicy status subscriber shutting down") - }() -} - // watchResources watches gateway api resources. func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.Manager, c controller.Controller) error { if err := c.Watch( @@ -1350,11 +741,11 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M predicate.ResourceVersionChangedPredicate{}, predicate.NewPredicateFuncs(r.hasManagedClass), } - if len(r.namespaceLabels) != 0 { + if r.namespaceLabel != nil { epPredicates = append(epPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) } if err := c.Watch( - source.Kind(mgr.GetCache(), &v1alpha1.EnvoyProxy{}), + source.Kind(mgr.GetCache(), &egv1a1.EnvoyProxy{}), handler.EnqueueRequestsFromMapFunc(r.enqueueClass), epPredicates..., ); err != nil { @@ -1366,7 +757,7 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M predicate.GenerationChangedPredicate{}, predicate.NewPredicateFuncs(r.validateGatewayForReconcile), } - if len(r.namespaceLabels) != 0 { + if r.namespaceLabel != nil { gPredicates = append(gPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) } if err := c.Watch( @@ -1382,7 +773,7 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M // Watch HTTPRoute CRUDs and process affected Gateways. httprPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} - if len(r.namespaceLabels) != 0 { + if r.namespaceLabel != nil { httprPredicates = append(httprPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) } if err := c.Watch( @@ -1398,7 +789,7 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M // Watch GRPCRoute CRUDs and process affected Gateways. grpcrPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} - if len(r.namespaceLabels) != 0 { + if r.namespaceLabel != nil { grpcrPredicates = append(grpcrPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) } if err := c.Watch( @@ -1414,7 +805,7 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M // Watch TLSRoute CRUDs and process affected Gateways. tlsrPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} - if len(r.namespaceLabels) != 0 { + if r.namespaceLabel != nil { tlsrPredicates = append(tlsrPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) } if err := c.Watch( @@ -1430,7 +821,7 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M // Watch UDPRoute CRUDs and process affected Gateways. udprPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} - if len(r.namespaceLabels) != 0 { + if r.namespaceLabel != nil { udprPredicates = append(udprPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) } if err := c.Watch( @@ -1446,7 +837,7 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M // Watch TCPRoute CRUDs and process affected Gateways. tcprPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} - if len(r.namespaceLabels) != 0 { + if r.namespaceLabel != nil { tcprPredicates = append(tcprPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) } if err := c.Watch( @@ -1462,7 +853,7 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M // Watch Service CRUDs and process affected *Route objects. servicePredicates := []predicate.Predicate{predicate.NewPredicateFuncs(r.validateServiceForReconcile)} - if len(r.namespaceLabels) != 0 { + if r.namespaceLabel != nil { servicePredicates = append(servicePredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) } if err := c.Watch( @@ -1495,7 +886,7 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M predicate.GenerationChangedPredicate{}, predicate.NewPredicateFuncs(r.validateEndpointSliceForReconcile), } - if len(r.namespaceLabels) != 0 { + if r.namespaceLabel != nil { esPredicates = append(esPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) } if err := c.Watch( @@ -1512,7 +903,7 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M predicate.GenerationChangedPredicate{}, predicate.NewPredicateFuncs(r.handleNode), } - if len(r.namespaceLabels) != 0 { + if r.namespaceLabel != nil { nPredicates = append(nPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) } // resource address. @@ -1524,12 +915,12 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M return err } - // Watch Secret CRUDs and process affected Gateways. + // Watch Secret CRUDs and process affected EG CRs (Gateway, SecurityPolicy, more in the future). secretPredicates := []predicate.Predicate{ predicate.GenerationChangedPredicate{}, predicate.NewPredicateFuncs(r.validateSecretForReconcile), } - if len(r.namespaceLabels) != 0 { + if r.namespaceLabel != nil { secretPredicates = append(secretPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) } if err := c.Watch( @@ -1540,9 +931,25 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M return err } + // Watch ConfigMap CRUDs and process affected ClienTraffiPolicies. + configMapPredicates := []predicate.Predicate{ + predicate.GenerationChangedPredicate{}, + predicate.NewPredicateFuncs(r.validateConfigMapForReconcile), + } + if r.namespaceLabel != nil { + configMapPredicates = append(configMapPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) + } + if err := c.Watch( + source.Kind(mgr.GetCache(), &corev1.ConfigMap{}), + handler.EnqueueRequestsFromMapFunc(r.enqueueClass), + configMapPredicates..., + ); err != nil { + return err + } + // Watch ReferenceGrant CRUDs and process affected Gateways. rgPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} - if len(r.namespaceLabels) != 0 { + if r.namespaceLabel != nil { rgPredicates = append(rgPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) } if err := c.Watch( @@ -1558,7 +965,7 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M // Watch Deployment CRUDs and process affected Gateways. dPredicates := []predicate.Predicate{predicate.NewPredicateFuncs(r.validateDeploymentForReconcile)} - if len(r.namespaceLabels) != 0 { + if r.namespaceLabel != nil { dPredicates = append(dPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) } if err := c.Watch( @@ -1571,13 +978,13 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M // Watch EnvoyPatchPolicy if enabled in config eppPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} - if len(r.namespaceLabels) != 0 { + if r.namespaceLabel != nil { eppPredicates = append(eppPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) } if r.envoyGateway.ExtensionAPIs != nil && r.envoyGateway.ExtensionAPIs.EnableEnvoyPatchPolicy { // Watch EnvoyPatchPolicy CRUDs if err := c.Watch( - source.Kind(mgr.GetCache(), &v1alpha1.EnvoyPatchPolicy{}), + source.Kind(mgr.GetCache(), &egv1a1.EnvoyPatchPolicy{}), handler.EnqueueRequestsFromMapFunc(r.enqueueClass), eppPredicates..., ); err != nil { @@ -1587,26 +994,30 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M // Watch ClientTrafficPolicy ctpPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} - if len(r.namespaceLabels) != 0 { + if r.namespaceLabel != nil { ctpPredicates = append(ctpPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) } if err := c.Watch( - source.Kind(mgr.GetCache(), &v1alpha1.ClientTrafficPolicy{}), + source.Kind(mgr.GetCache(), &egv1a1.ClientTrafficPolicy{}), handler.EnqueueRequestsFromMapFunc(r.enqueueClass), ctpPredicates..., ); err != nil { return err } + if err := addCtpIndexers(ctx, mgr); err != nil { + return err + } + // Watch BackendTrafficPolicy btpPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} - if len(r.namespaceLabels) != 0 { + if r.namespaceLabel != nil { btpPredicates = append(btpPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) } if err := c.Watch( - source.Kind(mgr.GetCache(), &v1alpha1.BackendTrafficPolicy{}), + source.Kind(mgr.GetCache(), &egv1a1.BackendTrafficPolicy{}), handler.EnqueueRequestsFromMapFunc(r.enqueueClass), btpPredicates..., ); err != nil { @@ -1615,23 +1026,26 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M // Watch SecurityPolicy spPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} - if len(r.namespaceLabels) != 0 { + if r.namespaceLabel != nil { spPredicates = append(spPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) } if err := c.Watch( - source.Kind(mgr.GetCache(), &v1alpha1.SecurityPolicy{}), + source.Kind(mgr.GetCache(), &egv1a1.SecurityPolicy{}), handler.EnqueueRequestsFromMapFunc(r.enqueueClass), spPredicates..., ); err != nil { return err } + if err := addSecurityPolicyIndexers(ctx, mgr); err != nil { + return err + } r.log.Info("Watching gatewayAPI related objects") // Watch any additional GVKs from the registered extension. uPredicates := []predicate.Predicate{predicate.GenerationChangedPredicate{}} - if len(r.namespaceLabels) != 0 { + if r.namespaceLabel != nil { uPredicates = append(uPredicates, predicate.NewPredicateFuncs(r.hasMatchingNamespaceLabels)) } for _, gvk := range r.extGVKs { @@ -1655,7 +1069,7 @@ func (r *gatewayAPIReconciler) enqueueClass(_ context.Context, _ client.Object) } func (r *gatewayAPIReconciler) hasManagedClass(obj client.Object) bool { - ep, ok := obj.(*v1alpha1.EnvoyProxy) + ep, ok := obj.(*egv1a1.EnvoyProxy) if !ok { panic(fmt.Sprintf("unsupported object type %T", obj)) } @@ -1693,7 +1107,7 @@ func (r *gatewayAPIReconciler) processParamsRef(ctx context.Context, gc *gwapiv1 return fmt.Errorf("unsupported parametersRef for gatewayclass %s", gc.Name) } - epList := new(v1alpha1.EnvoyProxyList) + epList := new(egv1a1.EnvoyProxyList) // The EnvoyProxy must be in the same namespace as EG. if err := r.client.List(ctx, epList, &client.ListOptions{Namespace: r.namespace}); err != nil { diff --git a/internal/provider/kubernetes/filters.go b/internal/provider/kubernetes/filters.go index caa3cb1018d..8ef8dc1ede1 100644 --- a/internal/provider/kubernetes/filters.go +++ b/internal/provider/kubernetes/filters.go @@ -23,14 +23,14 @@ func (r *gatewayAPIReconciler) getExtensionRefFilters(ctx context.Context) ([]un } uExtResources := uExtResourceList.Items - if len(r.namespaceLabels) != 0 { + if r.namespaceLabel != nil { var extRs []unstructured.Unstructured for _, extR := range uExtResources { - ns := extR.GetNamespace() - ok, err := r.checkObjectNamespaceLabels(ns) + extR := extR + ok, err := r.checkObjectNamespaceLabels(&extR) if err != nil { - // TODO: should return? or just proceed? - return nil, fmt.Errorf("failed to check namespace labels for ExtensionRefFilter %s in namespace %s: %w", extR.GetName(), ns, err) + r.log.Error(err, "failed to check namespace labels for ExtensionRefFilter %s in namespace %s: %w", extR.GetName(), extR.GetNamespace()) + continue } if ok { extRs = append(extRs, extR) diff --git a/internal/provider/kubernetes/helpers.go b/internal/provider/kubernetes/helpers.go index d8d6a74b29f..00029f1cb92 100644 --- a/internal/provider/kubernetes/helpers.go +++ b/internal/provider/kubernetes/helpers.go @@ -80,25 +80,10 @@ func validateParentRefs(ctx context.Context, client client.Client, namespace str type controlledClasses struct { // matchedClasses holds all GatewayClass objects with matching controllerName. matchedClasses []*gwapiv1.GatewayClass - - // oldestClass stores the first GatewayClass encountered with matching - // controllerName. This is maintained so that the oldestClass does not change - // during reboots. - oldestClass *gwapiv1.GatewayClass } func (cc *controlledClasses) addMatch(gc *gwapiv1.GatewayClass) { cc.matchedClasses = append(cc.matchedClasses, gc) - - switch { - case cc.oldestClass == nil: - cc.oldestClass = gc - case gc.CreationTimestamp.Time.Before(cc.oldestClass.CreationTimestamp.Time): - cc.oldestClass = gc - case gc.CreationTimestamp.Time.Equal(cc.oldestClass.CreationTimestamp.Time) && gc.Name < cc.oldestClass.Name: - // tie-breaker: first one in alphabetical order is considered oldest/accepted - cc.oldestClass = gc - } } func (cc *controlledClasses) removeMatch(gc *gwapiv1.GatewayClass) { @@ -110,42 +95,6 @@ func (cc *controlledClasses) removeMatch(gc *gwapiv1.GatewayClass) { break } } - - // If the oldestClass is removed, find the new oldestClass candidate - // from matchedClasses. - if cc.oldestClass != nil && cc.oldestClass.Name == gc.Name { - if len(cc.matchedClasses) == 0 { - cc.oldestClass = nil - return - } - - cc.oldestClass = cc.matchedClasses[0] - for i := 1; i < len(cc.matchedClasses); i++ { - current := cc.matchedClasses[i] - if current.CreationTimestamp.Time.Before(cc.oldestClass.CreationTimestamp.Time) || - (current.CreationTimestamp.Time.Equal(cc.oldestClass.CreationTimestamp.Time) && - current.Name < cc.oldestClass.Name) { - cc.oldestClass = current - return - } - } - } -} - -func (cc *controlledClasses) acceptedClass() *gwapiv1.GatewayClass { - return cc.oldestClass -} - -func (cc *controlledClasses) notAcceptedClasses() []*gwapiv1.GatewayClass { - var res []*gwapiv1.GatewayClass - for _, gc := range cc.matchedClasses { - // skip the oldest one since it will be accepted. - if gc.Name != cc.oldestClass.Name { - res = append(res, gc) - } - } - - return res } // isAccepted returns true if the provided gatewayclass contains the Accepted=true diff --git a/internal/provider/kubernetes/helpers_test.go b/internal/provider/kubernetes/helpers_test.go index 1d88c38f0e2..0d5deb0d5d3 100644 --- a/internal/provider/kubernetes/helpers_test.go +++ b/internal/provider/kubernetes/helpers_test.go @@ -7,7 +7,6 @@ package kubernetes import ( "testing" - "time" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -108,7 +107,7 @@ func TestGatewaysOfClass(t *testing.T) { t.Run(tc.name, func(t *testing.T) { gwList := &gwapiv1.GatewayList{Items: tc.gws} actual := gatewaysOfClass(gc, gwList) - require.Equal(t, tc.expect, len(actual)) + require.Len(t, actual, tc.expect) }) } } @@ -194,100 +193,6 @@ func TestIsGatewayClassAccepted(t *testing.T) { } } -func TestGatewayOldestClass(t *testing.T) { - createGatewayClass := func(name string, creationTime time.Time) *gwapiv1.GatewayClass { - return &gwapiv1.GatewayClass{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - CreationTimestamp: metav1.NewTime(creationTime), - }, - Spec: gwapiv1.GatewayClassSpec{ - ControllerName: egv1a1.GatewayControllerName, - }, - } - } - - currentTime := metav1.Now() - addDuration := time.Duration(10) - testCases := []struct { - name string - classes map[string]time.Time - remove map[string]time.Time - oldest string - }{ - { - name: "normal", - classes: map[string]time.Time{ - "class-b": currentTime.Time, - "class-a": currentTime.Add(1 * addDuration), - }, - remove: nil, - oldest: "class-b", - }, - { - name: "tie breaker", - classes: map[string]time.Time{ - "class-aa": currentTime.Time, - "class-ab": currentTime.Time, - }, - remove: nil, - oldest: "class-aa", - }, - { - name: "remove from matched", - classes: map[string]time.Time{ - "class-a": currentTime.Time, - "class-b": currentTime.Add(1 * addDuration), - "class-c": currentTime.Add(2 * addDuration), - }, - remove: map[string]time.Time{ - "class-b": currentTime.Add(1 * addDuration), - }, - oldest: "class-a", - }, - { - name: "remove oldest", - classes: map[string]time.Time{ - "class-a": currentTime.Time, - "class-b": currentTime.Add(1 * addDuration), - "class-c": currentTime.Add(2 * addDuration), - }, - remove: map[string]time.Time{ - "class-a": currentTime.Time, - }, - oldest: "class-b", - }, - { - name: "remove oldest last", - classes: map[string]time.Time{ - "class-a": currentTime.Time, - }, - remove: map[string]time.Time{ - "class-a": currentTime.Time, - }, - oldest: "", - }, - } - - for _, tc := range testCases { - var cc controlledClasses - for name, timestamp := range tc.classes { - cc.addMatch(createGatewayClass(name, timestamp)) - } - - for name, timestamp := range tc.remove { - cc.removeMatch(createGatewayClass(name, timestamp)) - } - - if tc.oldest == "" { - require.Nil(t, cc.oldestClass) - return - } - - require.Equal(t, tc.oldest, cc.oldestClass.Name) - } -} - func TestRefsEnvoyProxy(t *testing.T) { testCases := []struct { name string diff --git a/internal/provider/kubernetes/indexers.go b/internal/provider/kubernetes/indexers.go new file mode 100644 index 00000000000..f4daed5960e --- /dev/null +++ b/internal/provider/kubernetes/indexers.go @@ -0,0 +1,483 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package kubernetes + +import ( + "context" + + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/manager" + gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" + gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + gwapiv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" + + "github.com/envoyproxy/gateway/api/v1alpha1" + "github.com/envoyproxy/gateway/internal/gatewayapi" +) + +const ( + classGatewayIndex = "classGatewayIndex" + gatewayTLSRouteIndex = "gatewayTLSRouteIndex" + gatewayHTTPRouteIndex = "gatewayHTTPRouteIndex" + gatewayGRPCRouteIndex = "gatewayGRPCRouteIndex" + gatewayTCPRouteIndex = "gatewayTCPRouteIndex" + gatewayUDPRouteIndex = "gatewayUDPRouteIndex" + secretGatewayIndex = "secretGatewayIndex" + targetRefGrantRouteIndex = "targetRefGrantRouteIndex" + backendHTTPRouteIndex = "backendHTTPRouteIndex" + backendGRPCRouteIndex = "backendGRPCRouteIndex" + backendTLSRouteIndex = "backendTLSRouteIndex" + backendTCPRouteIndex = "backendTCPRouteIndex" + backendUDPRouteIndex = "backendUDPRouteIndex" + secretSecurityPolicyIndex = "secretSecurityPolicyIndex" + backendSecurityPolicyIndex = "backendSecurityPolicyIndex" + configMapCtpIndex = "configMapCtpIndex" + secretCtpIndex = "secretCtpIndex" +) + +func addReferenceGrantIndexers(ctx context.Context, mgr manager.Manager) error { + if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1b1.ReferenceGrant{}, targetRefGrantRouteIndex, func(rawObj client.Object) []string { + refGrant := rawObj.(*gwapiv1b1.ReferenceGrant) + var referredServices []string + for _, target := range refGrant.Spec.To { + referredServices = append(referredServices, string(target.Kind)) + } + return referredServices + }); err != nil { + return err + } + return nil +} + +// addHTTPRouteIndexers adds indexing on HTTPRoute. +// - For Service, ServiceImports objects that are referenced in HTTPRoute objects via `.spec.rules.backendRefs`. +// This helps in querying for HTTPRoutes that are affected by a particular Service CRUD. +func addHTTPRouteIndexers(ctx context.Context, mgr manager.Manager) error { + if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1.HTTPRoute{}, gatewayHTTPRouteIndex, gatewayHTTPRouteIndexFunc); err != nil { + return err + } + + if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1.HTTPRoute{}, backendHTTPRouteIndex, backendHTTPRouteIndexFunc); err != nil { + return err + } + + return nil +} + +func gatewayHTTPRouteIndexFunc(rawObj client.Object) []string { + httproute := rawObj.(*gwapiv1.HTTPRoute) + var gateways []string + for _, parent := range httproute.Spec.ParentRefs { + if parent.Kind == nil || string(*parent.Kind) == gatewayapi.KindGateway { + // If an explicit Gateway namespace is not provided, use the HTTPRoute namespace to + // lookup the provided Gateway Name. + gateways = append(gateways, + types.NamespacedName{ + Namespace: gatewayapi.NamespaceDerefOr(parent.Namespace, httproute.Namespace), + Name: string(parent.Name), + }.String(), + ) + } + } + return gateways +} + +func backendHTTPRouteIndexFunc(rawObj client.Object) []string { + httproute := rawObj.(*gwapiv1.HTTPRoute) + var backendRefs []string + for _, rule := range httproute.Spec.Rules { + for _, backend := range rule.BackendRefs { + if backend.Kind == nil || string(*backend.Kind) == gatewayapi.KindService { + // If an explicit Backend namespace is not provided, use the HTTPRoute namespace to + // lookup the provided Gateway Name. + backendRefs = append(backendRefs, + types.NamespacedName{ + Namespace: gatewayapi.NamespaceDerefOr(backend.Namespace, httproute.Namespace), + Name: string(backend.Name), + }.String(), + ) + } + } + } + return backendRefs +} + +// addGRPCRouteIndexers adds indexing on GRPCRoute, for Service objects that are +// referenced in GRPCRoute objects via `.spec.rules.backendRefs`. This helps in +// querying for GRPCRoutes that are affected by a particular Service CRUD. +func addGRPCRouteIndexers(ctx context.Context, mgr manager.Manager) error { + if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1a2.GRPCRoute{}, gatewayGRPCRouteIndex, gatewayGRPCRouteIndexFunc); err != nil { + return err + } + + if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1a2.GRPCRoute{}, backendGRPCRouteIndex, backendGRPCRouteIndexFunc); err != nil { + return err + } + + return nil +} + +func gatewayGRPCRouteIndexFunc(rawObj client.Object) []string { + grpcroute := rawObj.(*gwapiv1a2.GRPCRoute) + var gateways []string + for _, parent := range grpcroute.Spec.ParentRefs { + if parent.Kind == nil || string(*parent.Kind) == gatewayapi.KindGateway { + // If an explicit Gateway namespace is not provided, use the GRPCRoute namespace to + // lookup the provided Gateway Name. + gateways = append(gateways, + types.NamespacedName{ + Namespace: gatewayapi.NamespaceDerefOr(parent.Namespace, grpcroute.Namespace), + Name: string(parent.Name), + }.String(), + ) + } + } + return gateways +} + +func backendGRPCRouteIndexFunc(rawObj client.Object) []string { + grpcroute := rawObj.(*gwapiv1a2.GRPCRoute) + var backendRefs []string + for _, rule := range grpcroute.Spec.Rules { + for _, backend := range rule.BackendRefs { + if backend.Kind == nil || string(*backend.Kind) == gatewayapi.KindService { + // If an explicit Backend namespace is not provided, use the GRPCRoute namespace to + // lookup the provided Gateway Name. + backendRefs = append(backendRefs, + types.NamespacedName{ + Namespace: gatewayapi.NamespaceDerefOr(backend.Namespace, grpcroute.Namespace), + Name: string(backend.Name), + }.String(), + ) + } + } + } + return backendRefs +} + +// addTLSRouteIndexers adds indexing on TLSRoute, for Service objects that are +// referenced in TLSRoute objects via `.spec.rules.backendRefs`. This helps in +// querying for TLSRoutes that are affected by a particular Service CRUD. +func addTLSRouteIndexers(ctx context.Context, mgr manager.Manager) error { + if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1a2.TLSRoute{}, gatewayTLSRouteIndex, func(rawObj client.Object) []string { + tlsRoute := rawObj.(*gwapiv1a2.TLSRoute) + var gateways []string + for _, parent := range tlsRoute.Spec.ParentRefs { + if string(*parent.Kind) == gatewayapi.KindGateway { + // If an explicit Gateway namespace is not provided, use the TLSRoute namespace to + // lookup the provided Gateway Name. + gateways = append(gateways, + types.NamespacedName{ + Namespace: gatewayapi.NamespaceDerefOrAlpha(parent.Namespace, tlsRoute.Namespace), + Name: string(parent.Name), + }.String(), + ) + } + } + return gateways + }); err != nil { + return err + } + + if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1a2.TLSRoute{}, backendTLSRouteIndex, backendTLSRouteIndexFunc); err != nil { + return err + } + return nil +} + +func backendTLSRouteIndexFunc(rawObj client.Object) []string { + tlsroute := rawObj.(*gwapiv1a2.TLSRoute) + var backendRefs []string + for _, rule := range tlsroute.Spec.Rules { + for _, backend := range rule.BackendRefs { + if backend.Kind == nil || string(*backend.Kind) == gatewayapi.KindService { + // If an explicit Backend namespace is not provided, use the TLSRoute namespace to + // lookup the provided Gateway Name. + backendRefs = append(backendRefs, + types.NamespacedName{ + Namespace: gatewayapi.NamespaceDerefOrAlpha(backend.Namespace, tlsroute.Namespace), + Name: string(backend.Name), + }.String(), + ) + } + } + } + return backendRefs +} + +// addTCPRouteIndexers adds indexing on TCPRoute, for Service objects that are +// referenced in TCPRoute objects via `.spec.rules.backendRefs`. This helps in +// querying for TCPRoutes that are affected by a particular Service CRUD. +func addTCPRouteIndexers(ctx context.Context, mgr manager.Manager) error { + if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1a2.TCPRoute{}, gatewayTCPRouteIndex, func(rawObj client.Object) []string { + tcpRoute := rawObj.(*gwapiv1a2.TCPRoute) + var gateways []string + for _, parent := range tcpRoute.Spec.ParentRefs { + if string(*parent.Kind) == gatewayapi.KindGateway { + // If an explicit Gateway namespace is not provided, use the TCPRoute namespace to + // lookup the provided Gateway Name. + gateways = append(gateways, + types.NamespacedName{ + Namespace: gatewayapi.NamespaceDerefOrAlpha(parent.Namespace, tcpRoute.Namespace), + Name: string(parent.Name), + }.String(), + ) + } + } + return gateways + }); err != nil { + return err + } + + if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1a2.TCPRoute{}, backendTCPRouteIndex, backendTCPRouteIndexFunc); err != nil { + return err + } + return nil +} + +func backendTCPRouteIndexFunc(rawObj client.Object) []string { + tcpRoute := rawObj.(*gwapiv1a2.TCPRoute) + var backendRefs []string + for _, rule := range tcpRoute.Spec.Rules { + for _, backend := range rule.BackendRefs { + if backend.Kind == nil || string(*backend.Kind) == gatewayapi.KindService { + // If an explicit Backend namespace is not provided, use the TCPRoute namespace to + // lookup the provided Gateway Name. + backendRefs = append(backendRefs, + types.NamespacedName{ + Namespace: gatewayapi.NamespaceDerefOrAlpha(backend.Namespace, tcpRoute.Namespace), + Name: string(backend.Name), + }.String(), + ) + } + } + } + return backendRefs +} + +// addUDPRouteIndexers adds indexing on UDPRoute. +// - For Gateway objects that are referenced in UDPRoute objects via `.spec.parentRefs`. This helps in +// querying for UDPRoutes that are affected by a particular Gateway CRUD. +// - For Service objects that are referenced in UDPRoute objects via `.spec.rules.backendRefs`. This helps in +// querying for UDPRoutes that are affected by a particular Service CRUD. +func addUDPRouteIndexers(ctx context.Context, mgr manager.Manager) error { + if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1a2.UDPRoute{}, gatewayUDPRouteIndex, func(rawObj client.Object) []string { + udpRoute := rawObj.(*gwapiv1a2.UDPRoute) + var gateways []string + for _, parent := range udpRoute.Spec.ParentRefs { + if string(*parent.Kind) == gatewayapi.KindGateway { + // If an explicit Gateway namespace is not provided, use the UDPRoute namespace to + // lookup the provided Gateway Name. + gateways = append(gateways, + types.NamespacedName{ + Namespace: gatewayapi.NamespaceDerefOrAlpha(parent.Namespace, udpRoute.Namespace), + Name: string(parent.Name), + }.String(), + ) + } + } + return gateways + }); err != nil { + return err + } + + if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1a2.UDPRoute{}, backendUDPRouteIndex, backendUDPRouteIndexFunc); err != nil { + return err + } + return nil +} + +func backendUDPRouteIndexFunc(rawObj client.Object) []string { + udproute := rawObj.(*gwapiv1a2.UDPRoute) + var backendRefs []string + for _, rule := range udproute.Spec.Rules { + for _, backend := range rule.BackendRefs { + if backend.Kind == nil || string(*backend.Kind) == gatewayapi.KindService { + // If an explicit Backend namespace is not provided, use the UDPRoute namespace to + // lookup the provided Gateway Name. + backendRefs = append(backendRefs, + types.NamespacedName{ + Namespace: gatewayapi.NamespaceDerefOrAlpha(backend.Namespace, udproute.Namespace), + Name: string(backend.Name), + }.String(), + ) + } + } + } + return backendRefs +} + +// addGatewayIndexers adds indexing on Gateway, for Secret objects that are +// referenced in Gateway objects. This helps in querying for Gateways that are +// affected by a particular Secret CRUD. +func addGatewayIndexers(ctx context.Context, mgr manager.Manager) error { + if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1.Gateway{}, secretGatewayIndex, secretGatewayIndexFunc); err != nil { + return err + } + + if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1.Gateway{}, classGatewayIndex, func(rawObj client.Object) []string { + gateway := rawObj.(*gwapiv1.Gateway) + return []string{string(gateway.Spec.GatewayClassName)} + }); err != nil { + return err + } + return nil +} + +func secretGatewayIndexFunc(rawObj client.Object) []string { + gateway := rawObj.(*gwapiv1.Gateway) + var secretReferences []string + for _, listener := range gateway.Spec.Listeners { + if listener.TLS == nil || *listener.TLS.Mode != gwapiv1.TLSModeTerminate { + continue + } + for _, cert := range listener.TLS.CertificateRefs { + if *cert.Kind == gatewayapi.KindSecret { + // If an explicit Secret namespace is not provided, use the Gateway namespace to + // lookup the provided Secret Name. + secretReferences = append(secretReferences, + types.NamespacedName{ + Namespace: gatewayapi.NamespaceDerefOr(cert.Namespace, gateway.Namespace), + Name: string(cert.Name), + }.String(), + ) + } + } + } + return secretReferences +} + +// addSecurityPolicyIndexers adds indexing on SecurityPolicy. +// - For Secret objects that are referenced in SecurityPolicy objects via +// `.spec.OIDC.clientSecret` and `.spec.basicAuth.users`. This helps in +// querying for SecurityPolicies that are affected by a particular Secret CRUD. +// - For Service objects that are referenced in SecurityPolicy objects via +// `.spec.extAuth.http.backendObjectReference`. This helps in querying for +// SecurityPolicies that are affected by a particular Service CRUD. +func addSecurityPolicyIndexers(ctx context.Context, mgr manager.Manager) error { + var err error + + if err = mgr.GetFieldIndexer().IndexField( + ctx, &v1alpha1.SecurityPolicy{}, secretSecurityPolicyIndex, + secretSecurityPolicyIndexFunc); err != nil { + return err + } + + if err = mgr.GetFieldIndexer().IndexField( + ctx, &v1alpha1.SecurityPolicy{}, backendSecurityPolicyIndex, + backendSecurityPolicyIndexFunc); err != nil { + return err + } + + return nil +} + +func secretSecurityPolicyIndexFunc(rawObj client.Object) []string { + securityPolicy := rawObj.(*v1alpha1.SecurityPolicy) + + var ( + secretReferences []gwapiv1b1.SecretObjectReference + values []string + ) + + if securityPolicy.Spec.OIDC != nil { + secretReferences = append(secretReferences, securityPolicy.Spec.OIDC.ClientSecret) + } + if securityPolicy.Spec.BasicAuth != nil { + secretReferences = append(secretReferences, securityPolicy.Spec.BasicAuth.Users) + } + + for _, reference := range secretReferences { + values = append(values, + types.NamespacedName{ + Namespace: gatewayapi.NamespaceDerefOr(reference.Namespace, securityPolicy.Namespace), + Name: string(reference.Name), + }.String(), + ) + } + return values +} + +func backendSecurityPolicyIndexFunc(rawObj client.Object) []string { + securityPolicy := rawObj.(*v1alpha1.SecurityPolicy) + + var backendRef *gwapiv1.BackendObjectReference + + if securityPolicy.Spec.ExtAuth != nil { + if securityPolicy.Spec.ExtAuth.HTTP != nil { + backendRef = &securityPolicy.Spec.ExtAuth.HTTP.BackendRef + } else if securityPolicy.Spec.ExtAuth.GRPC != nil { + backendRef = &securityPolicy.Spec.ExtAuth.GRPC.BackendRef + } + } + + if backendRef != nil { + return []string{ + types.NamespacedName{ + Namespace: gatewayapi.NamespaceDerefOr(backendRef.Namespace, securityPolicy.Namespace), + Name: string(backendRef.Name), + }.String(), + } + } + + // This should not happen because the CEL validation should catch it. + return []string{} +} + +// addCtpIndexers adds indexing on ClientTrafficPolicy, for ConfigMap or Secret objects that are +// referenced in ClientTrafficPolicy objects. This helps in querying for ClientTrafficPolicies that are +// affected by a particular ConfigMap or Secret CRUD. +func addCtpIndexers(ctx context.Context, mgr manager.Manager) error { + if err := mgr.GetFieldIndexer().IndexField(ctx, &v1alpha1.ClientTrafficPolicy{}, configMapCtpIndex, configMapCtpIndexFunc); err != nil { + return err + } + if err := mgr.GetFieldIndexer().IndexField(ctx, &v1alpha1.ClientTrafficPolicy{}, secretCtpIndex, secretCtpIndexFunc); err != nil { + return err + } + + return nil +} + +func configMapCtpIndexFunc(rawObj client.Object) []string { + ctp := rawObj.(*v1alpha1.ClientTrafficPolicy) + var configMapReferences []string + if ctp.Spec.TLS != nil && ctp.Spec.TLS.ClientValidation != nil { + for _, caCertRef := range ctp.Spec.TLS.ClientValidation.CACertificateRefs { + if caCertRef.Kind != nil && string(*caCertRef.Kind) == gatewayapi.KindConfigMap { + // If an explicit configmap namespace is not provided, use the ctp namespace to + // lookup the provided config map Name. + configMapReferences = append(configMapReferences, + types.NamespacedName{ + Namespace: gatewayapi.NamespaceDerefOr(caCertRef.Namespace, ctp.Namespace), + Name: string(caCertRef.Name), + }.String(), + ) + } + } + } + return configMapReferences +} + +func secretCtpIndexFunc(rawObj client.Object) []string { + ctp := rawObj.(*v1alpha1.ClientTrafficPolicy) + var secretReferences []string + if ctp.Spec.TLS != nil && ctp.Spec.TLS.ClientValidation != nil { + for _, caCertRef := range ctp.Spec.TLS.ClientValidation.CACertificateRefs { + if caCertRef.Kind == nil || (string(*caCertRef.Kind) == gatewayapi.KindSecret) { + // If an explicit namespace is not provided, use the ctp namespace to + // lookup the provided secrent Name. + secretReferences = append(secretReferences, + types.NamespacedName{ + Namespace: gatewayapi.NamespaceDerefOr(caCertRef.Namespace, ctp.Namespace), + Name: string(caCertRef.Name), + }.String(), + ) + } + } + } + return secretReferences +} diff --git a/internal/provider/kubernetes/kubernetes.go b/internal/provider/kubernetes/kubernetes.go index e84b9d442ff..3a4bfb7c793 100644 --- a/internal/provider/kubernetes/kubernetes.go +++ b/internal/provider/kubernetes/kubernetes.go @@ -41,7 +41,6 @@ func New(cfg *rest.Config, svr *config.Server, resources *message.ProviderResour LeaderElectionID: "5b9825d2.gateway.envoyproxy.io", } - // TODO: implement config validation on the watch mode config if svr.EnvoyGateway.NamespaceMode() { mgrOpts.Cache.DefaultNamespaces = make(map[string]cache.Config) for _, watchNS := range svr.EnvoyGateway.Provider.Kubernetes.Watch.Namespaces { diff --git a/internal/provider/kubernetes/kubernetes_test.go b/internal/provider/kubernetes/kubernetes_test.go index 39f96109ff8..2c470f12d02 100644 --- a/internal/provider/kubernetes/kubernetes_test.go +++ b/internal/provider/kubernetes/kubernetes_test.go @@ -141,7 +141,11 @@ func testGatewayClassAcceptedStatus(ctx context.Context, t *testing.T, provider // Even though no gateways exist, the controller loads the empty resource map // to support gateway deletions. require.Eventually(t, func() bool { - _, ok := resources.GatewayAPIResources.Load(gc.Name) + gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + if !ok { + return false + } + _, ok = (*gatewayClassResources)[gc.Name] return ok }, defaultWait, defaultTick) } @@ -195,9 +199,12 @@ func testGatewayClassWithParamRef(ctx context.Context, t *testing.T, provider *P return false }, defaultWait, defaultTick) - // Ensure the resource map contains the EnvoyProxy. require.Eventually(t, func() bool { - res, ok := resources.GatewayAPIResources.Load(gc.Name) + gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + if !ok { + return false + } + res, ok := (*gatewayClassResources)[gc.Name] if !ok { return false } @@ -335,7 +342,8 @@ func testGatewayScheduledStatus(ctx context.Context, t *testing.T, provider *Pro // Ensure the number of Gateways in the Gateway resource table is as expected. require.Eventually(t, func() bool { - res, _ := resources.GatewayAPIResources.Load("gc-scheduled-status-test") + gatewayClassResources, _ := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + res := (*gatewayClassResources)[gc.Name] return res != nil && len(res.Gateways) == 1 }, defaultWait, defaultTick) @@ -354,7 +362,8 @@ func testGatewayScheduledStatus(ctx context.Context, t *testing.T, provider *Pro return cli.Get(ctx, key, gw) == nil }, defaultWait, defaultTick) - res, _ := resources.GatewayAPIResources.Load("gc-scheduled-status-test") + gatewayClassResources, _ := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + res := (*gatewayClassResources)[gc.Name] // Only check if the spec is equal // The watchable map will not store a resource // with an updated status if the spec has not changed @@ -884,15 +893,18 @@ func testHTTPRoute(ctx context.Context, t *testing.T, provider *Provider, resour }, defaultWait, defaultTick) require.Eventually(t, func() bool { - res, ok := resources.GatewayAPIResources.Load("httproute-test") + gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + res := (*gatewayClassResources)[gc.Name] return ok && len(res.HTTPRoutes) != 0 }, defaultWait, defaultTick) - res, _ := resources.GatewayAPIResources.Load("httproute-test") + gatewayClassResources, _ := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + res := (*gatewayClassResources)[gc.Name] assert.Equal(t, &testCase.route, res.HTTPRoutes[0]) // Ensure the HTTPRoute Namespace is in the Namespace resource map. require.Eventually(t, func() bool { - res, ok := resources.GatewayAPIResources.Load(testCase.route.Namespace) + gatewayClassResources, _ := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + res, ok := (*gatewayClassResources)[testCase.route.Namespace] if !ok { return false } @@ -911,7 +923,8 @@ func testHTTPRoute(ctx context.Context, t *testing.T, provider *Provider, resour return true } - res, ok := resources.GatewayAPIResources.Load("httproute-test") + gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + res, ok := (*gatewayClassResources)[gc.Name] if !ok { return false } @@ -1031,15 +1044,21 @@ func testTLSRoute(ctx context.Context, t *testing.T, provider *Provider, resourc }, defaultWait, defaultTick) require.Eventually(t, func() bool { - res, ok := resources.GatewayAPIResources.Load("tlsroute-test") + gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + res, ok := (*gatewayClassResources)[gc.Name] + if !ok { + return false + } return ok && len(res.TLSRoutes) != 0 }, defaultWait, defaultTick) - res, _ := resources.GatewayAPIResources.Load("tlsroute-test") + gatewayClassResources, _ := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + res, _ := (*gatewayClassResources)[gc.Name] assert.Equal(t, &testCase.route, res.TLSRoutes[0]) // Ensure the HTTPRoute Namespace is in the Namespace resource map. require.Eventually(t, func() bool { - res, ok := resources.GatewayAPIResources.Load(testCase.route.Namespace) + gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + res, ok := (*gatewayClassResources)[gc.Name] if !ok { return false } @@ -1053,7 +1072,8 @@ func testTLSRoute(ctx context.Context, t *testing.T, provider *Provider, resourc // Ensure the Service is in the resource map. require.Eventually(t, func() bool { - res, ok := resources.GatewayAPIResources.Load("tlsroute-test") + gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + res, ok := (*gatewayClassResources)[gc.Name] if !ok { return false } @@ -1182,7 +1202,8 @@ func testServiceCleanupForMultipleRoutes(ctx context.Context, t *testing.T, prov // Check that the Service is present in the resource map require.Eventually(t, func() bool { - res, ok := resources.GatewayAPIResources.Load("service-cleanup-test") + gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + res, ok := (*gatewayClassResources)[gc.Name] if !ok { return false } @@ -1197,7 +1218,8 @@ func testServiceCleanupForMultipleRoutes(ctx context.Context, t *testing.T, prov // Delete the TLSRoute, and check if the Service is still present require.NoError(t, cli.Delete(ctx, &tlsRoute)) require.Eventually(t, func() bool { - res, ok := resources.GatewayAPIResources.Load("service-cleanup-test") + gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + res, ok := (*gatewayClassResources)[gc.Name] if !ok { return false } @@ -1212,7 +1234,8 @@ func testServiceCleanupForMultipleRoutes(ctx context.Context, t *testing.T, prov // Delete the HTTPRoute, and check if the Service is also removed require.NoError(t, cli.Delete(ctx, &httpRoute)) require.Eventually(t, func() bool { - res, ok := resources.GatewayAPIResources.Load("service-cleanup-test") + gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + res, ok := (*gatewayClassResources)[gc.Name] if !ok { return false } @@ -1285,7 +1308,7 @@ func TestNamespacedProvider(t *testing.T) { }() } -func TestNamespaceSelectorsProvider(t *testing.T) { +func TestNamespaceSelectorProvider(t *testing.T) { // Setup the test environment. testEnv, cliCfg, err := startEnv() require.NoError(t, err) @@ -1296,8 +1319,8 @@ func TestNamespaceSelectorsProvider(t *testing.T) { // config to watch a subset of namespaces svr.EnvoyGateway.Provider.Kubernetes = &egv1a1.EnvoyGatewayKubernetesProvider{ Watch: &egv1a1.KubernetesWatchMode{ - Type: egv1a1.KubernetesWatchModeTypeNamespaceSelectors, - NamespaceSelectors: []string{"label-1", "label-2"}, + Type: egv1a1.KubernetesWatchModeTypeNamespaceSelector, + NamespaceSelector: &metav1.LabelSelector{MatchLabels: map[string]string{"label-1": "true", "label-2": "true"}}, }, } @@ -1359,7 +1382,11 @@ func TestNamespaceSelectorsProvider(t *testing.T) { }() require.Eventually(t, func() bool { - res, _ := resources.GatewayAPIResources.Load(gc.Name) + gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + res, ok := (*gatewayClassResources)[gc.Name] + if !ok { + return false + } return res != nil && len(res.Gateways) == 1 }, defaultWait, defaultTick) @@ -1508,33 +1535,57 @@ func TestNamespaceSelectorsProvider(t *testing.T) { }() require.Eventually(t, func() bool { - res, _ := resources.GatewayAPIResources.Load(gc.Name) + gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + res, ok := (*gatewayClassResources)[gc.Name] + if !ok { + return false + } // The service number dependes on the service created and the backendRef return res != nil && len(res.Services) == 5 }, defaultWait, defaultTick) require.Eventually(t, func() bool { - res, _ := resources.GatewayAPIResources.Load(gc.Name) + gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + res, ok := (*gatewayClassResources)[gc.Name] + if !ok { + return false + } return res != nil && len(res.HTTPRoutes) == 1 }, defaultWait, defaultTick) require.Eventually(t, func() bool { - res, _ := resources.GatewayAPIResources.Load(gc.Name) + gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + res, ok := (*gatewayClassResources)[gc.Name] + if !ok { + return false + } return res != nil && len(res.TCPRoutes) == 1 }, defaultWait, defaultTick) require.Eventually(t, func() bool { - res, _ := resources.GatewayAPIResources.Load(gc.Name) + gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + res, ok := (*gatewayClassResources)[gc.Name] + if !ok { + return false + } return res != nil && len(res.TLSRoutes) == 1 }, defaultWait, defaultTick) require.Eventually(t, func() bool { - res, _ := resources.GatewayAPIResources.Load(gc.Name) + gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + res, ok := (*gatewayClassResources)[gc.Name] + if !ok { + return false + } return res != nil && len(res.UDPRoutes) == 1 }, defaultWait, defaultTick) require.Eventually(t, func() bool { - res, _ := resources.GatewayAPIResources.Load(gc.Name) + gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + res, ok := (*gatewayClassResources)[gc.Name] + if !ok { + return false + } return res != nil && len(res.GRPCRoutes) == 1 }, defaultWait, defaultTick) diff --git a/internal/provider/kubernetes/predicates.go b/internal/provider/kubernetes/predicates.go index 0ffcfc369a4..5a042d1cacf 100644 --- a/internal/provider/kubernetes/predicates.go +++ b/internal/provider/kubernetes/predicates.go @@ -12,13 +12,16 @@ import ( corev1 "k8s.io/api/core/v1" discoveryv1 "k8s.io/api/discovery/v1" kerrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" mcsapi "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1" + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/gatewayapi" "github.com/envoyproxy/gateway/internal/provider/utils" ) @@ -45,7 +48,7 @@ func (r *gatewayAPIReconciler) hasMatchingController(obj client.Object) bool { // hasMatchingNamespaceLabels returns true if the namespace of provided object has // the provided labels or false otherwise. func (r *gatewayAPIReconciler) hasMatchingNamespaceLabels(obj client.Object) bool { - ok, err := r.checkObjectNamespaceLabels(obj.GetNamespace()) + ok, err := r.checkObjectNamespaceLabels(obj) if err != nil { r.log.Error( err, "failed to get Namespace", @@ -61,44 +64,44 @@ type NamespaceGetter interface { } // checkObjectNamespaceLabels checks if labels of namespace of the object is a subset of namespaceLabels -// TODO: check if param can be an interface, so the caller doesn't need to get the namespace before calling -// this function. -func (r *gatewayAPIReconciler) checkObjectNamespaceLabels(nsString string) (bool, error) { - // TODO: add validation here because some objects don't have namespace +func (r *gatewayAPIReconciler) checkObjectNamespaceLabels(obj metav1.Object) (bool, error) { + + var nsString string + // TODO: it requires extra condition validate cluster resources or resources without namespace? + if nsString = obj.GetNamespace(); len(nsString) == 0 { + return false, nil + } + ns := &corev1.Namespace{} if err := r.client.Get( context.Background(), client.ObjectKey{ - Namespace: "", // Namespace object should have empty Namespace + Namespace: "", // Namespace object should have an empty Namespace Name: nsString, }, ns, ); err != nil { return false, err } - return containAll(ns.Labels, r.namespaceLabels), nil + + return matchLabelsAndExpressions(r.namespaceLabel, ns.Labels), nil } -func containAll(labels map[string]string, labelsToCheck []string) bool { - if len(labels) < len(labelsToCheck) { - return false - } - for _, l := range labelsToCheck { - if !contains(labels, l) { - return false - } +// matchLabelsAndExpressions extracts information from a given label selector and checks whether +// the provided object labels match the selector criteria. +// If the label selector is nil, it returns true, indicating a match. +// It returns false if there is an error while converting the label selector or if the labels do not match. +func matchLabelsAndExpressions(ls *metav1.LabelSelector, objLabels map[string]string) bool { + if ls == nil { + return true } - return true -} -func contains(m map[string]string, i string) bool { - for k := range m { - if k == i { - return true - } + selector, err := metav1.LabelSelectorAsSelector(ls) + if err != nil { + return false } - return false + return selector.Matches(labels.Set(objLabels)) } // validateGatewayForReconcile returns true if the provided object is a Gateway @@ -118,7 +121,7 @@ func (r *gatewayAPIReconciler) validateGatewayForReconcile(obj client.Object) bo } if gc.Spec.ControllerName != r.classController { - r.log.Info("gatewayclass controller name", gc.Spec.ControllerName, "class controller name", r.classController) + r.log.Info("gatewayclass controller name", string(gc.Spec.ControllerName), "class controller name", string(r.classController)) r.log.Info("gatewayclass name for gateway doesn't match configured name", "namespace", gw.Namespace, "name", gw.Name) return false @@ -135,11 +138,29 @@ func (r *gatewayAPIReconciler) validateSecretForReconcile(obj client.Object) boo return false } + nsName := utils.NamespacedName(secret) + + if r.isGatewayReferencingSecret(&nsName) { + return true + } + + if r.isSecurityPolicyReferencingSecret(&nsName) { + return true + } + + if r.isCtpReferencingSecret(&nsName) { + return true + } + + return false +} + +func (r *gatewayAPIReconciler) isGatewayReferencingSecret(nsName *types.NamespacedName) bool { gwList := &gwapiv1.GatewayList{} if err := r.client.List(context.Background(), gwList, &client.ListOptions{ - FieldSelector: fields.OneTermEqualSelector(secretGatewayIndex, utils.NamespacedName(secret).String()), + FieldSelector: fields.OneTermEqualSelector(secretGatewayIndex, nsName.String()), }); err != nil { - r.log.Error(err, "unable to find associated HTTPRoutes") + r.log.Error(err, "unable to find associated Gateways") return false } @@ -153,10 +174,33 @@ func (r *gatewayAPIReconciler) validateSecretForReconcile(obj client.Object) boo return false } } - return true } +func (r *gatewayAPIReconciler) isSecurityPolicyReferencingSecret(nsName *types.NamespacedName) bool { + spList := &egv1a1.SecurityPolicyList{} + if err := r.client.List(context.Background(), spList, &client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector(secretSecurityPolicyIndex, nsName.String()), + }); err != nil { + r.log.Error(err, "unable to find associated SecurityPolicies") + return false + } + + return len(spList.Items) > 0 +} + +func (r *gatewayAPIReconciler) isCtpReferencingSecret(nsName *types.NamespacedName) bool { + ctpList := &egv1a1.ClientTrafficPolicyList{} + if err := r.client.List(context.Background(), ctpList, &client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector(secretCtpIndex, nsName.String()), + }); err != nil { + r.log.Error(err, "unable to find associated ClientTrafficPolicies") + return false + } + + return len(ctpList.Items) > 0 +} + // validateServiceForReconcile tries finding the owning Gateway of the Service // if it exists, finds the Gateway's Deployment, and further updates the Gateway // status Ready condition. All Services are pushed for reconciliation. @@ -172,26 +216,43 @@ func (r *gatewayAPIReconciler) validateServiceForReconcile(obj client.Object) bo // Check if the Service belongs to a Gateway, if so, update the Gateway status. gtw := r.findOwningGateway(ctx, labels) if gtw != nil { - r.statusUpdateForGateway(ctx, gtw) + r.updateStatusForGateway(ctx, gtw) return false } - // Only merged gateways will have this label, update status of all Gateways under found GatewayClass. + // Merged gateways will have only this label, update status of all Gateways under found GatewayClass. gclass, ok := labels[gatewayapi.OwningGatewayClassLabel] - if ok { - res, _ := r.resources.GatewayAPIResources.Load(gclass) - if res != nil && len(res.Gateways) > 0 { - for _, gw := range res.Gateways { - gw := gw - r.statusUpdateForGateway(ctx, gw) + if ok && r.mergeGateways[gclass] { + res, _ := r.resources.GatewayAPIResources.Load(string(r.classController)) + if res != nil { + if (*res)[gclass] != nil && len((*res)[gclass].Gateways) > 0 { + for _, gw := range (*res)[gclass].Gateways { + gw := gw + r.updateStatusForGateway(ctx, gw) + } } } - return false } nsName := utils.NamespacedName(svc) - return r.isRouteReferencingBackend(&nsName) + if r.isRouteReferencingBackend(&nsName) { + return true + } + + return r.isSecurityPolicyReferencingBackend(&nsName) +} + +func (r *gatewayAPIReconciler) isSecurityPolicyReferencingBackend(nsName *types.NamespacedName) bool { + spList := &egv1a1.SecurityPolicyList{} + if err := r.client.List(context.Background(), spList, &client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector(backendSecurityPolicyIndex, nsName.String()), + }); err != nil { + r.log.Error(err, "unable to find associated SecurityPolicies") + return false + } + + return len(spList.Items) > 0 } // validateServiceImportForReconcile tries finding the owning Gateway of the ServiceImport @@ -287,7 +348,11 @@ func (r *gatewayAPIReconciler) validateEndpointSliceForReconcile(obj client.Obje nsName.Name = multiClusterSvcName } - return r.isRouteReferencingBackend(&nsName) + if r.isRouteReferencingBackend(&nsName) { + return true + } + + return r.isSecurityPolicyReferencingBackend(&nsName) } // validateDeploymentForReconcile tries finding the owning Gateway of the Deployment @@ -307,19 +372,21 @@ func (r *gatewayAPIReconciler) validateDeploymentForReconcile(obj client.Object) // Check if the deployment belongs to a Gateway, if so, update the Gateway status. gtw := r.findOwningGateway(ctx, labels) if gtw != nil { - r.statusUpdateForGateway(ctx, gtw) + r.updateStatusForGateway(ctx, gtw) return false } } - // Only merged gateways will have this label, update status of all Gateways under found GatewayClass. + // Merged gateways will have only this label, update status of all Gateways under found GatewayClass. gclass, ok := labels[gatewayapi.OwningGatewayClassLabel] - if ok { - res, _ := r.resources.GatewayAPIResources.Load(gclass) - if res != nil && len(res.Gateways) > 0 { - for _, gw := range res.Gateways { - gw := gw - r.statusUpdateForGateway(ctx, gw) + if ok && r.mergeGateways[gclass] { + res, _ := r.resources.GatewayAPIResources.Load(string(r.classController)) + if res != nil { + if (*res)[gclass] != nil && len((*res)[gclass].Gateways) > 0 { + for _, gw := range (*res)[gclass].Gateways { + gw := gw + r.updateStatusForGateway(ctx, gw) + } } } return false @@ -333,7 +400,7 @@ func (r *gatewayAPIReconciler) validateDeploymentForReconcile(obj client.Object) func (r *gatewayAPIReconciler) envoyDeploymentForGateway(ctx context.Context, gateway *gwapiv1.Gateway) (*appsv1.Deployment, error) { key := types.NamespacedName{ Namespace: r.namespace, - Name: infraName(gateway, r.mergeGateways), + Name: infraName(gateway, r.mergeGateways[string(gateway.Spec.GatewayClassName)]), } deployment := new(appsv1.Deployment) if err := r.client.Get(ctx, key, deployment); err != nil { @@ -349,7 +416,7 @@ func (r *gatewayAPIReconciler) envoyDeploymentForGateway(ctx context.Context, ga func (r *gatewayAPIReconciler) envoyServiceForGateway(ctx context.Context, gateway *gwapiv1.Gateway) (*corev1.Service, error) { key := types.NamespacedName{ Namespace: r.namespace, - Name: infraName(gateway, r.mergeGateways), + Name: infraName(gateway, r.mergeGateways[string(gateway.Spec.GatewayClassName)]), } svc := new(corev1.Service) if err := r.client.Get(ctx, key, svc); err != nil { @@ -404,3 +471,26 @@ func (r *gatewayAPIReconciler) handleNode(obj client.Object) bool { r.store.addNode(node) return true } + +// validateConfigMapForReconcile checks whether the ConfigMap belongs to a valid ClientTrafficPolicy. +func (r *gatewayAPIReconciler) validateConfigMapForReconcile(obj client.Object) bool { + configMap, ok := obj.(*corev1.ConfigMap) + if !ok { + r.log.Info("unexpected object type, bypassing reconciliation", "object", obj) + return false + } + + ctpList := &egv1a1.ClientTrafficPolicyList{} + if err := r.client.List(context.Background(), ctpList, &client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector(configMapCtpIndex, utils.NamespacedName(configMap).String()), + }); err != nil { + r.log.Error(err, "unable to find associated ClientTrafficPolicy") + return false + } + + if len(ctpList.Items) == 0 { + return false + } + + return true +} diff --git a/internal/provider/kubernetes/predicates_test.go b/internal/provider/kubernetes/predicates_test.go index 18eeba59550..c36f29016bb 100644 --- a/internal/provider/kubernetes/predicates_test.go +++ b/internal/provider/kubernetes/predicates_test.go @@ -6,16 +6,19 @@ package kubernetes import ( + "fmt" "testing" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + 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" gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + gwapiv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/envoygateway" @@ -65,30 +68,37 @@ func TestGatewayClassHasMatchingController(t *testing.T) { // TestGatewayClassHasMatchingNamespaceLabels tests the hasMatchingNamespaceLabels // predicate function. func TestGatewayClassHasMatchingNamespaceLabels(t *testing.T) { + matchExpressions := func(key string, operator metav1.LabelSelectorOperator, values []string) []metav1.LabelSelectorRequirement { + return []metav1.LabelSelectorRequirement{{ + Key: key, + Operator: operator, + Values: values, + }} + } ns := "namespace-1" testCases := []struct { name string - labels []string - namespaceLabels []string + labels map[string]string + namespaceLabels string expect bool }{ { name: "matching one label when namespace has one label", - labels: []string{"label-1"}, - namespaceLabels: []string{"label-1"}, + labels: map[string]string{"label-1": ""}, + namespaceLabels: "label-1", expect: true, }, { name: "matching one label when namespace has two labels", - labels: []string{"label-1"}, - namespaceLabels: []string{"label-1", "label-2"}, - expect: true, + labels: map[string]string{"label-1": ""}, + namespaceLabels: "label-2", + expect: false, }, { name: "namespace has less labels than the specified labels", - labels: []string{"label-1", "label-2"}, - namespaceLabels: []string{"label-1"}, - expect: false, + labels: map[string]string{"label-1": "", "label-2": ""}, + namespaceLabels: "label-1", + expect: true, }, } @@ -97,23 +107,18 @@ func TestGatewayClassHasMatchingNamespaceLabels(t *testing.T) { for _, tc := range testCases { tc := tc - namespaceLabelsToMap := make(map[string]string) - for _, l := range tc.namespaceLabels { - namespaceLabelsToMap[l] = "" - } - r := gatewayAPIReconciler{ classController: v1alpha1.GatewayControllerName, - namespaceLabels: tc.labels, + namespaceLabel: &metav1.LabelSelector{MatchExpressions: matchExpressions(tc.namespaceLabels, metav1.LabelSelectorOpExists, []string{})}, log: logger, client: fakeclient.NewClientBuilder(). WithScheme(envoygateway.GetScheme()). WithObjects(&corev1.Namespace{ - TypeMeta: v1.TypeMeta{ + TypeMeta: metav1.TypeMeta{ Kind: "Namespace", APIVersion: "v1", }, - ObjectMeta: v1.ObjectMeta{Name: ns, Labels: namespaceLabelsToMap}, + ObjectMeta: metav1.ObjectMeta{Name: ns, Labels: tc.labels}, }). Build(), } @@ -208,7 +213,67 @@ func TestValidateSecretForReconcile(t *testing.T) { expect: false, }, { - name: "gateway does not exist", + name: "references SecurityPolicy OIDC", + configs: []client.Object{ + test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), + test.GetGateway(types.NamespacedName{Name: "scheduled-status-test"}, "test-gc"), + &v1alpha1.SecurityPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "oidc", + }, + Spec: v1alpha1.SecurityPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Kind: "Gateway", + Name: "scheduled-status-test", + }, + }, + OIDC: &v1alpha1.OIDC{ + Provider: v1alpha1.OIDCProvider{ + Issuer: "https://accounts.google.com", + AuthorizationEndpoint: ptr.To("https://accounts.google.com/o/oauth2/v2/auth"), + TokenEndpoint: ptr.To("https://oauth2.googleapis.com/token"), + }, + ClientID: "client-id", + ClientSecret: gwapiv1b1.SecretObjectReference{ + Name: "secret", + }, + }, + }, + }, + }, + secret: test.GetSecret(types.NamespacedName{Name: "secret"}), + expect: true, + }, + { + name: "references SecurityPolicy Basic Auth", + configs: []client.Object{ + test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), + test.GetGateway(types.NamespacedName{Name: "scheduled-status-test"}, "test-gc"), + &v1alpha1.SecurityPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "basic-auth", + }, + Spec: v1alpha1.SecurityPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Kind: "Gateway", + Name: "scheduled-status-test", + }, + }, + BasicAuth: &v1alpha1.BasicAuth{ + Users: gwapiv1b1.SecretObjectReference{ + Name: "secret", + }, + }, + }, + }, + }, + secret: test.GetSecret(types.NamespacedName{Name: "secret"}), + expect: true, + }, + { + name: "secret is not referenced by any EG CRs", configs: []client.Object{ test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), }, @@ -231,6 +296,7 @@ func TestValidateSecretForReconcile(t *testing.T) { WithScheme(envoygateway.GetScheme()). WithObjects(tc.configs...). WithIndex(&gwapiv1.Gateway{}, secretGatewayIndex, secretGatewayIndexFunc). + WithIndex(&v1alpha1.SecurityPolicy{}, secretSecurityPolicyIndex, secretSecurityPolicyIndexFunc). Build() t.Run(tc.name, func(t *testing.T) { res := r.validateSecretForReconcile(tc.secret) @@ -419,6 +485,33 @@ func TestValidateServiceForReconcile(t *testing.T) { service: test.GetService(types.NamespacedName{Name: "service"}, nil, nil), expect: true, }, + { + name: "service referenced by SecurityPolicy ExtAuth HTTP service", + configs: []client.Object{ + &v1alpha1.SecurityPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "ext-auth-http", + }, + Spec: v1alpha1.SecurityPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Kind: "Gateway", + Name: "scheduled-status-test", + }, + }, + ExtAuth: &v1alpha1.ExtAuth{ + HTTP: &v1alpha1.HTTPExtAuthService{ + BackendRef: gwapiv1.BackendObjectReference{ + Name: "ext-auth-http-service", + }, + }, + }, + }, + }, + }, + service: test.GetService(types.NamespacedName{Name: "ext-auth-http-service"}, nil, nil), + expect: true, + }, } // Create the reconciler. @@ -439,6 +532,7 @@ func TestValidateServiceForReconcile(t *testing.T) { WithIndex(&gwapiv1a2.TLSRoute{}, backendTLSRouteIndex, backendTLSRouteIndexFunc). WithIndex(&gwapiv1a2.TCPRoute{}, backendTCPRouteIndex, backendTCPRouteIndexFunc). WithIndex(&gwapiv1a2.UDPRoute{}, backendUDPRouteIndex, backendUDPRouteIndexFunc). + WithIndex(&v1alpha1.SecurityPolicy{}, backendSecurityPolicyIndex, backendSecurityPolicyIndexFunc). Build() t.Run(tc.name, func(t *testing.T) { res := r.validateServiceForReconcile(tc.service) @@ -495,3 +589,205 @@ func TestValidateDeploymentForReconcile(t *testing.T) { }) } } + +func TestCheckObjectNamespaceLabels(t *testing.T) { + matchExpressions := func(key string, operator metav1.LabelSelectorOperator, values []string) []metav1.LabelSelectorRequirement { + return []metav1.LabelSelectorRequirement{{ + Key: key, + Operator: operator, + Values: values, + }} + } + testCases := []struct { + name string + object client.Object + reconcileLabels string + ns *corev1.Namespace + expect bool + }{ + { + name: "matching labels of namespace of the object is a subset of namespaceLabels", + object: test.GetHTTPRoute( + types.NamespacedName{ + Name: "foo-route", + Namespace: "foo", + }, + "eg", + types.NamespacedName{ + Name: "foo-svc", + Namespace: "foo", + }, + 8080, + ), + ns: &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Labels: map[string]string{ + "label-1": "", + }, + }, + }, + reconcileLabels: "label-1", + expect: true, + }, + { + name: "non-matching labels of namespace of the object is a subset of namespaceLabels", + object: test.GetHTTPRoute( + types.NamespacedName{ + Name: "bar-route", + Namespace: "bar", + }, + "eg", + types.NamespacedName{ + Name: "bar-svc", + Namespace: "bar", + }, + 8080, + ), + ns: &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "bar", + Labels: map[string]string{ + "label-2": "", + }, + }, + }, + reconcileLabels: "label-1", + expect: false, + }, + { + name: "non-matching labels of namespace of the cluster-level object is a subset of namespaceLabels", + object: &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo-1", + Labels: map[string]string{ + "label-1": "", + }, + }, + }, + ns: &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "bar-1", + Labels: map[string]string{ + "label-1": "", + }, + }, + }, + reconcileLabels: "label-1", + expect: false, + }, + } + + // Create the reconciler. + logger := logging.DefaultLogger(v1alpha1.LogLevelInfo) + + r := gatewayAPIReconciler{ + classController: v1alpha1.GatewayControllerName, + log: logger, + } + + for _, tc := range testCases { + tc := tc + r.client = fakeclient.NewClientBuilder().WithObjects(tc.ns).Build() + r.namespaceLabel = &metav1.LabelSelector{MatchExpressions: matchExpressions(tc.reconcileLabels, metav1.LabelSelectorOpExists, []string{})} + ok, err := r.checkObjectNamespaceLabels(tc.object) + require.NoError(t, err) + require.Equal(t, tc.expect, ok) + } +} + +func TestMatchLabelsAndExpressions(t *testing.T) { + matchLabels := map[string]string{"foo": "bar"} + matchExpressions := func(operator metav1.LabelSelectorOperator, values []string) []metav1.LabelSelectorRequirement { + return []metav1.LabelSelectorRequirement{{ + Key: "baz", + Operator: operator, + Values: values, + }} + } + + tests := []struct { + ls *metav1.LabelSelector + objLabels map[string]string + want bool + }{ + { + ls: &metav1.LabelSelector{MatchLabels: matchLabels}, + objLabels: map[string]string{"foo": "bar"}, + want: true, + }, + { + ls: &metav1.LabelSelector{MatchLabels: matchLabels, MatchExpressions: matchExpressions(metav1.LabelSelectorOpIn, []string{"norf"})}, + objLabels: map[string]string{"foo": "bar", "baz": "norf"}, + want: true, + }, + { + ls: &metav1.LabelSelector{MatchExpressions: matchExpressions(metav1.LabelSelectorOpIn, []string{"norf"})}, + objLabels: map[string]string{"baz": "norf"}, + want: true, + }, + { + ls: &metav1.LabelSelector{MatchLabels: matchLabels, MatchExpressions: matchExpressions(metav1.LabelSelectorOpIn, []string{"norf", "qux"})}, + objLabels: map[string]string{"foo": "bar", "baz": "norf"}, + want: true, + }, + { + ls: &metav1.LabelSelector{MatchLabels: matchLabels, MatchExpressions: matchExpressions(metav1.LabelSelectorOpIn, []string{"norf", "qux"})}, + objLabels: map[string]string{"foo": "bar"}, + want: false, + }, + { + ls: &metav1.LabelSelector{MatchExpressions: matchExpressions(metav1.LabelSelectorOpNotIn, []string{"norf", "qux"})}, + objLabels: map[string]string{}, + want: true, + }, + { + ls: &metav1.LabelSelector{MatchExpressions: matchExpressions(metav1.LabelSelectorOpNotIn, []string{"norf", "qux"})}, + objLabels: map[string]string{"baz": "norf"}, + want: false, + }, + { + ls: &metav1.LabelSelector{MatchLabels: matchLabels, MatchExpressions: matchExpressions(metav1.LabelSelectorOpNotIn, []string{"norf", "qux"})}, + objLabels: map[string]string{"foo": "bar"}, + want: true, + }, + { + ls: &metav1.LabelSelector{MatchLabels: matchLabels, MatchExpressions: matchExpressions(metav1.LabelSelectorOpNotIn, []string{"norf", "qux"})}, + objLabels: map[string]string{"foo": "bar", "baz": "norf"}, + want: false, + }, + { + ls: &metav1.LabelSelector{MatchLabels: matchLabels, MatchExpressions: matchExpressions(metav1.LabelSelectorOpExists, []string{})}, + objLabels: map[string]string{"foo": "bar"}, + want: false, + }, + { + ls: &metav1.LabelSelector{MatchLabels: matchLabels, MatchExpressions: matchExpressions(metav1.LabelSelectorOpExists, []string{})}, + objLabels: map[string]string{"foo": "bar", "baz": "1111"}, + want: true, + }, + { + ls: &metav1.LabelSelector{MatchLabels: matchLabels, MatchExpressions: matchExpressions(metav1.LabelSelectorOpDoesNotExist, []string{})}, + objLabels: map[string]string{"foo": "bar", "baz": "1111"}, + want: false, + }, + { + ls: &metav1.LabelSelector{MatchExpressions: matchExpressions(metav1.LabelSelectorOpDoesNotExist, []string{})}, + objLabels: map[string]string{"baz": "1111"}, + want: false, + }, + { + ls: &metav1.LabelSelector{MatchExpressions: matchExpressions(metav1.LabelSelectorOpDoesNotExist, []string{})}, + objLabels: map[string]string{"bazz": "1111"}, + want: true, + }, + } + + for i, tc := range tests { + t.Run(fmt.Sprintf("test-%d", i), func(t *testing.T) { + if got := matchLabelsAndExpressions(tc.ls, tc.objLabels); got != tc.want { + t.Errorf("ExtractMatchedSelectorInfo() = %v, want %v", got, tc.want) + } + }) + } +} diff --git a/internal/provider/kubernetes/routes.go b/internal/provider/kubernetes/routes.go index 39ea26f1309..ae0fa3fe883 100644 --- a/internal/provider/kubernetes/routes.go +++ b/internal/provider/kubernetes/routes.go @@ -8,7 +8,6 @@ package kubernetes import ( "context" "errors" - "fmt" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/runtime/schema" @@ -33,26 +32,16 @@ func (r *gatewayAPIReconciler) processTLSRoutes(ctx context.Context, gatewayName return err } - tlsRoutes := tlsRouteList.Items - if len(r.namespaceLabels) != 0 { - var rts []gwapiv1a2.TLSRoute - for _, rt := range tlsRoutes { - ns := rt.GetNamespace() - ok, err := r.checkObjectNamespaceLabels(ns) - if err != nil { - // TODO: should return? or just proceed? - return fmt.Errorf("failed to check namespace labels for TLSRoute %s in namespace %s: %w", rt.GetName(), ns, err) - } - - if ok { - rts = append(rts, rt) + for _, tlsRoute := range tlsRouteList.Items { + tlsRoute := tlsRoute + if r.namespaceLabel != nil { + if ok, err := r.checkObjectNamespaceLabels(&tlsRoute); err != nil { + r.log.Error(err, "failed to check namespace labels for TLSRoute %s in namespace %s: %w", tlsRoute.GetName(), tlsRoute.GetNamespace()) + continue + } else if !ok { + continue } } - tlsRoutes = rts - } - - for _, tlsRoute := range tlsRoutes { - tlsRoute := tlsRoute r.log.Info("processing TLSRoute", "namespace", tlsRoute.Namespace, "name", tlsRoute.Name) for _, rule := range tlsRoute.Spec.Rules { @@ -114,26 +103,16 @@ func (r *gatewayAPIReconciler) processGRPCRoutes(ctx context.Context, gatewayNam return err } - grpcRoutes := grpcRouteList.Items - if len(r.namespaceLabels) != 0 { - var grs []gwapiv1a2.GRPCRoute - for _, gr := range grpcRoutes { - ns := gr.GetNamespace() - ok, err := r.checkObjectNamespaceLabels(ns) - if err != nil { - // TODO: should return? or just proceed? - return fmt.Errorf("failed to check namespace labels for GRPCRoute %s in namespace %s: %w", gr.GetName(), ns, err) - } - if ok { - grs = append(grs, gr) + for _, grpcRoute := range grpcRouteList.Items { + grpcRoute := grpcRoute + if r.namespaceLabel != nil { + if ok, err := r.checkObjectNamespaceLabels(&grpcRoute); err != nil { + r.log.Error(err, "failed to check namespace labels for GRPCRoute %s in namespace %s: %w", grpcRoute.GetName(), grpcRoute.GetNamespace()) + continue + } else if !ok { + continue } } - - grpcRoutes = grs - } - - for _, grpcRoute := range grpcRoutes { - grpcRoute := grpcRoute r.log.Info("processing GRPCRoute", "namespace", grpcRoute.Namespace, "name", grpcRoute.Name) for _, rule := range grpcRoute.Spec.Rules { @@ -243,26 +222,16 @@ func (r *gatewayAPIReconciler) processHTTPRoutes(ctx context.Context, gatewayNam return err } - httpRoutes := httpRouteList.Items - if len(r.namespaceLabels) != 0 { - var hrs []gwapiv1.HTTPRoute - for _, hr := range httpRoutes { - ns := hr.GetNamespace() - ok, err := r.checkObjectNamespaceLabels(ns) - if err != nil { - // TODO: should return? or just proceed? - return fmt.Errorf("failed to check namespace labels for HTTPRoute %s in namespace %s: %w", hr.GetName(), ns, err) - } - - if ok { - hrs = append(hrs, hr) + for _, httpRoute := range httpRouteList.Items { + httpRoute := httpRoute + if r.namespaceLabel != nil { + if ok, err := r.checkObjectNamespaceLabels(&httpRoute); err != nil { + r.log.Error(err, "failed to check namespace labels for HTTPRoute %s in namespace %s: %w", httpRoute.GetName(), httpRoute.GetNamespace()) + continue + } else if !ok { + continue } } - httpRoutes = hrs - } - - for _, httpRoute := range httpRoutes { - httpRoute := httpRoute r.log.Info("processing HTTPRoute", "namespace", httpRoute.Namespace, "name", httpRoute.Name) for _, rule := range httpRoute.Spec.Rules { @@ -416,27 +385,16 @@ func (r *gatewayAPIReconciler) processTCPRoutes(ctx context.Context, gatewayName return err } - tcpRoutes := tcpRouteList.Items - if len(r.namespaceLabels) != 0 { - var trs []gwapiv1a2.TCPRoute - for _, tr := range tcpRoutes { - ns := tr.GetNamespace() - ok, err := r.checkObjectNamespaceLabels(ns) - if err != nil { - // TODO: should return? or just proceed? - return fmt.Errorf("failed to check namespace labels for TCPRoute %s in namespace %s: %w", tr.GetName(), ns, err) - } - - if ok { - trs = append(trs, tr) + for _, tcpRoute := range tcpRouteList.Items { + tcpRoute := tcpRoute + if r.namespaceLabel != nil { + if ok, err := r.checkObjectNamespaceLabels(&tcpRoute); err != nil { + r.log.Error(err, "failed to check namespace labels for TCPRoute %s in namespace %s: %w", tcpRoute.GetName(), tcpRoute.GetNamespace()) + continue + } else if !ok { + continue } } - - tcpRoutes = trs - } - - for _, tcpRoute := range tcpRoutes { - tcpRoute := tcpRoute r.log.Info("processing TCPRoute", "namespace", tcpRoute.Namespace, "name", tcpRoute.Name) for _, rule := range tcpRoute.Spec.Rules { @@ -497,27 +455,16 @@ func (r *gatewayAPIReconciler) processUDPRoutes(ctx context.Context, gatewayName return err } - udpRoutes := udpRouteList.Items - if len(r.namespaceLabels) != 0 { - var urs []gwapiv1a2.UDPRoute - for _, ur := range udpRoutes { - ns := ur.GetNamespace() - ok, err := r.checkObjectNamespaceLabels(ns) - if err != nil { - // TODO: should return? or just proceed? - return fmt.Errorf("failed to check namespace labels for UDPRoute %s in namespace %s: %w", ur.GetName(), ns, err) - } - - if ok { - urs = append(urs, ur) + for _, udpRoute := range udpRouteList.Items { + udpRoute := udpRoute + if r.namespaceLabel != nil { + if ok, err := r.checkObjectNamespaceLabels(&udpRoute); err != nil { + r.log.Error(err, "failed to check namespace labels for UDPRoute %s in namespace %s: %w", udpRoute.GetName(), udpRoute.GetNamespace()) + continue + } else if !ok { + continue } } - - udpRoutes = urs - } - - for _, udpRoute := range udpRoutes { - udpRoute := udpRoute r.log.Info("processing UDPRoute", "namespace", udpRoute.Namespace, "name", udpRoute.Name) for _, rule := range udpRoute.Spec.Rules { diff --git a/internal/provider/kubernetes/routes_test.go b/internal/provider/kubernetes/routes_test.go index c4f46b5693e..b7d747aa3e8 100644 --- a/internal/provider/kubernetes/routes_test.go +++ b/internal/provider/kubernetes/routes_test.go @@ -60,6 +60,8 @@ func TestProcessHTTPRoutes(t *testing.T) { } gwNsName := utils.NamespacedName(gw).String() + invalidDuration := gwapiv1.Duration("invalid duration") + testCases := []struct { name string routes []*gwapiv1.HTTPRoute @@ -184,6 +186,54 @@ func TestProcessHTTPRoutes(t *testing.T) { }, expected: true, }, + { + name: "httproute with invalid timeout setting for HTTPRouteRule", + routes: []*gwapiv1.HTTPRoute{ + { + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test", + }, + Spec: gwapiv1.HTTPRouteSpec{ + CommonRouteSpec: gwapiv1.CommonRouteSpec{ + ParentRefs: []gwapiv1.ParentReference{ + { + Name: "test", + }, + }, + }, + Rules: []gwapiv1.HTTPRouteRule{ + { + Matches: []gwapiv1.HTTPRouteMatch{ + { + Path: &gwapiv1.HTTPPathMatch{ + Type: ptr.To(gwapiv1.PathMatchPathPrefix), + Value: ptr.To("/"), + }, + }, + }, + BackendRefs: []gwapiv1.HTTPBackendRef{ + { + BackendRef: gwapiv1.BackendRef{ + BackendObjectReference: gwapiv1.BackendObjectReference{ + Group: gatewayapi.GroupPtr(corev1.GroupName), + Kind: gatewayapi.KindPtr(gatewayapi.KindService), + Name: "test", + }, + }, + }, + }, + Timeouts: &gwapiv1.HTTPRouteTimeouts{ + Request: &invalidDuration, + BackendRequest: &invalidDuration, + }, + }, + }, + }, + }, + }, + expected: true, + }, } for i := range testCases { @@ -421,10 +471,6 @@ func TestValidateHTTPRouteParentRefs(t *testing.T) { }, expect: []gwapiv1.Gateway{ { - TypeMeta: metav1.TypeMeta{ - Kind: "Gateway", - APIVersion: gwapiv1.GroupVersion.String(), - }, ObjectMeta: metav1.ObjectMeta{ Namespace: "test", Name: "test", @@ -556,10 +602,6 @@ func TestValidateHTTPRouteParentRefs(t *testing.T) { }, expect: []gwapiv1.Gateway{ { - TypeMeta: metav1.TypeMeta{ - Kind: "Gateway", - APIVersion: gwapiv1.GroupVersion.String(), - }, ObjectMeta: metav1.ObjectMeta{ Namespace: "test", Name: "test", @@ -570,10 +612,6 @@ func TestValidateHTTPRouteParentRefs(t *testing.T) { }, }, { - TypeMeta: metav1.TypeMeta{ - Kind: "Gateway", - APIVersion: gwapiv1.GroupVersion.String(), - }, ObjectMeta: metav1.ObjectMeta{ Namespace: "test", Name: "test2", @@ -650,10 +688,6 @@ func TestValidateHTTPRouteParentRefs(t *testing.T) { }, expect: []gwapiv1.Gateway{ { - TypeMeta: metav1.TypeMeta{ - Kind: "Gateway", - APIVersion: gwapiv1.GroupVersion.String(), - }, ObjectMeta: metav1.ObjectMeta{ Namespace: "test", Name: "test", diff --git a/internal/provider/kubernetes/status.go b/internal/provider/kubernetes/status.go new file mode 100644 index 00000000000..83f88579c46 --- /dev/null +++ b/internal/provider/kubernetes/status.go @@ -0,0 +1,411 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package kubernetes + +import ( + "context" + "fmt" + + kerrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" + gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + + "github.com/envoyproxy/gateway/api/v1alpha1" + "github.com/envoyproxy/gateway/internal/message" + "github.com/envoyproxy/gateway/internal/provider/utils" + "github.com/envoyproxy/gateway/internal/status" +) + +// subscribeAndUpdateStatus subscribes to gateway API object status updates and +// writes it into the Kubernetes API Server. +func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context) { + // Gateway object status updater + go func() { + message.HandleSubscription( + message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "gateway-status"}, + r.resources.GatewayStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *gwapiv1.GatewayStatus], errChan chan error) { + // skip delete updates. + if update.Delete { + return + } + // Get gateway object + gtw := new(gwapiv1.Gateway) + if err := r.client.Get(ctx, update.Key, gtw); err != nil { + r.log.Error(err, "gateway not found", "namespace", gtw.Namespace, "name", gtw.Name) + errChan <- err + return + } + // Set the updated Status and call the status update + gtw.Status = *update.Value + r.updateStatusForGateway(ctx, gtw) + }, + ) + r.log.Info("gateway status subscriber shutting down") + }() + + // HTTPRoute object status updater + go func() { + message.HandleSubscription( + message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "httproute-status"}, + r.resources.HTTPRouteStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *gwapiv1.HTTPRouteStatus], errChan chan error) { + // skip delete updates. + if update.Delete { + return + } + key := update.Key + val := update.Value + r.statusUpdater.Send(status.Update{ + NamespacedName: key, + Resource: new(gwapiv1.HTTPRoute), + Mutator: status.MutatorFunc(func(obj client.Object) client.Object { + h, ok := obj.(*gwapiv1.HTTPRoute) + if !ok { + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) + } + hCopy := h.DeepCopy() + hCopy.Status.Parents = val.Parents + return hCopy + }), + }) + }, + ) + r.log.Info("httpRoute status subscriber shutting down") + }() + + // GRPCRoute object status updater + go func() { + message.HandleSubscription(message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "grpcroute-status"}, r.resources.GRPCRouteStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *gwapiv1a2.GRPCRouteStatus], errChan chan error) { + // skip delete updates. + if update.Delete { + return + } + key := update.Key + val := update.Value + r.statusUpdater.Send(status.Update{ + NamespacedName: key, + Resource: new(gwapiv1a2.GRPCRoute), + Mutator: status.MutatorFunc(func(obj client.Object) client.Object { + h, ok := obj.(*gwapiv1a2.GRPCRoute) + if !ok { + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) + } + hCopy := h.DeepCopy() + hCopy.Status.Parents = val.Parents + return hCopy + }), + }) + }, + ) + r.log.Info("grpcRoute status subscriber shutting down") + }() + + // TLSRoute object status updater + go func() { + message.HandleSubscription( + message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "tlsroute-status"}, + r.resources.TLSRouteStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *gwapiv1a2.TLSRouteStatus], errChan chan error) { + // skip delete updates. + if update.Delete { + return + } + key := update.Key + val := update.Value + r.statusUpdater.Send(status.Update{ + NamespacedName: key, + Resource: new(gwapiv1a2.TLSRoute), + Mutator: status.MutatorFunc(func(obj client.Object) client.Object { + t, ok := obj.(*gwapiv1a2.TLSRoute) + if !ok { + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) + } + tCopy := t.DeepCopy() + tCopy.Status.Parents = val.Parents + return tCopy + }), + }) + }, + ) + r.log.Info("tlsRoute status subscriber shutting down") + }() + + // TCPRoute object status updater + go func() { + message.HandleSubscription( + message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "tcproute-status"}, + r.resources.TCPRouteStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *gwapiv1a2.TCPRouteStatus], errChan chan error) { + // skip delete updates. + if update.Delete { + return + } + key := update.Key + val := update.Value + r.statusUpdater.Send(status.Update{ + NamespacedName: key, + Resource: new(gwapiv1a2.TCPRoute), + Mutator: status.MutatorFunc(func(obj client.Object) client.Object { + t, ok := obj.(*gwapiv1a2.TCPRoute) + if !ok { + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) + } + tCopy := t.DeepCopy() + tCopy.Status.Parents = val.Parents + return tCopy + }), + }) + }, + ) + r.log.Info("tcpRoute status subscriber shutting down") + }() + + // UDPRoute object status updater + go func() { + message.HandleSubscription( + message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "udproute-status"}, + r.resources.UDPRouteStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *gwapiv1a2.UDPRouteStatus], errChan chan error) { + // skip delete updates. + if update.Delete { + return + } + key := update.Key + val := update.Value + r.statusUpdater.Send(status.Update{ + NamespacedName: key, + Resource: new(gwapiv1a2.UDPRoute), + Mutator: status.MutatorFunc(func(obj client.Object) client.Object { + t, ok := obj.(*gwapiv1a2.UDPRoute) + if !ok { + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) + } + tCopy := t.DeepCopy() + tCopy.Status.Parents = val.Parents + return tCopy + }), + }) + }, + ) + r.log.Info("udpRoute status subscriber shutting down") + }() + + // EnvoyPatchPolicy object status updater + go func() { + message.HandleSubscription( + message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "envoypatchpolicy-status"}, + r.resources.EnvoyPatchPolicyStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *v1alpha1.EnvoyPatchPolicyStatus], errChan chan error) { + // skip delete updates. + if update.Delete { + return + } + key := update.Key + val := update.Value + r.statusUpdater.Send(status.Update{ + NamespacedName: key, + Resource: new(v1alpha1.EnvoyPatchPolicy), + Mutator: status.MutatorFunc(func(obj client.Object) client.Object { + t, ok := obj.(*v1alpha1.EnvoyPatchPolicy) + if !ok { + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) + } + tCopy := t.DeepCopy() + tCopy.Status = *val + return tCopy + }), + }) + }, + ) + r.log.Info("envoyPatchPolicy status subscriber shutting down") + }() + + // ClientTrafficPolicy object status updater + go func() { + message.HandleSubscription( + message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "clienttrafficpolicy-status"}, + r.resources.ClientTrafficPolicyStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *v1alpha1.ClientTrafficPolicyStatus], errChan chan error) { + // skip delete updates. + if update.Delete { + return + } + key := update.Key + val := update.Value + r.statusUpdater.Send(status.Update{ + NamespacedName: key, + Resource: new(v1alpha1.ClientTrafficPolicy), + Mutator: status.MutatorFunc(func(obj client.Object) client.Object { + t, ok := obj.(*v1alpha1.ClientTrafficPolicy) + if !ok { + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) + } + tCopy := t.DeepCopy() + tCopy.Status = *val + return tCopy + }), + }) + }, + ) + r.log.Info("clientTrafficPolicy status subscriber shutting down") + }() + + // BackendTrafficPolicy object status updater + go func() { + message.HandleSubscription( + message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "backendtrafficpolicy-status"}, + r.resources.BackendTrafficPolicyStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *v1alpha1.BackendTrafficPolicyStatus], errChan chan error) { + // skip delete updates. + if update.Delete { + return + } + key := update.Key + val := update.Value + r.statusUpdater.Send(status.Update{ + NamespacedName: key, + Resource: new(v1alpha1.BackendTrafficPolicy), + Mutator: status.MutatorFunc(func(obj client.Object) client.Object { + t, ok := obj.(*v1alpha1.BackendTrafficPolicy) + if !ok { + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) + } + tCopy := t.DeepCopy() + tCopy.Status = *val + return tCopy + }), + }) + }, + ) + r.log.Info("backendTrafficPolicy status subscriber shutting down") + }() + + // SecurityPolicy object status updater + go func() { + message.HandleSubscription( + message.Metadata{Runner: string(v1alpha1.LogComponentProviderRunner), Message: "securitypolicy-status"}, + r.resources.SecurityPolicyStatuses.Subscribe(ctx), + func(update message.Update[types.NamespacedName, *v1alpha1.SecurityPolicyStatus], errChan chan error) { + // skip delete updates. + if update.Delete { + return + } + key := update.Key + val := update.Value + r.statusUpdater.Send(status.Update{ + NamespacedName: key, + Resource: new(v1alpha1.SecurityPolicy), + Mutator: status.MutatorFunc(func(obj client.Object) client.Object { + t, ok := obj.(*v1alpha1.SecurityPolicy) + if !ok { + err := fmt.Errorf("unsupported object type %T", obj) + errChan <- err + panic(err) + } + tCopy := t.DeepCopy() + tCopy.Status = *val + return tCopy + }), + }) + }, + ) + r.log.Info("securityPolicy status subscriber shutting down") + }() +} + +func (r *gatewayAPIReconciler) updateStatusForGateway(ctx context.Context, gtw *gwapiv1.Gateway) { + // nil check for unit tests. + if r.statusUpdater == nil { + return + } + + // Get deployment + deploy, err := r.envoyDeploymentForGateway(ctx, gtw) + if err != nil { + r.log.Info("failed to get Deployment for gateway", + "namespace", gtw.Namespace, "name", gtw.Name) + } + + // Get service + svc, err := r.envoyServiceForGateway(ctx, gtw) + if err != nil { + r.log.Info("failed to get Service for gateway", + "namespace", gtw.Namespace, "name", gtw.Name) + } + // update accepted condition + status.UpdateGatewayStatusAcceptedCondition(gtw, true) + // update address field and programmed condition + status.UpdateGatewayStatusProgrammedCondition(gtw, svc, deploy, r.store.listNodeAddresses()...) + + key := utils.NamespacedName(gtw) + + // publish status + r.statusUpdater.Send(status.Update{ + NamespacedName: key, + Resource: new(gwapiv1.Gateway), + Mutator: status.MutatorFunc(func(obj client.Object) client.Object { + g, ok := obj.(*gwapiv1.Gateway) + if !ok { + panic(fmt.Sprintf("unsupported object type %T", obj)) + } + gCopy := g.DeepCopy() + gCopy.Status.Conditions = gtw.Status.Conditions + gCopy.Status.Addresses = gtw.Status.Addresses + gCopy.Status.Listeners = gtw.Status.Listeners + return gCopy + }), + }) +} + +func (r *gatewayAPIReconciler) updateStatusForGatewayClass( + ctx context.Context, + gc *gwapiv1.GatewayClass, + accepted bool, + reason, + msg string) error { + if r.statusUpdater != nil { + r.statusUpdater.Send(status.Update{ + NamespacedName: types.NamespacedName{Name: gc.Name}, + Resource: &gwapiv1.GatewayClass{}, + Mutator: status.MutatorFunc(func(obj client.Object) client.Object { + gc, ok := obj.(*gwapiv1.GatewayClass) + if !ok { + panic(fmt.Sprintf("unsupported object type %T", obj)) + } + + return status.SetGatewayClassAccepted(gc.DeepCopy(), accepted, reason, msg) + }), + }) + } else { + // this branch makes testing easier by not going through the status.Updater. + duplicate := status.SetGatewayClassAccepted(gc.DeepCopy(), accepted, reason, msg) + + if err := r.client.Status().Update(ctx, duplicate); err != nil && !kerrors.IsNotFound(err) { + return fmt.Errorf("error updating status of gatewayclass %s: %w", duplicate.Name, err) + } + } + return nil +} diff --git a/internal/status/gateway.go b/internal/status/gateway.go index b7245c206aa..b62dffe66d4 100644 --- a/internal/status/gateway.go +++ b/internal/status/gateway.go @@ -28,10 +28,12 @@ func UpdateGatewayStatusProgrammedCondition(gw *gwapiv1.Gateway, svc *corev1.Ser // If the addresses is explicitly set in the Gateway spec by the user, use it // to populate the Status if len(gw.Spec.Addresses) > 0 { - // Make sure the addresses have been populated into ExternalIPs + // Make sure the addresses have been populated into ExternalIPs/ClusterIPs // and use that value 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...) } } else { if svc.Spec.Type == corev1.ServiceTypeLoadBalancer { diff --git a/internal/utils/env/env_test.go b/internal/utils/env/env_test.go index 357b69ef4d6..75fe60e2d0e 100644 --- a/internal/utils/env/env_test.go +++ b/internal/utils/env/env_test.go @@ -19,15 +19,15 @@ func TestLookupString(t *testing.T) { defer os.Clearenv() got := Lookup("TEST_ENV_KEY", "DEFAULT_ENV_VALUE") - require.Equal(t, got, "DEFAULT_ENV_VALUE") + require.Equal(t, "DEFAULT_ENV_VALUE", got) os.Setenv("TEST_ENV_KEY", "SET_ENV_VALUE") got = Lookup("TEST_ENV_KEY", "DEFAULT_ENV_VALUE") - require.Equal(t, got, "SET_ENV_VALUE") + require.Equal(t, "SET_ENV_VALUE", got) os.Clearenv() got = Lookup("TEST_ENV_KEY", "DEFAULT_ENV_VALUE") - require.Equal(t, got, "DEFAULT_ENV_VALUE") + require.Equal(t, "DEFAULT_ENV_VALUE", got) } func TestLookupInt(t *testing.T) { @@ -42,7 +42,7 @@ func TestLookupInt(t *testing.T) { os.Setenv("TEST_ENV_KEY", "1000") got = Lookup("TEST_ENV_KEY", i) - require.Equal(t, got, 1000) + require.Equal(t, 1000, got) os.Clearenv() got = Lookup("TEST_ENV_KEY", i) @@ -63,7 +63,7 @@ func TestLookupDuration(t *testing.T) { os.Setenv("TEST_ENV_KEY", "10s") got = Lookup("TEST_ENV_KEY", d) - require.Equal(t, got, time.Second*10) + require.Equal(t, time.Second*10, got) os.Clearenv() got = Lookup("TEST_ENV_KEY", d) diff --git a/internal/xds/bootstrap/bootstrap.yaml.tpl b/internal/xds/bootstrap/bootstrap.yaml.tpl index 56d0552f91c..b1b97905ecd 100644 --- a/internal/xds/bootstrap/bootstrap.yaml.tpl +++ b/internal/xds/bootstrap/bootstrap.yaml.tpl @@ -33,6 +33,8 @@ layered_runtime: - 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 diff --git a/internal/xds/bootstrap/bootstrap_test.go b/internal/xds/bootstrap/bootstrap_test.go index 6cb0ed31469..e57708b95ac 100644 --- a/internal/xds/bootstrap/bootstrap_test.go +++ b/internal/xds/bootstrap/bootstrap_test.go @@ -12,6 +12,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "k8s.io/utils/ptr" egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" @@ -85,9 +86,9 @@ func TestGetRenderedBootstrapConfig(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { got, err := GetRenderedBootstrapConfig(tc.proxyMetrics) - assert.NoError(t, err) + require.NoError(t, err) expected, err := readTestData(tc.name) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, expected, got) }) } diff --git a/internal/xds/bootstrap/testdata/custom-stats-matcher.yaml b/internal/xds/bootstrap/testdata/custom-stats-matcher.yaml index 58294aed4dd..3fbbaf4d63c 100644 --- a/internal/xds/bootstrap/testdata/custom-stats-matcher.yaml +++ b/internal/xds/bootstrap/testdata/custom-stats-matcher.yaml @@ -24,6 +24,8 @@ layered_runtime: - 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 diff --git a/internal/xds/bootstrap/testdata/disable-prometheus.yaml b/internal/xds/bootstrap/testdata/disable-prometheus.yaml index f6933c0de77..880f16cc5d8 100644 --- a/internal/xds/bootstrap/testdata/disable-prometheus.yaml +++ b/internal/xds/bootstrap/testdata/disable-prometheus.yaml @@ -13,6 +13,8 @@ layered_runtime: - 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 diff --git a/internal/xds/bootstrap/testdata/enable-prometheus.yaml b/internal/xds/bootstrap/testdata/enable-prometheus.yaml index 80160bf08dd..1830842ff58 100644 --- a/internal/xds/bootstrap/testdata/enable-prometheus.yaml +++ b/internal/xds/bootstrap/testdata/enable-prometheus.yaml @@ -13,6 +13,8 @@ layered_runtime: - 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 diff --git a/internal/xds/bootstrap/testdata/otel-metrics.yaml b/internal/xds/bootstrap/testdata/otel-metrics.yaml index d54047a6871..54e0a9d806e 100644 --- a/internal/xds/bootstrap/testdata/otel-metrics.yaml +++ b/internal/xds/bootstrap/testdata/otel-metrics.yaml @@ -13,6 +13,8 @@ layered_runtime: - 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 diff --git a/internal/xds/filters/wellknown.go b/internal/xds/filters/wellknown.go index 3ac7861edab..e6f01090781 100644 --- a/internal/xds/filters/wellknown.go +++ b/internal/xds/filters/wellknown.go @@ -36,12 +36,12 @@ var ( } ) -func GenerateRouterFilter(suppressEnvoyHeaders bool) *hcm.HttpFilter { +func GenerateRouterFilter(enableEnvoyHeaders bool) *hcm.HttpFilter { return &hcm.HttpFilter{ Name: wellknown.Router, ConfigType: &hcm.HttpFilter_TypedConfig{ TypedConfig: protocov.ToAny(&httprouter.Router{ - SuppressEnvoyHeaders: suppressEnvoyHeaders, + SuppressEnvoyHeaders: !enableEnvoyHeaders, }), }, } diff --git a/internal/xds/server/runner/runner.go b/internal/xds/server/runner/runner.go index bb18976932f..28c203a8634 100644 --- a/internal/xds/server/runner/runner.go +++ b/internal/xds/server/runner/runner.go @@ -83,7 +83,7 @@ func (r *Runner) Start(ctx context.Context) (err error) { PermitWithoutStream: true, })) - r.cache = cache.NewSnapshotCache(false, r.Logger) + r.cache = cache.NewSnapshotCache(true, r.Logger) registerServer(serverv3.NewServer(ctx, r.cache, r.cache), r.grpc) // Start and listen xDS gRPC Server. diff --git a/internal/xds/server/runner/runner_test.go b/internal/xds/server/runner/runner_test.go index b86b9760345..ced3aa20bbb 100644 --- a/internal/xds/server/runner/runner_test.go +++ b/internal/xds/server/runner/runner_test.go @@ -144,7 +144,7 @@ func TestTLSConfig(t *testing.T) { } if err == nil { expectedCert, _ := tc.serverCredentials.X509Certificate() - assert.Equal(t, receivedCert, &expectedCert) + assert.Equal(t, &expectedCert, receivedCert) } }) } @@ -193,7 +193,7 @@ func TestServeXdsServerListenFailed(t *testing.T) { // Occupy the address to make listening failed addr := net.JoinHostPort(XdsServerAddress, strconv.Itoa(bootstrap.DefaultXdsServerPort)) l, err := net.Listen("tcp", addr) - assert.Nil(t, err) + require.NoError(t, err) defer l.Close() cfg, _ := config.New() diff --git a/internal/xds/translator/basicauth.go b/internal/xds/translator/basicauth.go index a7af38551c7..c9658cfe82b 100644 --- a/internal/xds/translator/basicauth.go +++ b/internal/xds/translator/basicauth.go @@ -7,13 +7,11 @@ package translator import ( "errors" - "fmt" corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" routev3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" basicauthv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/basic_auth/v3" hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" - "github.com/tetratelabs/multierror" "google.golang.org/protobuf/types/known/anypb" "github.com/envoyproxy/gateway/internal/ir" @@ -36,6 +34,7 @@ var _ httpFilter = &basicAuth{} // patchHCM builds and appends the basic_auth Filters to the HTTP Connection Manager // if applicable, and it does not already exist. // Note: this method creates an basic_auth filter for each route that contains an BasicAuth config. +// The filter is disabled by default. It is enabled on the route level. func (*basicAuth) patchHCM(mgr *hcmv3.HttpConnectionManager, irListener *ir.HTTPListener) error { var errs error @@ -54,17 +53,10 @@ func (*basicAuth) patchHCM(mgr *hcmv3.HttpConnectionManager, irListener *ir.HTTP filter, err := buildHCMBasicAuthFilter(route) if err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) continue } - // skip if the filter already exists - for _, existingFilter := range mgr.HttpFilters { - if filter.Name == existingFilter.Name { - continue - } - } - mgr.HttpFilters = append(mgr.HttpFilters, filter) } @@ -85,7 +77,8 @@ func buildHCMBasicAuthFilter(route *ir.HTTPRoute) (*hcmv3.HttpFilter, error) { } return &hcmv3.HttpFilter{ - Name: basicAuthFilterName(route), + Name: basicAuthFilterName(route), + Disabled: true, ConfigType: &hcmv3.HttpFilter_TypedConfig{ TypedConfig: basicAuthAny, }, @@ -124,52 +117,6 @@ func (*basicAuth) patchResources(*types.ResourceVersionTable, []*ir.HTTPRoute) e return nil } -// patchRouteCfg patches the provided route configuration with the basicAuth filter -// if applicable. -// Note: this method disables all the basicAuth filters by default. The filter will -// be enabled per-route in the typePerFilterConfig of the route. -func (*basicAuth) patchRouteConfig(routeCfg *routev3.RouteConfiguration, irListener *ir.HTTPListener) error { - if routeCfg == nil { - return errors.New("route configuration is nil") - } - if irListener == nil { - return errors.New("ir listener is nil") - } - - var errs error - for _, route := range irListener.Routes { - if !routeContainsBasicAuth(route) { - continue - } - - filterName := basicAuthFilterName(route) - filterCfg := routeCfg.TypedPerFilterConfig - - if _, ok := filterCfg[filterName]; ok { - // This should not happen since this is the only place where the basicAuth - // filter is added in a route. - errs = multierror.Append(errs, fmt.Errorf( - "route config already contains basicAuth config: %+v", route)) - continue - } - - // Disable all the filters by default. The filter will be enabled - // per-route in the typePerFilterConfig of the route. - routeCfgAny, err := anypb.New(&routev3.FilterConfig{Disabled: true}) - if err != nil { - errs = multierror.Append(errs, err) - continue - } - - if filterCfg == nil { - routeCfg.TypedPerFilterConfig = make(map[string]*anypb.Any) - } - - routeCfg.TypedPerFilterConfig[filterName] = routeCfgAny - } - return errs -} - // patchRoute patches the provided route with the basicAuth config if applicable. // Note: this method enables the corresponding basicAuth filter for the provided route. func (*basicAuth) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) error { diff --git a/internal/xds/translator/cluster.go b/internal/xds/translator/cluster.go index 58e6641c667..3b2dee97941 100644 --- a/internal/xds/translator/cluster.go +++ b/internal/xds/translator/cluster.go @@ -14,6 +14,7 @@ import ( clusterv3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" endpointv3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" + preservecasev3 "github.com/envoyproxy/go-control-plane/envoy/extensions/http/header_formatters/preserve_case/v3" proxyprotocolv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/proxy_protocol/v3" rawbufferv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/raw_buffer/v3" httpv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/http/v3" @@ -23,6 +24,7 @@ import ( "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/wrapperspb" + "k8s.io/utils/ptr" "github.com/envoyproxy/gateway/internal/ir" ) @@ -31,6 +33,7 @@ const ( extensionOptionsKey = "envoy.extensions.upstreams.http.v3.HttpProtocolOptions" // https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto#envoy-v3-api-field-config-cluster-v3-cluster-per-connection-buffer-limit-bytes tcpClusterPerConnectionBufferLimitBytes = 32768 + tcpClusterPerConnectTimeout = 10 * time.Second ) type xdsClusterArgs struct { @@ -42,6 +45,9 @@ type xdsClusterArgs struct { proxyProtocol *ir.ProxyProtocol circuitBreaker *ir.CircuitBreaker healthCheck *ir.HealthCheck + http1Settings *ir.HTTP1Settings + timeout *ir.Timeout + tcpkeepalive *ir.TCPKeepalive } type EndpointType int @@ -54,7 +60,6 @@ const ( func buildXdsCluster(args *xdsClusterArgs) *clusterv3.Cluster { cluster := &clusterv3.Cluster{ Name: args.name, - ConnectTimeout: durationpb.New(10 * time.Second), DnsLookupFamily: clusterv3.Cluster_V4_ONLY, CommonLbConfig: &clusterv3.Cluster_CommonLbConfig{ LocalityConfigSpecifier: &clusterv3.Cluster_CommonLbConfig_LocalityWeightedLbConfig_{ @@ -63,6 +68,8 @@ func buildXdsCluster(args *xdsClusterArgs) *clusterv3.Cluster { PerConnectionBufferLimitBytes: wrapperspb.UInt32(tcpClusterPerConnectionBufferLimitBytes), } + cluster.ConnectTimeout = buildConnectTimeout(args.timeout) + // Set Proxy Protocol if args.proxyProtocol != nil { cluster.TransportSocket = buildProxyProtocolSocket(args.proxyProtocol, args.tSocket) @@ -87,16 +94,10 @@ func buildXdsCluster(args *xdsClusterArgs) *clusterv3.Cluster { cluster.RespectDnsTtl = true } - isHTTP2 := false - for _, ds := range args.settings { - if ds.Protocol == ir.GRPC || - ds.Protocol == ir.HTTP2 { - isHTTP2 = true - break - } - } - if isHTTP2 { - cluster.TypedExtensionProtocolOptions = buildTypedExtensionProtocolOptions() + // build common, HTTP/1 and HTTP/2 protocol options for cluster + epo := buildTypedExtensionProtocolOptions(args) + if epo != nil { + cluster.TypedExtensionProtocolOptions = epo } // Set Load Balancer policy @@ -135,50 +136,89 @@ func buildXdsCluster(args *xdsClusterArgs) *clusterv3.Cluster { cluster.LbPolicy = clusterv3.Cluster_MAGLEV } - if args.healthCheck != nil { - hc := &corev3.HealthCheck{ - Timeout: durationpb.New(args.healthCheck.Timeout.Duration), - Interval: durationpb.New(args.healthCheck.Interval.Duration), + if args.healthCheck != nil && args.healthCheck.Active != nil { + cluster.HealthChecks = buildXdsHealthCheck(args.healthCheck.Active) + } + + if args.healthCheck != nil && args.healthCheck.Passive != nil { + cluster.OutlierDetection = buildXdsOutlierDetection(args.healthCheck.Passive) + + } + if args.circuitBreaker != nil { + cluster.CircuitBreakers = buildXdsClusterCircuitBreaker(args.circuitBreaker) + } + if args.tcpkeepalive != nil { + cluster.UpstreamConnectionOptions = buildXdsClusterUpstreamOptions(args.tcpkeepalive) + } + return cluster +} + +func buildXdsHealthCheck(healthcheck *ir.ActiveHealthCheck) []*corev3.HealthCheck { + hc := &corev3.HealthCheck{ + Timeout: durationpb.New(healthcheck.Timeout.Duration), + Interval: durationpb.New(healthcheck.Interval.Duration), + } + if healthcheck.UnhealthyThreshold != nil { + hc.UnhealthyThreshold = wrapperspb.UInt32(*healthcheck.UnhealthyThreshold) + } + if healthcheck.HealthyThreshold != nil { + hc.HealthyThreshold = wrapperspb.UInt32(*healthcheck.HealthyThreshold) + } + if healthcheck.HTTP != nil { + httpChecker := &corev3.HealthCheck_HttpHealthCheck{ + Path: healthcheck.HTTP.Path, } - if args.healthCheck.UnhealthyThreshold != nil { - hc.UnhealthyThreshold = wrapperspb.UInt32(*args.healthCheck.UnhealthyThreshold) + if healthcheck.HTTP.Method != nil { + httpChecker.Method = corev3.RequestMethod(corev3.RequestMethod_value[*healthcheck.HTTP.Method]) } - if args.healthCheck.HealthyThreshold != nil { - hc.HealthyThreshold = wrapperspb.UInt32(*args.healthCheck.HealthyThreshold) + httpChecker.ExpectedStatuses = buildHTTPStatusRange(healthcheck.HTTP.ExpectedStatuses) + if receive := buildHealthCheckPayload(healthcheck.HTTP.ExpectedResponse); receive != nil { + httpChecker.Receive = append(httpChecker.Receive, receive) } - if args.healthCheck.HTTP != nil { - httpChecker := &corev3.HealthCheck_HttpHealthCheck{ - Path: args.healthCheck.HTTP.Path, - } - if args.healthCheck.HTTP.Method != nil { - httpChecker.Method = corev3.RequestMethod(corev3.RequestMethod_value[*args.healthCheck.HTTP.Method]) - } - httpChecker.ExpectedStatuses = buildHTTPStatusRange(args.healthCheck.HTTP.ExpectedStatuses) - if receive := buildHealthCheckPayload(args.healthCheck.HTTP.ExpectedResponse); receive != nil { - httpChecker.Receive = append(httpChecker.Receive, receive) - } - hc.HealthChecker = &corev3.HealthCheck_HttpHealthCheck_{ - HttpHealthCheck: httpChecker, - } + hc.HealthChecker = &corev3.HealthCheck_HttpHealthCheck_{ + HttpHealthCheck: httpChecker, } - if args.healthCheck.TCP != nil { - tcpChecker := &corev3.HealthCheck_TcpHealthCheck{ - Send: buildHealthCheckPayload(args.healthCheck.TCP.Send), - } - if receive := buildHealthCheckPayload(args.healthCheck.TCP.Receive); receive != nil { - tcpChecker.Receive = append(tcpChecker.Receive, receive) - } - hc.HealthChecker = &corev3.HealthCheck_TcpHealthCheck_{ - TcpHealthCheck: tcpChecker, - } + } + if healthcheck.TCP != nil { + tcpChecker := &corev3.HealthCheck_TcpHealthCheck{ + Send: buildHealthCheckPayload(healthcheck.TCP.Send), + } + if receive := buildHealthCheckPayload(healthcheck.TCP.Receive); receive != nil { + tcpChecker.Receive = append(tcpChecker.Receive, receive) + } + hc.HealthChecker = &corev3.HealthCheck_TcpHealthCheck_{ + TcpHealthCheck: tcpChecker, } - cluster.HealthChecks = []*corev3.HealthCheck{hc} } - if args.circuitBreaker != nil { - cluster.CircuitBreakers = buildXdsClusterCircuitBreaker(args.circuitBreaker) + return []*corev3.HealthCheck{hc} +} + +func buildXdsOutlierDetection(outlierDetection *ir.OutlierDetection) *clusterv3.OutlierDetection { + od := &clusterv3.OutlierDetection{ + BaseEjectionTime: durationpb.New(outlierDetection.BaseEjectionTime.Duration), + Interval: durationpb.New(outlierDetection.Interval.Duration), + } + if outlierDetection.SplitExternalLocalOriginErrors != nil { + od.SplitExternalLocalOriginErrors = *outlierDetection.SplitExternalLocalOriginErrors } - return cluster + if outlierDetection.MaxEjectionPercent != nil && *outlierDetection.MaxEjectionPercent > 0 { + od.MaxEjectionPercent = wrapperspb.UInt32(uint32(*outlierDetection.MaxEjectionPercent)) + } + + if outlierDetection.ConsecutiveLocalOriginFailures != nil { + od.ConsecutiveLocalOriginFailure = wrapperspb.UInt32(*outlierDetection.ConsecutiveLocalOriginFailures) + } + + if outlierDetection.Consecutive5xxErrors != nil { + od.Consecutive_5Xx = wrapperspb.UInt32(*outlierDetection.Consecutive5xxErrors) + } + + if outlierDetection.ConsecutiveGatewayErrors != nil { + od.ConsecutiveGatewayFailure = wrapperspb.UInt32(*outlierDetection.ConsecutiveGatewayErrors) + } + + return od } // buildHTTPStatusRange converts an array of http status to an array of the range of http status. @@ -315,13 +355,95 @@ func buildXdsClusterLoadAssignment(clusterName string, destSettings []*ir.Destin return &endpointv3.ClusterLoadAssignment{ClusterName: clusterName, Endpoints: localities} } -func buildTypedExtensionProtocolOptions() map[string]*anypb.Any { - protocolOptions := httpv3.HttpProtocolOptions{ - UpstreamProtocolOptions: &httpv3.HttpProtocolOptions_ExplicitHttpConfig_{ +func buildTypedExtensionProtocolOptions(args *xdsClusterArgs) map[string]*anypb.Any { + requiresHTTP2Options := false + for _, ds := range args.settings { + if ds.Protocol == ir.GRPC || + ds.Protocol == ir.HTTP2 { + requiresHTTP2Options = true + break + } + } + + requiresCommonHTTPOptions := (args.timeout != nil && args.timeout.HTTP != nil && + (args.timeout.HTTP.MaxConnectionDuration != nil || args.timeout.HTTP.ConnectionIdleTimeout != nil)) || + (args.circuitBreaker != nil && args.circuitBreaker.MaxRequestsPerConnection != nil) + + requiresHTTP1Options := args.http1Settings != nil && (args.http1Settings.EnableTrailers || args.http1Settings.PreserveHeaderCase || args.http1Settings.HTTP10 != nil) + + if !(requiresCommonHTTPOptions || requiresHTTP1Options || requiresHTTP2Options) { + return nil + } + + protocolOptions := httpv3.HttpProtocolOptions{} + + if requiresCommonHTTPOptions { + protocolOptions.CommonHttpProtocolOptions = &corev3.HttpProtocolOptions{} + + if args.timeout != nil && args.timeout.HTTP != nil { + if args.timeout.HTTP.ConnectionIdleTimeout != nil { + protocolOptions.CommonHttpProtocolOptions.IdleTimeout = + durationpb.New(args.timeout.HTTP.ConnectionIdleTimeout.Duration) + } + + if args.timeout.HTTP.MaxConnectionDuration != nil { + protocolOptions.CommonHttpProtocolOptions.MaxConnectionDuration = + durationpb.New(args.timeout.HTTP.MaxConnectionDuration.Duration) + } + } + + if args.circuitBreaker != nil && args.circuitBreaker.MaxRequestsPerConnection != nil { + protocolOptions.CommonHttpProtocolOptions.MaxRequestsPerConnection = &wrapperspb.UInt32Value{ + Value: *args.circuitBreaker.MaxRequestsPerConnection, + } + } + + } + + // When setting any Typed Extension Protocol Options, UpstreamProtocolOptions are mandatory + // If translation requires HTTP2 enablement or HTTP1 trailers, set appropriate setting + // Default to http1 otherwise + // TODO: If the cluster is TLS enabled, use AutoHTTPConfig instead of ExplicitHttpConfig + // so that when ALPN is supported then enabling http1 options doesn't force HTTP/1.1 + switch { + case requiresHTTP2Options: + protocolOptions.UpstreamProtocolOptions = &httpv3.HttpProtocolOptions_ExplicitHttpConfig_{ ExplicitHttpConfig: &httpv3.HttpProtocolOptions_ExplicitHttpConfig{ ProtocolConfig: &httpv3.HttpProtocolOptions_ExplicitHttpConfig_Http2ProtocolOptions{}, }, - }, + } + case requiresHTTP1Options: + http1opts := &corev3.Http1ProtocolOptions{ + EnableTrailers: args.http1Settings.EnableTrailers, + } + if args.http1Settings.PreserveHeaderCase { + preservecaseAny, _ := anypb.New(&preservecasev3.PreserveCaseFormatterConfig{}) + http1opts.HeaderKeyFormat = &corev3.Http1ProtocolOptions_HeaderKeyFormat{ + HeaderFormat: &corev3.Http1ProtocolOptions_HeaderKeyFormat_StatefulFormatter{ + StatefulFormatter: &corev3.TypedExtensionConfig{ + Name: "preserve_case", + TypedConfig: preservecaseAny, + }, + }, + } + } + if args.http1Settings.HTTP10 != nil { + http1opts.AcceptHttp_10 = true + http1opts.DefaultHostForHttp_10 = ptr.Deref(args.http1Settings.HTTP10.DefaultHost, "") + } + protocolOptions.UpstreamProtocolOptions = &httpv3.HttpProtocolOptions_ExplicitHttpConfig_{ + ExplicitHttpConfig: &httpv3.HttpProtocolOptions_ExplicitHttpConfig{ + ProtocolConfig: &httpv3.HttpProtocolOptions_ExplicitHttpConfig_HttpProtocolOptions{ + HttpProtocolOptions: http1opts, + }, + }, + } + default: + protocolOptions.UpstreamProtocolOptions = &httpv3.HttpProtocolOptions_ExplicitHttpConfig_{ + ExplicitHttpConfig: &httpv3.HttpProtocolOptions_ExplicitHttpConfig{ + ProtocolConfig: &httpv3.HttpProtocolOptions_ExplicitHttpConfig_HttpProtocolOptions{}, + }, + } } anyProtocolOptions, _ := anypb.New(&protocolOptions) @@ -389,3 +511,35 @@ func buildProxyProtocolSocket(proxyProtocol *ir.ProxyProtocol, tSocket *corev3.T }, } } + +func buildConnectTimeout(to *ir.Timeout) *durationpb.Duration { + if to != nil && to.TCP != nil && to.TCP.ConnectTimeout != nil { + return durationpb.New(to.TCP.ConnectTimeout.Duration) + } + return durationpb.New(tcpClusterPerConnectTimeout) +} + +func buildXdsClusterUpstreamOptions(tcpkeepalive *ir.TCPKeepalive) *clusterv3.UpstreamConnectionOptions { + if tcpkeepalive == nil { + return nil + } + + ka := &clusterv3.UpstreamConnectionOptions{ + TcpKeepalive: &corev3.TcpKeepalive{}, + } + + if tcpkeepalive.Probes != nil { + ka.TcpKeepalive.KeepaliveProbes = wrapperspb.UInt32(*tcpkeepalive.Probes) + } + + if tcpkeepalive.Probes != nil { + ka.TcpKeepalive.KeepaliveTime = wrapperspb.UInt32(*tcpkeepalive.IdleTime) + } + + if tcpkeepalive.Interval != nil { + ka.TcpKeepalive.KeepaliveInterval = wrapperspb.UInt32(*tcpkeepalive.Interval) + } + + return ka + +} diff --git a/internal/xds/translator/cors.go b/internal/xds/translator/cors.go index a7fe606d03e..ef8c6d8ddc6 100644 --- a/internal/xds/translator/cors.go +++ b/internal/xds/translator/cors.go @@ -165,10 +165,6 @@ func (*cors) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) error { return nil } -func (*cors) patchRouteConfig(*routev3.RouteConfiguration, *ir.HTTPListener) error { - return nil -} - func (c *cors) patchResources(*types.ResourceVersionTable, []*ir.HTTPRoute) error { return nil } diff --git a/internal/xds/translator/extauth.go b/internal/xds/translator/extauth.go new file mode 100644 index 00000000000..57536a3c20d --- /dev/null +++ b/internal/xds/translator/extauth.go @@ -0,0 +1,264 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package translator + +import ( + "errors" + "net/url" + + corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" + routev3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" + extauthv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_authz/v3" + hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" + matcherv3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" + "github.com/golang/protobuf/ptypes/duration" + "google.golang.org/protobuf/types/known/anypb" + + "github.com/envoyproxy/gateway/internal/ir" + "github.com/envoyproxy/gateway/internal/xds/types" +) + +const ( + extAuthFilter = "envoy.filters.http.ext_authz" +) + +func init() { + registerHTTPFilter(&extAuth{}) +} + +type extAuth struct { +} + +var _ httpFilter = &extAuth{} + +// patchHCM builds and appends the ext_authz Filters to the HTTP Connection Manager +// if applicable, and it does not already exist. +// Note: this method creates an ext_authz filter for each route that contains an ExtAuthz config. +// The filter is disabled by default. It is enabled on the route level. +// TODO: zhaohuabing avoid duplicated HTTP filters +func (*extAuth) patchHCM(mgr *hcmv3.HttpConnectionManager, irListener *ir.HTTPListener) error { + var errs error + + if mgr == nil { + return errors.New("hcm is nil") + } + + if irListener == nil { + return errors.New("ir listener is nil") + } + + for _, route := range irListener.Routes { + if !routeContainsExtAuth(route) { + continue + } + + filter, err := buildHCMExtAuthFilter(route) + if err != nil { + errs = errors.Join(errs, err) + continue + } + + mgr.HttpFilters = append(mgr.HttpFilters, filter) + } + + return nil +} + +// buildHCMExtAuthFilter returns an ext_authz HTTP filter from the provided IR HTTPRoute. +func buildHCMExtAuthFilter(route *ir.HTTPRoute) (*hcmv3.HttpFilter, error) { + extAuthProto := extAuthConfig(route.ExtAuth) + if err := extAuthProto.ValidateAll(); err != nil { + return nil, err + } + + extAuthAny, err := anypb.New(extAuthProto) + if err != nil { + return nil, err + } + + return &hcmv3.HttpFilter{ + Name: extAuthFilterName(route), + Disabled: true, + ConfigType: &hcmv3.HttpFilter_TypedConfig{ + TypedConfig: extAuthAny, + }, + }, nil +} + +func extAuthFilterName(route *ir.HTTPRoute) string { + return perRouteFilterName(extAuthFilter, route.Name) +} + +func extAuthConfig(extAuth *ir.ExtAuth) *extauthv3.ExtAuthz { + config := &extauthv3.ExtAuthz{} + + var headersToExtAuth []*matcherv3.StringMatcher + for _, header := range extAuth.HeadersToExtAuth { + headersToExtAuth = append(headersToExtAuth, &matcherv3.StringMatcher{ + MatchPattern: &matcherv3.StringMatcher_Exact{ + Exact: header, + }, + }) + } + + if len(headersToExtAuth) > 0 { + config.AllowedHeaders = &matcherv3.ListStringMatcher{ + Patterns: headersToExtAuth, + } + } + + if extAuth.HTTP != nil { + config.Services = &extauthv3.ExtAuthz_HttpService{ + HttpService: httpService(extAuth.HTTP), + } + } else if extAuth.GRPC != nil { + config.Services = &extauthv3.ExtAuthz_GrpcService{ + GrpcService: &corev3.GrpcService{ + TargetSpecifier: &corev3.GrpcService_EnvoyGrpc_{ + EnvoyGrpc: grpcService(extAuth.GRPC), + }, + Timeout: &duration.Duration{ + Seconds: defaultExtServiceRequestTimeout, + }, + }, + } + } + + return config +} + +func httpService(http *ir.HTTPExtAuthService) *extauthv3.HttpService { + var ( + uri string + headersToBackend []*matcherv3.StringMatcher + ) + + u := url.URL{ + // scheme should be decided by the TLS setting, but we don't have that info now. + // It's safe to set it to http because the ext auth filter doesn't use the + // uri to make the request. It only uses the cluster. + Scheme: "http", + Host: http.Authority, + Path: http.Path, + } + uri = u.String() + + for _, header := range http.HeadersToBackend { + headersToBackend = append(headersToBackend, &matcherv3.StringMatcher{ + MatchPattern: &matcherv3.StringMatcher_Exact{ + Exact: header, + }, + }) + } + + return &extauthv3.HttpService{ + ServerUri: &corev3.HttpUri{ + Uri: uri, + HttpUpstreamType: &corev3.HttpUri_Cluster{ + Cluster: http.Destination.Name, + }, + Timeout: &duration.Duration{ + Seconds: defaultExtServiceRequestTimeout, + }, + }, + AuthorizationResponse: &extauthv3.AuthorizationResponse{ + AllowedUpstreamHeaders: &matcherv3.ListStringMatcher{ + Patterns: headersToBackend, + }, + }, + } +} + +func grpcService(grpc *ir.GRPCExtAuthService) *corev3.GrpcService_EnvoyGrpc { + return &corev3.GrpcService_EnvoyGrpc{ + ClusterName: grpc.Destination.Name, + Authority: grpc.Authority, + } +} + +// routeContainsExtAuth returns true if ExtAuth exists for the provided route. +func routeContainsExtAuth(irRoute *ir.HTTPRoute) bool { + if irRoute == nil { + return false + } + + if irRoute != nil && + irRoute.ExtAuth != nil { + return true + } + + return false +} + +// patchResources patches the cluster resources for the external auth services. +func (*extAuth) patchResources(tCtx *types.ResourceVersionTable, + routes []*ir.HTTPRoute) error { + if tCtx == nil || tCtx.XdsResources == nil { + return errors.New("xds resource table is nil") + } + + var errs error + for _, route := range routes { + if !routeContainsExtAuth(route) { + continue + } + if route.ExtAuth.HTTP != nil { + if err := createExtServiceXDSCluster( + &route.ExtAuth.HTTP.Destination, tCtx); err != nil && !errors.Is( + err, ErrXdsClusterExists) { + errs = errors.Join(errs, err) + } + } else { + if err := createExtServiceXDSCluster( + &route.ExtAuth.GRPC.Destination, tCtx); err != nil && !errors.Is( + err, ErrXdsClusterExists) { + errs = errors.Join(errs, err) + } + } + } + + return errs +} + +func createExtServiceXDSCluster(rd *ir.RouteDestination, tCtx *types.ResourceVersionTable) error { + // Get the address type from the first setting. + // This is safe because no mixed address types in the settings. + addrTypeState := rd.Settings[0].AddressType + + var endpointType EndpointType + if addrTypeState != nil && *addrTypeState == ir.FQDN { + endpointType = EndpointTypeDNS + } else { + endpointType = EndpointTypeStatic + } + if err := addXdsCluster(tCtx, &xdsClusterArgs{ + name: rd.Name, + settings: rd.Settings, + tSocket: nil, + endpointType: endpointType, + }); err != nil && !errors.Is(err, ErrXdsClusterExists) { + return err + } + return nil +} + +// patchRoute patches the provided route with the extAuth config if applicable. +// Note: this method enables the corresponding extAuth filter for the provided route. +func (*extAuth) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) error { + if route == nil { + return errors.New("xds route is nil") + } + if irRoute == nil { + return errors.New("ir route is nil") + } + if irRoute.ExtAuth == nil { + return nil + } + if err := enableFilterOnRoute(extAuthFilter, route, irRoute); err != nil { + return err + } + return nil +} diff --git a/internal/xds/translator/fault.go b/internal/xds/translator/fault.go index 6fdf5008065..3b622097a66 100644 --- a/internal/xds/translator/fault.go +++ b/internal/xds/translator/fault.go @@ -121,10 +121,6 @@ func (*fault) patchResources(*types.ResourceVersionTable, []*ir.HTTPRoute) error return nil } -func (*fault) patchRouteConfig(routeCfg *routev3.RouteConfiguration, irListener *ir.HTTPListener) error { - return nil -} - // patchRoute patches the provided route with the fault config if applicable. // Note: this method enables the corresponding fault filter for the provided route. func (*fault) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) error { diff --git a/internal/xds/translator/httpfilters.go b/internal/xds/translator/httpfilters.go index 2b7193548ed..738e5ee9480 100644 --- a/internal/xds/translator/httpfilters.go +++ b/internal/xds/translator/httpfilters.go @@ -12,6 +12,7 @@ import ( routev3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" "github.com/envoyproxy/go-control-plane/pkg/wellknown" + "k8s.io/utils/ptr" "github.com/envoyproxy/gateway/internal/xds/filters" "github.com/envoyproxy/gateway/internal/xds/types" @@ -38,23 +39,18 @@ func registerHTTPFilter(filter httpFilter) { // - patchHCM: EG adds a filter for each route in the HCM filter chain, the // filter name is prefixed with the filter's type name, for example, // "envoy.filters.http.oauth2", and suffixed with the route name. Each filter -// is configured with the route's per-route configuration. -// - patchRouteConfig: EG disables all the filters of this type in the -// typedFilterConfig of the route config. +// is configured with the route's per-route configuration. The filter is +// disabled by default and is enabled on the route level. // - PatchRouteWithPerRouteConfig: EG enables the corresponding filter for each // route in the typedFilterConfig of that route. // -// The filter types that haven't native per-route support: oauth2, basic authn +// The filter types that haven't native per-route support: oauth2, basic authn, ext_authz. // Note: The filter types that have native per-route configuration support should // always se their own native per-route configuration. type httpFilter interface { // patchHCM patches the HttpConnectionManager with the filter. patchHCM(mgr *hcmv3.HttpConnectionManager, irListener *ir.HTTPListener) error - // patchRouteConfig patches the provided RouteConfiguration with a filter's - // RouteConfiguration level configuration. - patchRouteConfig(rc *routev3.RouteConfiguration, irListener *ir.HTTPListener) error - // patchRoute patches the provide Route with a filter's Route level configuration. patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) error @@ -91,18 +87,20 @@ func newOrderedHTTPFilter(filter *hcmv3.HttpFilter) *OrderedHTTPFilter { switch { case filter.Name == wellknown.CORS: order = 1 - case filter.Name == basicAuthFilter: + case isFilterType(filter, extAuthFilter): order = 2 - case isOAuth2Filter(filter): + case isFilterType(filter, basicAuthFilter): order = 3 - case filter.Name == jwtAuthn: + case isFilterType(filter, oauth2Filter): order = 4 - case filter.Name == wellknown.Fault: + case filter.Name == jwtAuthn: order = 5 - case filter.Name == localRateLimitFilter: + case filter.Name == wellknown.Fault: order = 6 - case filter.Name == wellknown.HTTPRateLimit: + case filter.Name == localRateLimitFilter: order = 7 + case filter.Name == wellknown.HTTPRateLimit: + order = 8 case filter.Name == wellknown.Router: order = 100 } @@ -168,30 +166,14 @@ func (t *Translator) patchHCMWithFilters( t.patchHCMWithRateLimit(mgr, irListener) // Add the router filter - mgr.HttpFilters = append(mgr.HttpFilters, filters.GenerateRouterFilter(irListener.SuppressEnvoyHeaders)) + headerSettings := ptr.Deref(irListener.Headers, ir.HeaderSettings{}) + mgr.HttpFilters = append(mgr.HttpFilters, filters.GenerateRouterFilter(headerSettings.EnableEnvoyHeaders)) // Sort the filters in the correct order. mgr.HttpFilters = sortHTTPFilters(mgr.HttpFilters) return nil } -// patchRouteCfgWithPerRouteConfig appends per-route filter configurations to the -// provided listener's RouteConfiguration. -// This method is used to disable the filters without native per-route support. -// The disabled filters will be enabled by route in the patchRouteWithPerRouteConfig -// method. -func patchRouteCfgWithPerRouteConfig( - routeCfg *routev3.RouteConfiguration, - irListener *ir.HTTPListener) error { - // Only supports the oauth2 filter for now, other filters will be added later. - for _, filter := range httpFilters { - if err := filter.patchRouteConfig(routeCfg, irListener); err != nil { - return err - } - } - return nil -} - // patchRouteWithPerRouteConfig appends per-route filter configuration to the // provided route. func patchRouteWithPerRouteConfig( @@ -214,11 +196,12 @@ func patchRouteWithPerRouteConfig( return nil } -// isOAuth2Filter returns true if the provided filter is an OAuth2 filter. -func isOAuth2Filter(filter *hcmv3.HttpFilter) bool { - // Multiple oauth2 filters are added to the HCM filter chain, one for each - // route. The oauth2 filter name is prefixed with "envoy.filters.http.oauth2". - return strings.HasPrefix(filter.Name, oauth2Filter) +// isFilterType returns true if the filter is the provided filter type. +func isFilterType(filter *hcmv3.HttpFilter, filterType string) bool { + // Multiple filters of the same types are added to the HCM filter chain, one for each + // route. The filter name is prefixed with the filter type, for example: + // "envoy.filters.http.oauth2_first-route". + return strings.HasPrefix(filter.Name, filterType) } // patchResources adds all the other needed resources referenced by this diff --git a/internal/xds/translator/httpfilters_test.go b/internal/xds/translator/httpfilters_test.go index 07c78cda323..c23f681efd8 100644 --- a/internal/xds/translator/httpfilters_test.go +++ b/internal/xds/translator/httpfilters_test.go @@ -25,11 +25,17 @@ func Test_sortHTTPFilters(t *testing.T) { httpFilterForTest(wellknown.Router), httpFilterForTest(wellknown.CORS), httpFilterForTest(jwtAuthn), + httpFilterForTest(oauth2Filter + "-route1"), + httpFilterForTest(basicAuthFilter + "-route1"), httpFilterForTest(wellknown.HTTPRateLimit), httpFilterForTest(wellknown.Fault), + httpFilterForTest(extAuthFilter + "-route1"), }, want: []*hcmv3.HttpFilter{ httpFilterForTest(wellknown.CORS), + httpFilterForTest(extAuthFilter + "-route1"), + httpFilterForTest(basicAuthFilter + "-route1"), + httpFilterForTest(oauth2Filter + "-route1"), httpFilterForTest(jwtAuthn), httpFilterForTest(wellknown.Fault), httpFilterForTest(wellknown.HTTPRateLimit), diff --git a/internal/xds/translator/jsonpatch.go b/internal/xds/translator/jsonpatch.go index c57e0010874..62638e78c69 100644 --- a/internal/xds/translator/jsonpatch.go +++ b/internal/xds/translator/jsonpatch.go @@ -6,6 +6,7 @@ package translator import ( + "errors" "fmt" "strings" @@ -13,9 +14,9 @@ import ( endpointv3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" listenerv3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" routev3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" + tlsv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" resourcev3 "github.com/envoyproxy/go-control-plane/pkg/resource/v3" jsonpatchv5 "github.com/evanphx/json-patch/v5" - "github.com/tetratelabs/multierror" "google.golang.org/protobuf/encoding/protojson" "sigs.k8s.io/yaml" @@ -26,8 +27,12 @@ import ( ) const ( - AddOperation = "add" - EmptyPath = "" + AddOperation = "add" + RemoveOperation = "remove" + ReplaceOperation = "replace" + CopyOperation = "copy" + MoveOperation = "move" + EmptyPath = "" ) // processJSONPatches applies each JSONPatch to the Xds Resources for a specific type. @@ -45,10 +50,26 @@ func processJSONPatches(tCtx *types.ResourceVersionTable, envoyPatchPolicies []* routeConfig *routev3.RouteConfiguration cluster *clusterv3.Cluster endpoint *endpointv3.ClusterLoadAssignment + secret *tlsv3.Secret resourceJSON []byte err error ) + switch p.Operation.Op { + case AddOperation, ReplaceOperation: + if p.Operation.Value == nil { + msg := fmt.Sprintf("The %s operation requires a value", p.Operation.Op) + status.SetEnvoyPatchPolicyInvalid(e.Status, msg) + continue + } + default: + if p.Operation.Value != nil { + msg := fmt.Sprintf("The value field can not be set for the %s operation", p.Operation.Op) + status.SetEnvoyPatchPolicyInvalid(e.Status, msg) + continue + } + } + // If Path is "" and op is "add", unmarshal and add the patch as a complete // resource if p.Operation.Op == AddOperation && p.Operation.Path == EmptyPath { @@ -118,6 +139,18 @@ func processJSONPatches(tCtx *types.ResourceVersionTable, envoyPatchPolicies []* status.SetEnvoyPatchPolicyInvalid(e.Status, msg) continue } + case string(resourcev3.SecretType): + temp := &tlsv3.Secret{} + if err = protojson.Unmarshal(jsonBytes, temp); err != nil { + msg := unmarshalErrorMessage(err, p.Operation.Value) + status.SetEnvoyPatchPolicyInvalid(e.Status, msg) + continue + } + if err = tCtx.AddXdsResource(resourcev3.SecretType, temp); err != nil { + msg := fmt.Sprintf("validation failed for xds resource %+v, err:%s", p.Operation.Value, err.Error()) + status.SetEnvoyPatchPolicyInvalid(e.Status, msg) + continue + } } @@ -135,7 +168,7 @@ func processJSONPatches(tCtx *types.ResourceVersionTable, envoyPatchPolicies []* if resourceJSON, err = m.Marshal(listener); err != nil { err := fmt.Errorf("unable to marshal xds resource %s: %s, err: %w", p.Type, p.Name, err) - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) continue } @@ -148,7 +181,7 @@ func processJSONPatches(tCtx *types.ResourceVersionTable, envoyPatchPolicies []* if resourceJSON, err = m.Marshal(routeConfig); err != nil { err = fmt.Errorf("unable to marshal xds resource %s: %s, err: %w", p.Type, p.Name, err) - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) continue } @@ -161,7 +194,7 @@ func processJSONPatches(tCtx *types.ResourceVersionTable, envoyPatchPolicies []* if resourceJSON, err = m.Marshal(cluster); err != nil { err = fmt.Errorf("unable to marshal xds resource %s: %s, err: %w", p.Type, p.Name, err) - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) continue } case string(resourcev3.EndpointType): @@ -172,7 +205,18 @@ func processJSONPatches(tCtx *types.ResourceVersionTable, envoyPatchPolicies []* } if resourceJSON, err = m.Marshal(endpoint); err != nil { err = fmt.Errorf("unable to marshal xds resource %s: %s, err: %w", p.Type, p.Name, err) - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) + continue + } + case string(resourcev3.SecretType): + if secret = findXdsSecret(tCtx, p.Name); secret == nil { + msg := fmt.Sprintf("unable to find xds resource %s: %s", p.Type, p.Name) + status.SetEnvoyPatchPolicyResourceNotFound(e.Status, msg) + continue + } + if resourceJSON, err = m.Marshal(secret); err != nil { + err = fmt.Errorf("unable to marshal xds resource %s: %s, err: %w", p.Type, p.Name, err) + errs = errors.Join(errs, err) continue } } @@ -227,7 +271,7 @@ func processJSONPatches(tCtx *types.ResourceVersionTable, envoyPatchPolicies []* } if err = deepCopyPtr(temp, listener); err != nil { err := fmt.Errorf("unable to copy xds resource %s, err: %w", string(modifiedJSON), err) - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) continue } case string(resourcev3.RouteType): @@ -244,7 +288,7 @@ func processJSONPatches(tCtx *types.ResourceVersionTable, envoyPatchPolicies []* } if err = deepCopyPtr(temp, routeConfig); err != nil { err := fmt.Errorf("unable to copy xds resource %s, err: %w", string(modifiedJSON), err) - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) continue } case string(resourcev3.ClusterType): @@ -261,7 +305,7 @@ func processJSONPatches(tCtx *types.ResourceVersionTable, envoyPatchPolicies []* } if err = deepCopyPtr(temp, cluster); err != nil { err := fmt.Errorf("unable to copy xds resource %s, err: %w", string(modifiedJSON), err) - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) continue } case string(resourcev3.EndpointType): @@ -278,7 +322,24 @@ func processJSONPatches(tCtx *types.ResourceVersionTable, envoyPatchPolicies []* } if err = deepCopyPtr(temp, endpoint); err != nil { err := fmt.Errorf("unable to copy xds resource %s, err: %w", string(modifiedJSON), err) - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) + continue + } + case string(resourcev3.SecretType): + temp := &tlsv3.Secret{} + if err = protojson.Unmarshal(modifiedJSON, temp); err != nil { + msg := unmarshalErrorMessage(err, string(modifiedJSON)) + status.SetEnvoyPatchPolicyInvalid(e.Status, msg) + continue + } + if err = temp.Validate(); err != nil { + msg := fmt.Sprintf("validation failed for xds resource %s, err:%s", string(modifiedJSON), err.Error()) + status.SetEnvoyPatchPolicyInvalid(e.Status, msg) + continue + } + if err = deepCopyPtr(temp, secret); err != nil { + err := fmt.Errorf("unable to copy xds resource %s, err: %w", string(modifiedJSON), err) + errs = errors.Join(errs, err) continue } } diff --git a/internal/xds/translator/jwt.go b/internal/xds/translator/jwt.go index abb4f0b13f6..e1bc76fa1af 100644 --- a/internal/xds/translator/jwt.go +++ b/internal/xds/translator/jwt.go @@ -15,11 +15,11 @@ import ( hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" tlsv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" "github.com/envoyproxy/go-control-plane/pkg/wellknown" - "github.com/tetratelabs/multierror" "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/durationpb" "k8s.io/utils/ptr" + "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/ir" "github.com/envoyproxy/gateway/internal/xds/types" ) @@ -121,7 +121,7 @@ func buildJWTAuthn(irListener *ir.HTTPListener) (*jwtauthnv3.JwtAuthentication, HttpUpstreamType: &corev3.HttpUri_Cluster{ Cluster: jwksCluster.name, }, - Timeout: &durationpb.Duration{Seconds: 5}, + Timeout: &durationpb.Duration{Seconds: defaultExtServiceRequestTimeout}, }, CacheDuration: &durationpb.Duration{Seconds: 5 * 60}, AsyncFetch: &jwtauthnv3.JwksAsyncFetch{}, @@ -146,7 +146,9 @@ func buildJWTAuthn(irListener *ir.HTTPListener) (*jwtauthnv3.JwtAuthentication, } if irProvider.ExtractFrom != nil { + jwtProvider.FromHeaders = buildJwtFromHeaders(irProvider.ExtractFrom.Headers) jwtProvider.FromCookies = irProvider.ExtractFrom.Cookies + jwtProvider.FromParams = irProvider.ExtractFrom.Params } providerKey := fmt.Sprintf("%s/%s", route.Name, irProvider.Name) @@ -179,8 +181,10 @@ func buildJWTAuthn(irListener *ir.HTTPListener) (*jwtauthnv3.JwtAuthentication, // buildXdsUpstreamTLSSocket returns an xDS TransportSocket that uses envoyTrustBundle // as the CA to authenticate server certificates. -func buildXdsUpstreamTLSSocket() (*corev3.TransportSocket, error) { +// TODO huabing: add support for custom CA and client certificate. +func buildXdsUpstreamTLSSocket(sni string) (*corev3.TransportSocket, error) { tlsCtxProto := &tlsv3.UpstreamTlsContext{ + Sni: sni, CommonTlsContext: &tlsv3.CommonTlsContext{ ValidationContextType: &tlsv3.CommonTlsContext_ValidationContext{ ValidationContext: &tlsv3.CertificateValidationContext{ @@ -264,7 +268,7 @@ func (*jwt) patchResources(tCtx *types.ResourceVersionTable, routes []*ir.HTTPRo provider := route.JWT.Providers[i] jwks, err = url2Cluster(provider.RemoteJWKS.URI, false) if err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) continue } @@ -279,16 +283,16 @@ func (*jwt) patchResources(tCtx *types.ResourceVersionTable, routes []*ir.HTTPRo endpointType: jwks.endpointType, } if jwks.tls { - tSocket, err = buildXdsUpstreamTLSSocket() + tSocket, err = buildXdsUpstreamTLSSocket(jwks.hostname) if err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) continue } clusterArgs.tSocket = tSocket } if err = addXdsCluster(tCtx, clusterArgs); err != nil && !errors.Is(err, ErrXdsClusterExists) { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } } @@ -329,6 +333,18 @@ func routeContainsJWTAuthn(irRoute *ir.HTTPRoute) bool { return false } -func (*jwt) patchRouteConfig(*routev3.RouteConfiguration, *ir.HTTPListener) error { - return nil +// buildJwtFromHeaders returns a list of JwtHeader transformed from JWTFromHeader struct +func buildJwtFromHeaders(headers []v1alpha1.JWTHeaderExtractor) []*jwtauthnv3.JwtHeader { + jwtHeaders := make([]*jwtauthnv3.JwtHeader, 0, len(headers)) + + for _, header := range headers { + jwtHeader := &jwtauthnv3.JwtHeader{ + Name: header.Name, + ValuePrefix: ptr.Deref(header.ValuePrefix, ""), + } + + jwtHeaders = append(jwtHeaders, jwtHeader) + } + + return jwtHeaders } diff --git a/internal/xds/translator/listener.go b/internal/xds/translator/listener.go index 02a9cc5810a..268cc1dd41c 100644 --- a/internal/xds/translator/listener.go +++ b/internal/xds/translator/listener.go @@ -16,13 +16,18 @@ import ( hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" tcpv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/tcp_proxy/v3" udpv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/udp/udp_proxy/v3" + preservecasev3 "github.com/envoyproxy/go-control-plane/envoy/extensions/http/header_formatters/preserve_case/v3" + customheaderv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/http/original_ip_detection/custom_header/v3" quicv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/quic/v3" tlsv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" + typev3 "github.com/envoyproxy/go-control-plane/envoy/type/v3" "github.com/envoyproxy/go-control-plane/pkg/resource/v3" "github.com/envoyproxy/go-control-plane/pkg/wellknown" "github.com/golang/protobuf/ptypes/wrappers" "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/wrapperspb" + "k8s.io/utils/ptr" "github.com/envoyproxy/gateway/internal/ir" "github.com/envoyproxy/gateway/internal/utils/protocov" @@ -40,6 +45,36 @@ const ( http2InitialConnectionWindowSize = 1048576 // 1 MiB ) +func http1ProtocolOptions(opts *ir.HTTP1Settings) *corev3.Http1ProtocolOptions { + if opts == nil { + return nil + } + if !opts.EnableTrailers && !opts.PreserveHeaderCase && opts.HTTP10 == nil { + return nil + } + // If PreserveHeaderCase is true and EnableTrailers is false then setting the EnableTrailers field to false + // is simply keeping it at its default value of "disabled". + r := &corev3.Http1ProtocolOptions{ + EnableTrailers: opts.EnableTrailers, + } + if opts.PreserveHeaderCase { + preservecaseAny, _ := anypb.New(&preservecasev3.PreserveCaseFormatterConfig{}) + r.HeaderKeyFormat = &corev3.Http1ProtocolOptions_HeaderKeyFormat{ + HeaderFormat: &corev3.Http1ProtocolOptions_HeaderKeyFormat_StatefulFormatter{ + StatefulFormatter: &corev3.TypedExtensionConfig{ + Name: "preserve_case", + TypedConfig: preservecaseAny, + }, + }, + } + } + if opts.HTTP10 != nil { + r.AcceptHttp_10 = true + r.DefaultHostForHttp_10 = ptr.Deref(opts.HTTP10.DefaultHost, "") + } + return r +} + func http2ProtocolOptions() *corev3.Http2ProtocolOptions { return &corev3.Http2ProtocolOptions{ MaxConcurrentStreams: &wrappers.UInt32Value{ @@ -54,6 +89,44 @@ func http2ProtocolOptions() *corev3.Http2ProtocolOptions { } } +func xffNumTrustedHops(clientIPDetection *ir.ClientIPDetectionSettings) uint32 { + if clientIPDetection != nil && clientIPDetection.XForwardedFor != nil && clientIPDetection.XForwardedFor.NumTrustedHops != nil { + return *clientIPDetection.XForwardedFor.NumTrustedHops + } + return 0 +} + +func originalIPDetectionExtensions(clientIPDetection *ir.ClientIPDetectionSettings) []*corev3.TypedExtensionConfig { + // Return early if settings are nil + if clientIPDetection == nil { + return nil + } + + var extensionConfig []*corev3.TypedExtensionConfig + + // Custom header extension + if clientIPDetection.CustomHeader != nil { + var rejectWithStatus *typev3.HttpStatus + if ptr.Deref(clientIPDetection.CustomHeader.FailClosed, false) { + rejectWithStatus = &typev3.HttpStatus{Code: typev3.StatusCode_Forbidden} + } + + customHeaderConfigAny, _ := anypb.New(&customheaderv3.CustomHeaderConfig{ + HeaderName: clientIPDetection.CustomHeader.Name, + RejectWithStatus: rejectWithStatus, + + AllowExtensionToSetAddressAsTrusted: true, + }) + + extensionConfig = append(extensionConfig, &corev3.TypedExtensionConfig{ + Name: "envoy.extensions.http.original_ip_detection.custom_header", + TypedConfig: customHeaderConfigAny, + }) + } + + return extensionConfig +} + // buildXdsTCPListener creates a xds Listener resource // TODO: Improve function parameters func buildXdsTCPListener(name, address string, port uint32, keepalive *ir.TCPKeepalive, accesslog *ir.AccessLog) *listenerv3.Listener { @@ -119,6 +192,14 @@ func (t *Translator) addXdsHTTPFilterChain(xdsListener *listenerv3.Listener, irL } else { statPrefix = "http" } + + // Client IP detection + var useRemoteAddress = true + var originalIPDetectionExtensions = originalIPDetectionExtensions(irListener.ClientIPDetection) + if originalIPDetectionExtensions != nil { + useRemoteAddress = false + } + mgr := &hcmv3.HttpConnectionManager{ AccessLog: al, CodecType: hcmv3.HttpConnectionManager_AUTO, @@ -130,11 +211,16 @@ func (t *Translator) addXdsHTTPFilterChain(xdsListener *listenerv3.Listener, irL RouteConfigName: irListener.Name, }, }, + HttpProtocolOptions: http1ProtocolOptions(irListener.HTTP1), + // Hide the Envoy proxy in the Server header by default + ServerHeaderTransformation: hcmv3.HttpConnectionManager_PASS_THROUGH, // Add HTTP2 protocol options // Set it by default to also support HTTP1.1 to HTTP2 Upgrades Http2ProtocolOptions: http2ProtocolOptions(), // https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers#x-forwarded-for - UseRemoteAddress: &wrappers.BoolValue{Value: true}, + UseRemoteAddress: &wrappers.BoolValue{Value: useRemoteAddress}, + XffNumTrustedHops: xffNumTrustedHops(irListener.ClientIPDetection), + OriginalIpDetectionExtensions: originalIPDetectionExtensions, // normalize paths according to RFC 3986 NormalizePath: &wrapperspb.BoolValue{Value: true}, MergeSlashes: irListener.Path.MergeSlashes, @@ -145,6 +231,10 @@ func (t *Translator) addXdsHTTPFilterChain(xdsListener *listenerv3.Listener, irL Tracing: hcmTracing, } + if irListener.Timeout != nil && irListener.Timeout.HTTP != nil && irListener.Timeout.HTTP.RequestReceivedTimeout != nil { + mgr.RequestTimeout = durationpb.New(irListener.Timeout.HTTP.RequestReceivedTimeout.Duration) + } + // Add the proxy protocol filter if needed patchProxyProtocolFilter(xdsListener, irListener) @@ -346,7 +436,6 @@ func buildDownstreamQUICTransportSocket(tlsConfig *ir.TLSConfig) (*corev3.Transp TlsParams: buildTLSParams(tlsConfig), AlpnProtocols: buildALPNProtocols(tlsConfig.ALPNProtocols), }, - RequireClientCertificate: &wrappers.BoolValue{Value: false}, }, } @@ -359,6 +448,16 @@ func buildDownstreamQUICTransportSocket(tlsConfig *ir.TLSConfig) (*corev3.Transp }) } + if tlsConfig.CACertificate != nil { + tlsCtx.DownstreamTlsContext.RequireClientCertificate = &wrappers.BoolValue{Value: true} + tlsCtx.DownstreamTlsContext.CommonTlsContext.ValidationContextType = &tlsv3.CommonTlsContext_ValidationContextSdsSecretConfig{ + ValidationContextSdsSecretConfig: &tlsv3.SdsSecretConfig{ + Name: tlsConfig.CACertificate.Name, + SdsConfig: makeConfigSource(), + }, + } + } + tlsCtxAny, err := anypb.New(tlsCtx) if err != nil { return nil, err @@ -389,6 +488,16 @@ func buildXdsDownstreamTLSSocket(tlsConfig *ir.TLSConfig) (*corev3.TransportSock }) } + if tlsConfig.CACertificate != nil { + tlsCtx.RequireClientCertificate = &wrappers.BoolValue{Value: true} + tlsCtx.CommonTlsContext.ValidationContextType = &tlsv3.CommonTlsContext_ValidationContextSdsSecretConfig{ + ValidationContextSdsSecretConfig: &tlsv3.SdsSecretConfig{ + Name: tlsConfig.CACertificate.Name, + SdsConfig: makeConfigSource(), + }, + } + } + tlsCtxAny, err := anypb.New(tlsCtx) if err != nil { return nil, err @@ -451,8 +560,7 @@ func buildALPNProtocols(alpn []string) []string { return alpn } -func buildXdsDownstreamTLSSecret(tlsConfig ir.TLSCertificate) *tlsv3.Secret { - // Build the tls secret +func buildXdsTLSCertSecret(tlsConfig ir.TLSCertificate) *tlsv3.Secret { return &tlsv3.Secret{ Name: tlsConfig.Name, Type: &tlsv3.Secret_TlsCertificate{ @@ -468,6 +576,19 @@ func buildXdsDownstreamTLSSecret(tlsConfig ir.TLSCertificate) *tlsv3.Secret { } } +func buildXdsTLSCaCertSecret(caCertificate *ir.TLSCACertificate) *tlsv3.Secret { + return &tlsv3.Secret{ + Name: caCertificate.Name, + Type: &tlsv3.Secret_ValidationContext{ + ValidationContext: &tlsv3.CertificateValidationContext{ + TrustedCa: &corev3.DataSource{ + Specifier: &corev3.DataSource_InlineBytes{InlineBytes: caCertificate.Certificate}, + }, + }, + }, + } +} + func buildXdsUDPListener(clusterName string, udpListener *ir.UDPListener, accesslog *ir.AccessLog) (*listenerv3.Listener, error) { if udpListener == nil { return nil, errors.New("udp listener is nil") diff --git a/internal/xds/translator/local_ratelimit.go b/internal/xds/translator/local_ratelimit.go index f54071d3536..a3110cbf98e 100644 --- a/internal/xds/translator/local_ratelimit.go +++ b/internal/xds/translator/local_ratelimit.go @@ -110,10 +110,6 @@ func (*localRateLimit) patchResources(*types.ResourceVersionTable, return nil } -func (*localRateLimit) patchRouteConfig(*routev3.RouteConfiguration, *ir.HTTPListener) error { - return nil -} - func (*localRateLimit) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) error { routeAction := route.GetRoute() diff --git a/internal/xds/translator/oidc.go b/internal/xds/translator/oidc.go index e6945d93352..d9a65deaf87 100644 --- a/internal/xds/translator/oidc.go +++ b/internal/xds/translator/oidc.go @@ -17,7 +17,6 @@ import ( tlsv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" matcherv3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" "github.com/golang/protobuf/ptypes/duration" - "github.com/tetratelabs/multierror" "google.golang.org/protobuf/types/known/anypb" "k8s.io/utils/ptr" @@ -26,8 +25,7 @@ import ( ) const ( - oauth2Filter = "envoy.filters.http.oauth2" - defaultTokenEndpointTimeout = 10 + oauth2Filter = "envoy.filters.http.oauth2" ) func init() { @@ -42,6 +40,7 @@ var _ httpFilter = &oidc{} // patchHCM builds and appends the oauth2 Filters to the HTTP Connection Manager // if applicable, and it does not already exist. // Note: this method creates an oauth2 filter for each route that contains an OIDC config. +// the filter is disabled by default. It is enabled on the route level. func (*oidc) patchHCM(mgr *hcmv3.HttpConnectionManager, irListener *ir.HTTPListener) error { var errs error @@ -60,17 +59,10 @@ func (*oidc) patchHCM(mgr *hcmv3.HttpConnectionManager, irListener *ir.HTTPListe filter, err := buildHCMOAuth2Filter(route) if err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) continue } - // skip if the filter already exists - for _, existingFilter := range mgr.HttpFilters { - if filter.Name == existingFilter.Name { - continue - } - } - mgr.HttpFilters = append(mgr.HttpFilters, filter) } @@ -94,7 +86,8 @@ func buildHCMOAuth2Filter(route *ir.HTTPRoute) (*hcmv3.HttpFilter, error) { } return &hcmv3.HttpFilter{ - Name: oauth2FilterName(route), + Name: oauth2FilterName(route), + Disabled: true, ConfigType: &hcmv3.HttpFilter_TypedConfig{ TypedConfig: OAuth2Any, }, @@ -124,7 +117,7 @@ func oauth2Config(route *ir.HTTPRoute) (*oauth2v3.OAuth2, error) { Cluster: cluster.name, }, Timeout: &duration.Duration{ - Seconds: defaultTokenEndpointTimeout, + Seconds: defaultExtServiceRequestTimeout, }, }, AuthorizationEndpoint: route.OIDC.Provider.AuthorizationEndpoint, @@ -160,6 +153,13 @@ func oauth2Config(route *ir.HTTPRoute) (*oauth2v3.OAuth2, error) { SdsConfig: makeConfigSource(), }, }, + CookieNames: &oauth2v3.OAuth2Credentials_CookieNames{ + BearerToken: fmt.Sprintf("BearerToken-%s", route.OIDC.CookieSuffix), + OauthHmac: fmt.Sprintf("OauthHMAC-%s", route.OIDC.CookieSuffix), + OauthExpires: fmt.Sprintf("OauthExpires-%s", route.OIDC.CookieSuffix), + IdToken: fmt.Sprintf("IdToken-%s", route.OIDC.CookieSuffix), + RefreshToken: fmt.Sprintf("RefreshToken-%s", route.OIDC.CookieSuffix), + }, }, // every OIDC provider supports basic auth AuthType: oauth2v3.OAuth2Config_BASIC_AUTH, @@ -217,7 +217,7 @@ func createOAuth2TokenEndpointClusters(tCtx *types.ResourceVersionTable, cluster, err = url2Cluster(route.OIDC.Provider.TokenEndpoint, true) if err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) continue } @@ -225,27 +225,18 @@ func createOAuth2TokenEndpointClusters(tCtx *types.ResourceVersionTable, // This validation could be removed since it's already validated in the // Gateway API translator. if cluster.endpointType == EndpointTypeStatic { - errs = multierror.Append(errs, fmt.Errorf( + errs = errors.Join(errs, fmt.Errorf( "static IP cluster is not allowed: %s", route.OIDC.Provider.TokenEndpoint)) continue } - tlsContext := &tlsv3.UpstreamTlsContext{ - Sni: cluster.hostname, - } - - tlsContextAny, err := anypb.New(tlsContext) + // TODO huabing: add support for custom CA and client certificate. + tSocket, err = buildXdsUpstreamTLSSocket(cluster.hostname) if err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) continue } - tSocket = &corev3.TransportSocket{ - Name: "envoy.transport_sockets.tls", - ConfigType: &corev3.TransportSocket_TypedConfig{ - TypedConfig: tlsContextAny, - }, - } ds = &ir.DestinationSetting{ Weight: ptr.To[uint32](1), @@ -261,7 +252,7 @@ func createOAuth2TokenEndpointClusters(tCtx *types.ResourceVersionTable, tSocket: tSocket, endpointType: cluster.endpointType, }); err != nil && !errors.Is(err, ErrXdsClusterExists) { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } @@ -282,15 +273,15 @@ func createOAuth2Secrets(tCtx *types.ResourceVersionTable, routes []*ir.HTTPRout // oauth2 client ID and secret. clientSecret := buildOAuth2ClientSecret(route) if err := addXdsSecret(tCtx, clientSecret); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } hmacSecret, err := buildOAuth2HMACSecret(route) if err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } if err := addXdsSecret(tCtx, hmacSecret); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } @@ -359,52 +350,6 @@ func generateHMACSecretKey() ([]byte, error) { return key, nil } -// patchRouteCfg patches the provided route configuration with the oauth2 filter -// if applicable. -// Note: this method disables all the oauth2 filters by default. The filter will -// be enabled per-route in the typePerFilterConfig of the route. -func (*oidc) patchRouteConfig(routeCfg *routev3.RouteConfiguration, irListener *ir.HTTPListener) error { - if routeCfg == nil { - return errors.New("route configuration is nil") - } - if irListener == nil { - return errors.New("ir listener is nil") - } - - var errs error - for _, route := range irListener.Routes { - if !routeContainsOIDC(route) { - continue - } - - filterName := oauth2FilterName(route) - filterCfg := routeCfg.TypedPerFilterConfig - - if _, ok := filterCfg[filterName]; ok { - // This should not happen since this is the only place where the oauth2 - // filter is added in a route. - errs = multierror.Append(errs, fmt.Errorf( - "route config already contains oauth2 config: %+v", route)) - continue - } - - // Disable all the filters by default. The filter will be enabled - // per-route in the typePerFilterConfig of the route. - routeCfgAny, err := anypb.New(&routev3.FilterConfig{Disabled: true}) - if err != nil { - errs = multierror.Append(errs, err) - continue - } - - if filterCfg == nil { - routeCfg.TypedPerFilterConfig = make(map[string]*anypb.Any) - } - - routeCfg.TypedPerFilterConfig[filterName] = routeCfgAny - } - return errs -} - // patchRoute patches the provided route with the oauth2 config if applicable. // Note: this method enables the corresponding oauth2 filter for the provided route. func (*oidc) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) error { diff --git a/internal/xds/translator/ratelimit.go b/internal/xds/translator/ratelimit.go index bcdc544a2b4..1a3e4ee5306 100644 --- a/internal/xds/translator/ratelimit.go +++ b/internal/xds/translator/ratelimit.go @@ -152,8 +152,8 @@ func buildRouteRateLimits(descriptorPrefix string, global *ir.GlobalRateLimit) [ // Rules are ORed for rIdx, rule := range global.Rules { - var rlActions []*routev3.RateLimit_Action // Matches are ANDed + rlActions := []*routev3.RateLimit_Action{routeDescriptor} for mIdx, match := range rule.HeaderMatches { // Case for distinct match if match.Distinct { @@ -167,7 +167,7 @@ func buildRouteRateLimits(descriptorPrefix string, global *ir.GlobalRateLimit) [ }, }, } - rlActions = append(rlActions, routeDescriptor, action) + rlActions = append(rlActions, action) } else { // Setup HeaderValueMatch actions descriptorKey := getRouteRuleDescriptor(rIdx, mIdx) @@ -190,7 +190,7 @@ func buildRouteRateLimits(descriptorPrefix string, global *ir.GlobalRateLimit) [ }, }, } - rlActions = append(rlActions, routeDescriptor, action) + rlActions = append(rlActions, action) } } @@ -225,7 +225,7 @@ func buildRouteRateLimits(descriptorPrefix string, global *ir.GlobalRateLimit) [ MaskedRemoteAddress: mra, }, } - rlActions = append(rlActions, routeDescriptor, action) + rlActions = append(rlActions, action) // Setup RemoteAddress action if distinct match is set if rule.CIDRMatch.Distinct { @@ -251,7 +251,7 @@ func buildRouteRateLimits(descriptorPrefix string, global *ir.GlobalRateLimit) [ }, }, } - rlActions = append(rlActions, routeDescriptor, action) + rlActions = append(rlActions, action) } rateLimit := &routev3.RateLimit{Actions: rlActions} @@ -291,6 +291,7 @@ func BuildRateLimitServiceConfig(irListener *ir.HTTPListener) *rlsconfv3.RateLim // descriptors: // - key: ${RouteRuleDescriptor} // value: ${RouteRuleDescriptor} + // - ... // routeDescriptor := &rlsconfv3.RateLimitDescriptor{ Key: getRouteDescriptor(route.Name), diff --git a/internal/xds/translator/route.go b/internal/xds/translator/route.go index b5dd1d61a12..5dd189ffa32 100644 --- a/internal/xds/translator/route.go +++ b/internal/xds/translator/route.go @@ -72,8 +72,9 @@ func buildXdsRoute(httpRoute *ir.HTTPRoute) (*routev3.Route, error) { } // Timeouts - if router.GetRoute() != nil && httpRoute.Timeout != nil { - router.GetRoute().Timeout = durationpb.New(httpRoute.Timeout.Duration) + if router.GetRoute() != nil && httpRoute.Timeout != nil && httpRoute.Timeout.HTTP != nil && + httpRoute.Timeout.HTTP.RequestTimeout != nil { + router.GetRoute().Timeout = durationpb.New(httpRoute.Timeout.HTTP.RequestTimeout.Duration) } // Add per route filter configs to the route, if needed. @@ -328,12 +329,20 @@ func buildXdsAddedHeaders(headersToAdd []ir.AddHeader) []*corev3.HeaderValueOpti headerValueOptions := make([]*corev3.HeaderValueOption, len(headersToAdd)) for i, header := range headersToAdd { + var appendAction corev3.HeaderValueOption_HeaderAppendAction + + if header.Append { + appendAction = corev3.HeaderValueOption_APPEND_IF_EXISTS_OR_ADD + } else { + appendAction = corev3.HeaderValueOption_OVERWRITE_IF_EXISTS_OR_ADD + } + headerValueOptions[i] = &corev3.HeaderValueOption{ Header: &corev3.HeaderValue{ Key: header.Name, Value: header.Value, }, - Append: &wrapperspb.BoolValue{Value: header.Append}, + AppendAction: appendAction, } // Allow empty headers to be set, but don't add the config to do so unless necessary diff --git a/internal/xds/translator/testdata/in/xds-ir/circuit-breaker.yaml b/internal/xds/translator/testdata/in/xds-ir/circuit-breaker.yaml index caf0d373f89..cb693fc583e 100644 --- a/internal/xds/translator/testdata/in/xds-ir/circuit-breaker.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/circuit-breaker.yaml @@ -14,6 +14,7 @@ http: maxConnections: 1 maxPendingRequests: 1 maxParallelRequests: 1 + maxRequestsPerConnection: 10 destination: name: "first-route-dest" settings: diff --git a/internal/xds/translator/testdata/in/xds-ir/client-ip-detection.yaml b/internal/xds/translator/testdata/in/xds-ir/client-ip-detection.yaml new file mode 100644 index 00000000000..de3236a8622 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/client-ip-detection.yaml @@ -0,0 +1,54 @@ +http: +- name: "first-listener" + address: "0.0.0.0" + port: 8081 + hostnames: + - "*" + routes: + - name: "first-route" + hostname: "*" + destination: + name: "first-route-dest" + settings: + - endpoints: + - host: "1.1.1.1" + port: 8081 + clientIPDetection: + xForwardedFor: + numTrustedHops: 2 +- name: "second-listener" + address: "0.0.0.0" + port: 8082 + hostnames: + - "*" + routes: + - name: "second-route" + hostname: "*" + destination: + name: "second-route-dest" + settings: + - endpoints: + - host: "2.2.2.2" + port: 8082 + clientIPDetection: + customHeader: + name: "x-my-custom-header" + failClosed: false +- name: "third-listener" + address: "0.0.0.0" + port: 8083 + hostnames: + - "*" + routes: + - name: "third-route" + hostname: "*" + destination: + name: "third-route-dest" + settings: + - endpoints: + - host: "3.3.3.3" + port: 8083 + clientIPDetection: + customHeader: + name: "x-my-custom-header" + failClosed: true diff --git a/internal/xds/translator/testdata/in/xds-ir/client-timeout.yaml b/internal/xds/translator/testdata/in/xds-ir/client-timeout.yaml new file mode 100644 index 00000000000..1c05b605a35 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/client-timeout.yaml @@ -0,0 +1,22 @@ +http: + - name: "first-listener" + address: "0.0.0.0" + port: 10080 + hostnames: + - "*" + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + routes: + - name: "first-route" + hostname: "*" + destination: + name: "first-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 + timeout: + http: + requestReceivedTimeout: "5s" + diff --git a/internal/xds/translator/testdata/in/xds-ir/ext-auth.yaml b/internal/xds/translator/testdata/in/xds-ir/ext-auth.yaml new file mode 100644 index 00000000000..d1451e968e3 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/ext-auth.yaml @@ -0,0 +1,61 @@ +http: +- name: "first-listener" + address: "0.0.0.0" + port: 10080 + hostnames: + - "www.example.com" + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + routes: + - name: httproute/default/httproute-1/rule/0/match/0/www_example_com + hostname: "*" + pathMatch: + exact: "foo" + destination: + name: httproute/default/httproute-1/rule/0 + settings: + - endpoints: + - host: "10.0.0.1" + port: 50000 + extAuth: + http: + authority: http-backend.envoy-gateway:80 + headersToBackend: + - header1 + - header2 + path: /auth + destination: + name: securitypolicy/default/policy-for-first-route/http-backend + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 80 + protocol: HTTP + weight: 1 + - name: httproute/default/httproute-2/rule/0/match/0/www_example_com + hostname: "*" + pathMatch: + exact: "bar" + destination: + name: httproute/default/httproute-2/rule/0 + settings: + - endpoints: + - host: "10.0.0.2" + port: 60000 + extAuth: + grpc: + authority: grpc-backend.default:9000 + destination: + name: securitypolicy/default/policy-for-second-route/grpc-backend + settings: + - addressType: IP + endpoints: + - host: 8.8.8.8 + port: 9000 + protocol: GRPC + weight: 1 + headersToExtAuth: + - header1 + - header2 diff --git a/internal/xds/translator/testdata/in/xds-ir/health-check.yaml b/internal/xds/translator/testdata/in/xds-ir/health-check.yaml index 63fc5d6f43d..a634af2ef8f 100644 --- a/internal/xds/translator/testdata/in/xds-ir/health-check.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/health-check.yaml @@ -11,17 +11,22 @@ http: - name: "first-route" hostname: "*" healthCheck: - timeout: "500ms" - interval: "3s" - unhealthyThreshold: 3 - healthyThreshold: 1 - http: - path: "/healthz" - expectedResponse: - text: "ok" - expectedStatuses: - - 200 - - 300 + active: + timeout: "500ms" + interval: "3s" + unhealthyThreshold: 3 + healthyThreshold: 1 + http: + path: "/healthz" + expectedResponse: + text: "ok" + expectedStatuses: + - 200 + - 300 + passive: + baseEjectionTime: 180s + interval: 2s + maxEjectionPercent: 100 destination: name: "first-route-dest" settings: @@ -31,17 +36,22 @@ http: - name: "second-route" hostname: "*" healthCheck: - timeout: "1s" - interval: "5s" - unhealthyThreshold: 3 - healthyThreshold: 3 - http: - path: "/healthz" - expectedResponse: - binary: "cG9uZw==" - expectedStatuses: - - 200 - - 201 + active: + timeout: "1s" + interval: "5s" + unhealthyThreshold: 3 + healthyThreshold: 3 + http: + path: "/healthz" + expectedResponse: + binary: "cG9uZw==" + expectedStatuses: + - 200 + - 201 + passive: + baseEjectionTime: 180s + interval: 1s + maxEjectionPercent: 100 destination: name: "second-route-dest" settings: @@ -51,15 +61,20 @@ http: - name: "third-route" hostname: "*" healthCheck: - timeout: "1s" - interval: "5s" - unhealthyThreshold: 3 - healthyThreshold: 3 - tcp: - send: - text: "ping" - receive: - text: "pong" + active: + timeout: "1s" + interval: "5s" + unhealthyThreshold: 3 + healthyThreshold: 3 + tcp: + send: + text: "ping" + receive: + text: "pong" + passive: + baseEjectionTime: 160s + interval: 1s + maxEjectionPercent: 100 destination: name: "third-route-dest" settings: @@ -69,15 +84,20 @@ http: - name: "fourth-route" hostname: "*" healthCheck: - timeout: "1s" - interval: "5s" - unhealthyThreshold: 3 - healthyThreshold: 3 - tcp: - send: - binary: "cGluZw==" - receive: - binary: "cG9uZw==" + active: + timeout: "1s" + interval: "5s" + unhealthyThreshold: 3 + healthyThreshold: 3 + tcp: + send: + binary: "cGluZw==" + receive: + binary: "cG9uZw==" + passive: + baseEjectionTime: 180s + interval: 1s + maxEjectionPercent: 90 destination: name: "fourth-route-dest" settings: diff --git a/internal/xds/translator/testdata/in/xds-ir/http-route-timeout.yaml b/internal/xds/translator/testdata/in/xds-ir/http-route-timeout.yaml index 355f07279d4..da1a4243aa3 100644 --- a/internal/xds/translator/testdata/in/xds-ir/http-route-timeout.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/http-route-timeout.yaml @@ -10,7 +10,9 @@ http: routes: - name: "first-route" hostname: "*" - timeout: 5s + timeout: + http: + requestTimeout: 5s headerMatches: - name: user stringMatch: diff --git a/internal/xds/translator/testdata/in/xds-ir/http1-preserve-case.yaml b/internal/xds/translator/testdata/in/xds-ir/http1-preserve-case.yaml new file mode 100644 index 00000000000..f857ac8f854 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/http1-preserve-case.yaml @@ -0,0 +1,40 @@ +http: +- name: "first-listener" + address: "0.0.0.0" + port: 10080 + hostnames: + - "*" + http1: + preserveHeaderCase: true + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + routes: + - name: "first-route" + hostname: "*" + destination: + name: "first-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 +- name: "second-listener" + address: "0.0.0.0" + port: 10081 + hostnames: + - "*" + http1: + preserveHeaderCase: true + enableTrailers: true + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + routes: + - name: "second-route" + hostname: "*" + destination: + name: "second-route-dest" + settings: + - endpoints: + - host: "1.2.3.5" + port: 50000 diff --git a/internal/xds/translator/testdata/in/xds-ir/http1-trailers.yaml b/internal/xds/translator/testdata/in/xds-ir/http1-trailers.yaml new file mode 100644 index 00000000000..51174744979 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/http1-trailers.yaml @@ -0,0 +1,20 @@ +http: +- name: "first-listener" + address: "0.0.0.0" + port: 10080 + hostnames: + - "*" + http1: + enableTrailers: true + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + routes: + - name: "first-route" + hostname: "*" + destination: + name: "first-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 diff --git a/internal/xds/translator/testdata/in/xds-ir/http10.yaml b/internal/xds/translator/testdata/in/xds-ir/http10.yaml new file mode 100644 index 00000000000..47f57a04422 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/http10.yaml @@ -0,0 +1,21 @@ +http: +- name: "first-listener" + address: "0.0.0.0" + port: 10080 + hostnames: + - "foo.com" + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + http1: + http10: + defaultHost: "foo.com" + routes: + - name: "first-route" + hostname: "*" + destination: + name: "first-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 diff --git a/internal/xds/translator/testdata/in/xds-ir/jsonpatch-add-op-without-value.yaml b/internal/xds/translator/testdata/in/xds-ir/jsonpatch-add-op-without-value.yaml new file mode 100644 index 00000000000..610195b2938 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/jsonpatch-add-op-without-value.yaml @@ -0,0 +1,62 @@ +envoyPatchPolicies: +- status: {} + name: "first-policy" + namespace: "default" + jsonPatches: + - type: "type.googleapis.com/envoy.config.listener.v3.Listener" + name: "first-listener" + operation: + op: "add" + path: "/filter_chains/0/filters/0/typed_config/http_filters/0" + value: + name: "envoy.filters.http.ratelimit" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit" + domain: "eg-ratelimit" + failure_mode_deny: true + timeout: 1s + rate_limit_service: + grpc_service: + envoy_grpc: + cluster_name: rate-limit-cluster + transport_api_version: V3 + - type: "type.googleapis.com/envoy.config.route.v3.RouteConfiguration" + name: "first-listener" + operation: + op: "add" + path: "/virtual_hosts/0/rate_limits" +http: +- name: "first-listener" + address: "0.0.0.0" + port: 10080 + hostnames: + - "*" + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + tls: + alpnProtocols: + - h2 + - http/1.1 + certificates: + - name: secret-1 + # byte slice representation of "key-data" + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + # byte slice representation of "key-data" + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + - name: secret-2 + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + routes: + - name: "first-route" + hostname: "*" + headerMatches: + - name: user + stringMatch: + exact: "jason" + destination: + name: "first-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 diff --git a/internal/xds/translator/testdata/in/xds-ir/jsonpatch-move-op-with-value.yaml b/internal/xds/translator/testdata/in/xds-ir/jsonpatch-move-op-with-value.yaml new file mode 100644 index 00000000000..0f7612b3408 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/jsonpatch-move-op-with-value.yaml @@ -0,0 +1,65 @@ +envoyPatchPolicies: +- status: {} + name: "first-policy" + namespace: "default" + jsonPatches: + - type: "type.googleapis.com/envoy.config.listener.v3.Listener" + name: "first-listener" + operation: + op: "add" + path: "/filter_chains/0/filters/0/typed_config/http_filters/0" + value: + name: "envoy.filters.http.ratelimit" + typed_config: + "@type": "type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit" + domain: "eg-ratelimit" + failure_mode_deny: true + timeout: 1s + rate_limit_service: + grpc_service: + envoy_grpc: + cluster_name: rate-limit-cluster + transport_api_version: V3 + - type: "type.googleapis.com/envoy.config.listener.v3.Listener" + name: "first-listener" + operation: + op: "remove" + from: "/filter_chains/0/filters/0/typed_config/http_filters/0" + path: "/filter_chains/0/filters/0/typed_config/http_filters/1" + value: + test: "abc" +http: +- name: "first-listener" + address: "0.0.0.0" + port: 10080 + hostnames: + - "*" + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + tls: + alpnProtocols: + - h2 + - http/1.1 + certificates: + - name: secret-1 + # byte slice representation of "key-data" + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + # byte slice representation of "key-data" + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + - name: secret-2 + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + routes: + - name: "first-route" + hostname: "*" + headerMatches: + - name: user + stringMatch: + exact: "jason" + destination: + name: "first-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 diff --git a/internal/xds/translator/testdata/in/xds-ir/jsonpatch.yaml b/internal/xds/translator/testdata/in/xds-ir/jsonpatch.yaml index 1fc1a5f3a66..c05e7e77c5d 100644 --- a/internal/xds/translator/testdata/in/xds-ir/jsonpatch.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/jsonpatch.yaml @@ -7,7 +7,7 @@ envoyPatchPolicies: name: "first-listener" operation: op: "add" - path: "/default_filter_chain/filters/0/typed_config/http_filters/0" + path: "/filter_chains/0/filters/0/typed_config/http_filters/0" value: name: "envoy.filters.http.ratelimit" typed_config: @@ -54,6 +54,47 @@ envoyPatchPolicies: op: "replace" path: "/endpoints/0/load_balancing_weight" value: "50" + - type: "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret" + name: "secret-1" + operation: + op: "replace" + path: "/tls_certificate/certificate_chain/inline_bytes" + value: "a2V5LWRhdGE=" + - type: "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret" + name: "test-secret" + operation: + op: "add" + path: "" + value: + name: test_secret + tls_certificate: + certificate_chain: + inline_bytes: Y2VydC1kYXRh + - type: "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment" + name: "first-route-dest" + operation: + op: add + path: "/endpoints/1" + value: + lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + - type: "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment" + name: "first-route-dest" + operation: + op: "move" + from: "/endpoints/0/load_balancing_weight" + path: "/endpoints/1/load_balancing_weight" + - type: "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment" + name: "first-route-dest" + operation: + op: copy + from: "/endpoints/1/load_balancing_weight" + path: "/endpoints/0/load_balancing_weight" http: - name: "first-listener" address: "0.0.0.0" @@ -63,6 +104,19 @@ http: path: mergeSlashes: true escapedSlashesAction: UnescapeAndRedirect + tls: + alpnProtocols: + - h2 + - http/1.1 + certificates: + - name: secret-1 + # byte slice representation of "key-data" + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + # byte slice representation of "key-data" + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + - name: secret-2 + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] routes: - name: "first-route" hostname: "*" diff --git a/internal/xds/translator/testdata/in/xds-ir/jwt-custom-extractor.yaml b/internal/xds/translator/testdata/in/xds-ir/jwt-custom-extractor.yaml index 2104396d666..2a362a469dc 100644 --- a/internal/xds/translator/testdata/in/xds-ir/jwt-custom-extractor.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/jwt-custom-extractor.yaml @@ -23,6 +23,11 @@ http: extractFrom: cookies: - session_access_token + headers: + - name: Authorization + valuePrefix: 'Bearer ' + params: + - token destination: name: "first-route-dest" settings: diff --git a/internal/xds/translator/testdata/in/xds-ir/mutual-tls.yaml b/internal/xds/translator/testdata/in/xds-ir/mutual-tls.yaml new file mode 100644 index 00000000000..ea7ebf48a4d --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/mutual-tls.yaml @@ -0,0 +1,34 @@ +http: +- name: "first-listener" + address: "0.0.0.0" + port: 10080 + hostnames: + - "*" + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + tls: + alpnProtocols: + - h2 + - http/1.1 + certificates: + - name: secret-1 + # byte slice representation of "key-data" + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + # byte slice representation of "key-data" + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + - name: secret-2 + serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + privateKey: [107, 101, 121, 45, 100, 97, 116, 97] + caCertificate: + name: ca-cert + certificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] + routes: + - name: "first-route" + hostname: "*" + destination: + name: "first-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 diff --git a/internal/xds/translator/testdata/in/xds-ir/oidc.yaml b/internal/xds/translator/testdata/in/xds-ir/oidc.yaml index ff1d3fb37ca..ee69934f1c5 100644 --- a/internal/xds/translator/testdata/in/xds-ir/oidc.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/oidc.yaml @@ -31,6 +31,7 @@ http: redirectURL: "https://www.example.com/foo/oauth2/callback" redirectPath: "/foo/oauth2/callback" logoutPath: "/foo/logout" + cookieSuffix: 5F93C2E4 - name: "second-route" hostname: "*" pathMatch: @@ -54,3 +55,4 @@ http: redirectURL: "https://www.example.com/bar/oauth2/callback" redirectPath: "/bar/oauth2/callback" logoutPath: "/bar/logout" + cookieSuffix: B0A1B740 diff --git a/internal/xds/translator/testdata/in/xds-ir/suppress-envoy-headers.yaml b/internal/xds/translator/testdata/in/xds-ir/suppress-envoy-headers.yaml index 9eaf2996e88..f26d13b084e 100644 --- a/internal/xds/translator/testdata/in/xds-ir/suppress-envoy-headers.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/suppress-envoy-headers.yaml @@ -20,7 +20,8 @@ http: - name: secret-2 serverCertificate: [99, 101, 114, 116, 45, 100, 97, 116, 97] privateKey: [107, 101, 121, 45, 100, 97, 116, 97] - suppressEnvoyHeaders: true + headers: + enableEnvoyHeaders: true routes: - name: "first-route" hostname: "*" diff --git a/internal/xds/translator/testdata/in/xds-ir/timeout.yaml b/internal/xds/translator/testdata/in/xds-ir/timeout.yaml new file mode 100644 index 00000000000..daee154f055 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/timeout.yaml @@ -0,0 +1,24 @@ +http: +- name: "first-listener" + address: "0.0.0.0" + port: 10080 + hostnames: + - "*" + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + routes: + - name: "first-route" + hostname: "*" + timeout: + tcp: + connectTimeout: "31s" + http: + connectionIdleTimeout: "32s" + maxConnectionDuration: "33s" + destination: + name: "first-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 diff --git a/internal/xds/translator/testdata/in/xds-ir/upstream-tcpkeepalive.yaml b/internal/xds/translator/testdata/in/xds-ir/upstream-tcpkeepalive.yaml new file mode 100644 index 00000000000..bb7febec8b7 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/upstream-tcpkeepalive.yaml @@ -0,0 +1,22 @@ +http: +- name: "first-listener" + address: "0.0.0.0" + port: 10080 + hostnames: + - "*" + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + routes: + - name: "first-route" + hostname: "*" + tcpKeepalive: + idleTime: 1200 + interval: 60 + probes: 3 + destination: + name: "first-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 diff --git a/internal/xds/translator/testdata/out/extension-xds-ir/http-route-extension-filter.listeners.yaml b/internal/xds/translator/testdata/out/extension-xds-ir/http-route-extension-filter.listeners.yaml index 00b88ec33bb..c5835215d89 100644 --- a/internal/xds/translator/testdata/out/extension-xds-ir/http-route-extension-filter.listeners.yaml +++ b/internal/xds/translator/testdata/out/extension-xds-ir/http-route-extension-filter.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: extension-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/extension-xds-ir/http-route.listeners.yaml b/internal/xds/translator/testdata/out/extension-xds-ir/http-route.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/extension-xds-ir/http-route.listeners.yaml +++ b/internal/xds/translator/testdata/out/extension-xds-ir/http-route.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket 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 8b64c852a8f..a3bf0b5bc88 100644 --- a/internal/xds/translator/testdata/out/xds-ir/accesslog.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/accesslog.listeners.yaml @@ -127,6 +127,7 @@ - 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 @@ -135,6 +136,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/basic-auth.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/basic-auth.listeners.yaml index ab0592b760b..11ecc856c2d 100644 --- a/internal/xds/translator/testdata/out/xds-ir/basic-auth.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/basic-auth.listeners.yaml @@ -14,7 +14,8 @@ initialStreamWindowSize: 65536 maxConcurrentStreams: 100 httpFilters: - - name: envoy.filters.http.basic_auth_first-route + - disabled: true + name: envoy.filters.http.basic_auth_first-route typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.http.basic_auth.v3.BasicAuth users: @@ -22,6 +23,7 @@ - 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 @@ -30,6 +32,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/basic-auth.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/basic-auth.routes.yaml index dbaae69d06a..6fdefbdf7c1 100644 --- a/internal/xds/translator/testdata/out/xds-ir/basic-auth.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/basic-auth.routes.yaml @@ -1,9 +1,5 @@ - ignorePortInHostMatching: true name: first-listener - typedPerFilterConfig: - envoy.filters.http.basic_auth_first-route: - '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig - disabled: true virtualHosts: - domains: - '*' diff --git a/internal/xds/translator/testdata/out/xds-ir/circuit-breaker.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/circuit-breaker.clusters.yaml index 59a43e91a45..9bae95db486 100644 --- a/internal/xds/translator/testdata/out/xds-ir/circuit-breaker.clusters.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/circuit-breaker.clusters.yaml @@ -17,3 +17,10 @@ outlierDetection: {} perConnectionBufferLimitBytes: 32768 type: EDS + typedExtensionProtocolOptions: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + commonHttpProtocolOptions: + maxRequestsPerConnection: 10 + explicitHttpConfig: + httpProtocolOptions: {} diff --git a/internal/xds/translator/testdata/out/xds-ir/circuit-breaker.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/circuit-breaker.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/circuit-breaker.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/circuit-breaker.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/client-ip-detection.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/client-ip-detection.clusters.yaml new file mode 100755 index 00000000000..869321c6504 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/client-ip-detection.clusters.yaml @@ -0,0 +1,42 @@ +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: first-route-dest + lbPolicy: LEAST_REQUEST + name: first-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: second-route-dest + lbPolicy: LEAST_REQUEST + name: second-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: third-route-dest + lbPolicy: LEAST_REQUEST + name: third-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/client-ip-detection.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/client-ip-detection.endpoints.yaml new file mode 100755 index 00000000000..59545ddec3a --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/client-ip-detection.endpoints.yaml @@ -0,0 +1,36 @@ +- clusterName: first-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.1.1.1 + portValue: 8081 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: first-route-dest/backend/0 +- clusterName: second-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 2.2.2.2 + portValue: 8082 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: second-route-dest/backend/0 +- clusterName: third-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 3.3.3.3 + portValue: 8083 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: third-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/client-ip-detection.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/client-ip-detection.listeners.yaml new file mode 100755 index 00000000000..102b968f145 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/client-ip-detection.listeners.yaml @@ -0,0 +1,114 @@ +- address: + socketAddress: + address: 0.0.0.0 + portValue: 8081 + defaultFilterChain: + 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 + normalizePath: true + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: http + upgradeConfigs: + - upgradeType: websocket + useRemoteAddress: true + xffNumTrustedHops: 2 + name: first-listener + perConnectionBufferLimitBytes: 32768 +- address: + socketAddress: + address: 0.0.0.0 + portValue: 8082 + defaultFilterChain: + 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 + normalizePath: true + originalIpDetectionExtensions: + - name: envoy.extensions.http.original_ip_detection.custom_header + typedConfig: + '@type': type.googleapis.com/envoy.extensions.http.original_ip_detection.custom_header.v3.CustomHeaderConfig + allowExtensionToSetAddressAsTrusted: true + headerName: x-my-custom-header + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: second-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: http + upgradeConfigs: + - upgradeType: websocket + useRemoteAddress: false + name: second-listener + perConnectionBufferLimitBytes: 32768 +- address: + socketAddress: + address: 0.0.0.0 + portValue: 8083 + defaultFilterChain: + 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 + normalizePath: true + originalIpDetectionExtensions: + - name: envoy.extensions.http.original_ip_detection.custom_header + typedConfig: + '@type': type.googleapis.com/envoy.extensions.http.original_ip_detection.custom_header.v3.CustomHeaderConfig + allowExtensionToSetAddressAsTrusted: true + headerName: x-my-custom-header + rejectWithStatus: + code: Forbidden + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: third-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: http + upgradeConfigs: + - upgradeType: websocket + useRemoteAddress: false + name: third-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/client-ip-detection.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/client-ip-detection.routes.yaml new file mode 100755 index 00000000000..724f80699c7 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/client-ip-detection.routes.yaml @@ -0,0 +1,36 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + prefix: / + name: first-route + route: + cluster: first-route-dest +- ignorePortInHostMatching: true + name: second-listener + virtualHosts: + - domains: + - '*' + name: second-listener/* + routes: + - match: + prefix: / + name: second-route + route: + cluster: second-route-dest +- ignorePortInHostMatching: true + name: third-listener + virtualHosts: + - domains: + - '*' + name: third-listener/* + routes: + - match: + prefix: / + name: third-route + route: + cluster: third-route-dest diff --git a/internal/xds/translator/testdata/out/xds-ir/client-timeout.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/client-timeout.clusters.yaml new file mode 100644 index 00000000000..c8692b81602 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/client-timeout.clusters.yaml @@ -0,0 +1,14 @@ +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: first-route-dest + lbPolicy: LEAST_REQUEST + name: first-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/client-timeout.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/client-timeout.endpoints.yaml new file mode 100644 index 00000000000..3b3f2d09076 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/client-timeout.endpoints.yaml @@ -0,0 +1,12 @@ +- clusterName: first-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: first-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/client-timeout.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/client-timeout.listeners.yaml new file mode 100644 index 00000000000..e6e99e720bf --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/client-timeout.listeners.yaml @@ -0,0 +1,36 @@ +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10080 + defaultFilterChain: + 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: first-listener + requestTimeout: 5s + serverHeaderTransformation: PASS_THROUGH + statPrefix: http + upgradeConfigs: + - upgradeType: websocket + useRemoteAddress: true + name: first-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/client-timeout.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/client-timeout.routes.yaml new file mode 100644 index 00000000000..2734c7cc42a --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/client-timeout.routes.yaml @@ -0,0 +1,12 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + prefix: / + name: first-route + route: + cluster: first-route-dest diff --git a/internal/xds/translator/testdata/out/xds-ir/cors.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/cors.listeners.yaml index c48a6d76424..b9858e6777a 100644 --- a/internal/xds/translator/testdata/out/xds-ir/cors.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/cors.listeners.yaml @@ -20,6 +20,7 @@ - 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 @@ -28,6 +29,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-auth.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-auth.clusters.yaml new file mode 100755 index 00000000000..ec3cb0b2f79 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/ext-auth.clusters.yaml @@ -0,0 +1,61 @@ +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: httproute/default/httproute-1/rule/0 + lbPolicy: LEAST_REQUEST + name: httproute/default/httproute-1/rule/0 + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: httproute/default/httproute-2/rule/0 + lbPolicy: LEAST_REQUEST + name: httproute/default/httproute-2/rule/0 + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: securitypolicy/default/policy-for-first-route/http-backend + lbPolicy: LEAST_REQUEST + name: securitypolicy/default/policy-for-first-route/http-backend + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: securitypolicy/default/policy-for-second-route/grpc-backend + lbPolicy: LEAST_REQUEST + name: securitypolicy/default/policy-for-second-route/grpc-backend + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS + typedExtensionProtocolOptions: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicitHttpConfig: + http2ProtocolOptions: {} diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-auth.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-auth.endpoints.yaml new file mode 100755 index 00000000000..ce53193cdb2 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/ext-auth.endpoints.yaml @@ -0,0 +1,48 @@ +- clusterName: httproute/default/httproute-1/rule/0 + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 10.0.0.1 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: httproute/default/httproute-1/rule/0/backend/0 +- clusterName: httproute/default/httproute-2/rule/0 + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 10.0.0.2 + portValue: 60000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: httproute/default/httproute-2/rule/0/backend/0 +- clusterName: securitypolicy/default/policy-for-first-route/http-backend + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 7.7.7.7 + portValue: 80 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: securitypolicy/default/policy-for-first-route/http-backend/backend/0 +- clusterName: securitypolicy/default/policy-for-second-route/grpc-backend + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 8.8.8.8 + portValue: 9000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: securitypolicy/default/policy-for-second-route/grpc-backend/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-auth.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-auth.listeners.yaml new file mode 100755 index 00000000000..ec6f73b212f --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/ext-auth.listeners.yaml @@ -0,0 +1,62 @@ +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10080 + defaultFilterChain: + 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: + - disabled: true + name: envoy.filters.http.ext_authz_httproute/default/httproute-1/rule/0/match/0/www_example_com + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz + httpService: + authorizationResponse: + allowedUpstreamHeaders: + patterns: + - exact: header1 + - exact: header2 + serverUri: + cluster: securitypolicy/default/policy-for-first-route/http-backend + timeout: 10s + uri: http://http-backend.envoy-gateway:80/auth + - disabled: true + name: envoy.filters.http.ext_authz_httproute/default/httproute-2/rule/0/match/0/www_example_com + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz + allowedHeaders: + patterns: + - exact: header1 + - exact: header2 + grpcService: + envoyGrpc: + authority: grpc-backend.default:9000 + clusterName: securitypolicy/default/policy-for-second-route/grpc-backend + timeout: 10s + - 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: first-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: http + upgradeConfigs: + - upgradeType: websocket + useRemoteAddress: true + name: first-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-auth.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-auth.routes.yaml new file mode 100755 index 00000000000..d8aae14302a --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/ext-auth.routes.yaml @@ -0,0 +1,25 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + path: foo + name: httproute/default/httproute-1/rule/0/match/0/www_example_com + route: + cluster: httproute/default/httproute-1/rule/0 + typedPerFilterConfig: + envoy.filters.http.ext_authz_httproute/default/httproute-1/rule/0/match/0/www_example_com: + '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig + config: {} + - match: + path: bar + name: httproute/default/httproute-2/rule/0/match/0/www_example_com + route: + cluster: httproute/default/httproute-2/rule/0 + typedPerFilterConfig: + envoy.filters.http.ext_authz_httproute/default/httproute-2/rule/0/match/0/www_example_com: + '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig + config: {} diff --git a/internal/xds/translator/testdata/out/xds-ir/fault-injection.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/fault-injection.listeners.yaml index d396bfb96b0..7586adc78b0 100755 --- a/internal/xds/translator/testdata/out/xds-ir/fault-injection.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/fault-injection.listeners.yaml @@ -20,6 +20,7 @@ - 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 @@ -28,6 +29,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/health-check.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/health-check.clusters.yaml index 628302cce16..6003509f196 100644 --- a/internal/xds/translator/testdata/out/xds-ir/health-check.clusters.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/health-check.clusters.yaml @@ -23,7 +23,10 @@ unhealthyThreshold: 3 lbPolicy: LEAST_REQUEST name: first-route-dest - outlierDetection: {} + outlierDetection: + baseEjectionTime: 180s + interval: 2s + maxEjectionPercent: 100 perConnectionBufferLimitBytes: 32768 type: EDS - commonLbConfig: @@ -49,7 +52,10 @@ unhealthyThreshold: 3 lbPolicy: LEAST_REQUEST name: second-route-dest - outlierDetection: {} + outlierDetection: + baseEjectionTime: 180s + interval: 1s + maxEjectionPercent: 100 perConnectionBufferLimitBytes: 32768 type: EDS - commonLbConfig: @@ -73,7 +79,10 @@ unhealthyThreshold: 3 lbPolicy: LEAST_REQUEST name: third-route-dest - outlierDetection: {} + outlierDetection: + baseEjectionTime: 160s + interval: 1s + maxEjectionPercent: 100 perConnectionBufferLimitBytes: 32768 type: EDS - commonLbConfig: @@ -97,6 +106,9 @@ unhealthyThreshold: 3 lbPolicy: LEAST_REQUEST name: fourth-route-dest - outlierDetection: {} + outlierDetection: + baseEjectionTime: 180s + interval: 1s + maxEjectionPercent: 90 perConnectionBufferLimitBytes: 32768 type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/health-check.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/health-check.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/health-check.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/health-check.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-direct-response.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-direct-response.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-direct-response.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-direct-response.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-dns-cluster.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-dns-cluster.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-dns-cluster.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-dns-cluster.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-mirror.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-mirror.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-mirror.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-mirror.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-matches.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-matches.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-matches.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-matches.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-mirrors.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-mirrors.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-mirrors.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-mirrors.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-partial-invalid.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-partial-invalid.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-partial-invalid.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-partial-invalid.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-redirect.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-redirect.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-redirect.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-redirect.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-regex.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-regex.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-regex.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-regex.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-request-headers.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-request-headers.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-request-headers.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-request-headers.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-request-headers.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-request-headers.routes.yaml index 2d8f26ab8da..3ded1e7105d 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-request-headers.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-request-headers.routes.yaml @@ -9,23 +9,21 @@ prefix: / name: request-header-route requestHeadersToAdd: - - append: true - header: + - header: key: some-header value: some-value - - append: true - header: + - header: key: some-header-2 value: some-value - - append: false + - appendAction: OVERWRITE_IF_EXISTS_OR_ADD header: key: some-header3 value: some-value - - append: false + - appendAction: OVERWRITE_IF_EXISTS_OR_ADD header: key: some-header4 value: some-value - - append: false + - appendAction: OVERWRITE_IF_EXISTS_OR_ADD header: key: empty-header keepEmptyValue: true diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-headers.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-headers.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-headers.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-headers.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-headers.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-headers.routes.yaml index af0333a9bfb..a57c32ff84a 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-headers.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-headers.routes.yaml @@ -9,23 +9,21 @@ prefix: / name: response-header-route responseHeadersToAdd: - - append: true - header: + - header: key: some-header value: some-value - - append: true - header: + - header: key: some-header-2 value: some-value - - append: false + - appendAction: OVERWRITE_IF_EXISTS_OR_ADD header: key: some-header3 value: some-value - - append: false + - appendAction: OVERWRITE_IF_EXISTS_OR_ADD header: key: some-header4 value: some-value - - append: false + - appendAction: OVERWRITE_IF_EXISTS_OR_ADD header: key: empty-header keepEmptyValue: true diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-remove-headers.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-remove-headers.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-remove-headers.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-remove-headers.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-remove-headers.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-remove-headers.routes.yaml index f94d0e9d92d..f8c7a7ff5bb 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-remove-headers.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-remove-headers.routes.yaml @@ -9,23 +9,21 @@ prefix: / name: response-header-route responseHeadersToAdd: - - append: true - header: + - header: key: some-header value: some-value - - append: true - header: + - header: key: some-header-2 value: some-value - - append: false + - appendAction: OVERWRITE_IF_EXISTS_OR_ADD header: key: some-header3 value: some-value - - append: false + - appendAction: OVERWRITE_IF_EXISTS_OR_ADD header: key: some-header4 value: some-value - - append: false + - appendAction: OVERWRITE_IF_EXISTS_OR_ADD header: key: empty-header keepEmptyValue: true diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-response-remove-headers.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-response-remove-headers.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-response-remove-headers.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-response-remove-headers.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-root-path-url-prefix.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-root-path-url-prefix.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-root-path-url-prefix.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-root-path-url-prefix.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-fullpath.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-fullpath.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-fullpath.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-fullpath.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-host.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-host.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-host.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-host.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-prefix.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-prefix.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-prefix.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-prefix.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-timeout.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-timeout.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-timeout.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-timeout.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-invalid-backend.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-invalid-backend.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-invalid-backend.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-invalid-backend.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-with-stripped-host-port.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-with-stripped-host-port.listeners.yaml index 1ddd025c99e..1eae91bee81 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-with-stripped-host-port.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-with-stripped-host-port.listeners.yaml @@ -13,6 +13,7 @@ - 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 @@ -21,6 +22,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http1-preserve-case.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/http1-preserve-case.clusters.yaml new file mode 100644 index 00000000000..3799e281ee2 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http1-preserve-case.clusters.yaml @@ -0,0 +1,49 @@ +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: first-route-dest + lbPolicy: LEAST_REQUEST + name: first-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS + typedExtensionProtocolOptions: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicitHttpConfig: + httpProtocolOptions: + headerKeyFormat: + statefulFormatter: + name: preserve_case + typedConfig: + '@type': type.googleapis.com/envoy.extensions.http.header_formatters.preserve_case.v3.PreserveCaseFormatterConfig +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: second-route-dest + lbPolicy: LEAST_REQUEST + name: second-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS + typedExtensionProtocolOptions: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicitHttpConfig: + httpProtocolOptions: + enableTrailers: true + headerKeyFormat: + statefulFormatter: + name: preserve_case + typedConfig: + '@type': type.googleapis.com/envoy.extensions.http.header_formatters.preserve_case.v3.PreserveCaseFormatterConfig diff --git a/internal/xds/translator/testdata/out/xds-ir/http1-preserve-case.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/http1-preserve-case.endpoints.yaml new file mode 100644 index 00000000000..28a57caf3b5 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http1-preserve-case.endpoints.yaml @@ -0,0 +1,24 @@ +- clusterName: first-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: first-route-dest/backend/0 +- clusterName: second-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.5 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: second-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/http1-preserve-case.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http1-preserve-case.listeners.yaml new file mode 100644 index 00000000000..51679103175 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http1-preserve-case.listeners.yaml @@ -0,0 +1,83 @@ +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10080 + defaultFilterChain: + 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 + httpProtocolOptions: + headerKeyFormat: + statefulFormatter: + name: preserve_case + typedConfig: + '@type': type.googleapis.com/envoy.extensions.http.header_formatters.preserve_case.v3.PreserveCaseFormatterConfig + mergeSlashes: true + normalizePath: true + pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: http + upgradeConfigs: + - upgradeType: websocket + useRemoteAddress: true + name: first-listener + perConnectionBufferLimitBytes: 32768 +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10081 + defaultFilterChain: + 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 + httpProtocolOptions: + enableTrailers: true + headerKeyFormat: + statefulFormatter: + name: preserve_case + typedConfig: + '@type': type.googleapis.com/envoy.extensions.http.header_formatters.preserve_case.v3.PreserveCaseFormatterConfig + mergeSlashes: true + normalizePath: true + pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: second-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: http + upgradeConfigs: + - upgradeType: websocket + useRemoteAddress: true + name: second-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http1-preserve-case.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http1-preserve-case.routes.yaml new file mode 100644 index 00000000000..d36b9824e31 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http1-preserve-case.routes.yaml @@ -0,0 +1,24 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + prefix: / + name: first-route + route: + cluster: first-route-dest +- ignorePortInHostMatching: true + name: second-listener + virtualHosts: + - domains: + - '*' + name: second-listener/* + routes: + - match: + prefix: / + name: second-route + route: + cluster: second-route-dest diff --git a/internal/xds/translator/testdata/out/xds-ir/http1-trailers.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/http1-trailers.clusters.yaml new file mode 100644 index 00000000000..2e9b5ba149f --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http1-trailers.clusters.yaml @@ -0,0 +1,20 @@ +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: first-route-dest + lbPolicy: LEAST_REQUEST + name: first-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS + typedExtensionProtocolOptions: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicitHttpConfig: + httpProtocolOptions: + enableTrailers: true diff --git a/internal/xds/translator/testdata/out/xds-ir/http1-trailers.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/http1-trailers.endpoints.yaml new file mode 100644 index 00000000000..3b3f2d09076 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http1-trailers.endpoints.yaml @@ -0,0 +1,12 @@ +- clusterName: first-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: first-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/http1-trailers.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http1-trailers.listeners.yaml new file mode 100644 index 00000000000..59592df658a --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http1-trailers.listeners.yaml @@ -0,0 +1,37 @@ +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10080 + defaultFilterChain: + 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 + httpProtocolOptions: + enableTrailers: true + mergeSlashes: true + normalizePath: true + pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: http + upgradeConfigs: + - upgradeType: websocket + useRemoteAddress: true + name: first-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http1-trailers.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http1-trailers.routes.yaml new file mode 100644 index 00000000000..2734c7cc42a --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http1-trailers.routes.yaml @@ -0,0 +1,12 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + prefix: / + name: first-route + route: + cluster: first-route-dest diff --git a/internal/xds/translator/testdata/out/xds-ir/http10.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/http10.clusters.yaml new file mode 100644 index 00000000000..5fe5a91e3ed --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http10.clusters.yaml @@ -0,0 +1,21 @@ +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: first-route-dest + lbPolicy: LEAST_REQUEST + name: first-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS + typedExtensionProtocolOptions: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicitHttpConfig: + httpProtocolOptions: + acceptHttp10: true + defaultHostForHttp10: foo.com diff --git a/internal/xds/translator/testdata/out/xds-ir/http10.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/http10.endpoints.yaml new file mode 100644 index 00000000000..3b3f2d09076 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http10.endpoints.yaml @@ -0,0 +1,12 @@ +- clusterName: first-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: first-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/http10.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http10.listeners.yaml new file mode 100644 index 00000000000..cb4e1c75776 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http10.listeners.yaml @@ -0,0 +1,38 @@ +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10080 + defaultFilterChain: + 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 + httpProtocolOptions: + acceptHttp10: true + defaultHostForHttp10: foo.com + mergeSlashes: true + normalizePath: true + pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: http + upgradeConfigs: + - upgradeType: websocket + useRemoteAddress: true + name: first-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http10.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http10.routes.yaml new file mode 100644 index 00000000000..2734c7cc42a --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http10.routes.yaml @@ -0,0 +1,12 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + prefix: / + name: first-route + route: + cluster: first-route-dest diff --git a/internal/xds/translator/testdata/out/xds-ir/http2-route.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http2-route.listeners.yaml index 52a0307d76a..299ae39cd94 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http2-route.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http2-route.listeners.yaml @@ -25,6 +25,7 @@ - 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 @@ -33,6 +34,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http useRemoteAddress: true name: first-listener diff --git a/internal/xds/translator/testdata/out/xds-ir/http3.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http3.listeners.yaml index d345cc14e96..5c05193ce62 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http3.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http3.listeners.yaml @@ -20,6 +20,7 @@ - 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 @@ -28,6 +29,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: envoy-gateway/gateway-1/tls + serverHeaderTransformation: PASS_THROUGH statPrefix: https upgradeConfigs: - upgradeType: websocket @@ -45,7 +47,6 @@ sdsConfig: ads: {} resourceApiVersion: V3 - requireClientCertificate: false name: envoy-gateway/gateway-1/tls-quic udpListenerConfig: downstreamSocketConfig: {} @@ -69,6 +70,7 @@ - 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 @@ -77,6 +79,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: envoy-gateway/gateway-1/tls + serverHeaderTransformation: PASS_THROUGH statPrefix: https upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-without-value.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-without-value.clusters.yaml new file mode 100644 index 00000000000..c8692b81602 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-without-value.clusters.yaml @@ -0,0 +1,14 @@ +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: first-route-dest + lbPolicy: LEAST_REQUEST + name: first-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-without-value.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-without-value.endpoints.yaml new file mode 100644 index 00000000000..3b3f2d09076 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-without-value.endpoints.yaml @@ -0,0 +1,12 @@ +- clusterName: first-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: first-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-without-value.envoypatchpolicies.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-without-value.envoypatchpolicies.yaml new file mode 100644 index 00000000000..55cdd5c4cb2 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-without-value.envoypatchpolicies.yaml @@ -0,0 +1,9 @@ +- name: first-policy + namespace: default + status: + conditions: + - lastTransitionTime: null + message: The add operation requires a value + reason: Invalid + status: "False" + type: Programmed diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-without-value.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-without-value.listeners.yaml new file mode 100644 index 00000000000..d0e88f02b41 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-without-value.listeners.yaml @@ -0,0 +1,63 @@ +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10080 + filterChains: + - 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.ratelimit + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit + domain: eg-ratelimit + failureModeDeny: true + rateLimitService: + grpcService: + envoyGrpc: + clusterName: rate-limit-cluster + transportApiVersion: V3 + timeout: 1s + - 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: first-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: https + upgradeConfigs: + - upgradeType: websocket + useRemoteAddress: true + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + commonTlsContext: + alpnProtocols: + - h2 + - http/1.1 + tlsCertificateSdsSecretConfigs: + - name: secret-1 + sdsConfig: + ads: {} + resourceApiVersion: V3 + - name: secret-2 + sdsConfig: + ads: {} + resourceApiVersion: V3 + name: first-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-without-value.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-without-value.routes.yaml new file mode 100644 index 00000000000..dc48be19646 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-without-value.routes.yaml @@ -0,0 +1,16 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + headers: + - name: user + stringMatch: + exact: jason + prefix: / + name: first-route + route: + cluster: first-route-dest diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-invalid-patch.envoypatchpolicies.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-invalid-patch.envoypatchpolicies.yaml index 9ff692421b9..8d9f6918bd1 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-invalid-patch.envoypatchpolicies.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-invalid-patch.envoypatchpolicies.yaml @@ -3,8 +3,8 @@ status: conditions: - lastTransitionTime: null - message: 'unable to unmarshal xds resource {"name":"first-listener","address":{"socket_address":{"address":"0.0.0.0","port_value":10080}},"default_filter_chain":{"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":"http","rds":{"config_source":{"ads":{},"resource_api_version":"V3"},"route_config_name":"first-listener"},"http_filters":[{"name":"envoy.filters.http.router","typed_config":{"@type":"type.googleapis.com/envoy.extensions.filters.http.router.v3.Router"}}],"common_http_protocol_options":{"headers_with_underscores_action":"REJECT_REQUEST"},"http2_protocol_options":{"max_concurrent_streams":100,"initial_stream_window_size":65536,"initial_connection_window_size":1048576},"use_remote_address":true,"upgrade_configs":[{"upgrade_type":"websocket"}],"normalize_path":true,"merge_slashes":true,"path_with_escaped_slashes_action":"UNESCAPE_AND_REDIRECT"}}]},"per_connection_buffer_limit_bytes":32768,"this":{"path":{"never":{"existed":{"name":"envoy.filters.http.ratelimit","typed_config":{"@type":"type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit","domain":"eg-ratelimit","failure_mode_deny":true,"rate_limit_service":{"grpc_service":{"envoy_grpc":{"cluster_name":"rate-limit-cluster"}},"transport_api_version":"V3"},"timeout":"1s"}}}}}}, - err:proto: (line 1:1023): unknown field "this"' + message: 'unable to unmarshal xds resource {"name":"first-listener","address":{"socket_address":{"address":"0.0.0.0","port_value":10080}},"default_filter_chain":{"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":"http","rds":{"config_source":{"ads":{},"resource_api_version":"V3"},"route_config_name":"first-listener"},"http_filters":[{"name":"envoy.filters.http.router","typed_config":{"@type":"type.googleapis.com/envoy.extensions.filters.http.router.v3.Router","suppress_envoy_headers":true}}],"common_http_protocol_options":{"headers_with_underscores_action":"REJECT_REQUEST"},"http2_protocol_options":{"max_concurrent_streams":100,"initial_stream_window_size":65536,"initial_connection_window_size":1048576},"server_header_transformation":"PASS_THROUGH","use_remote_address":true,"upgrade_configs":[{"upgrade_type":"websocket"}],"normalize_path":true,"merge_slashes":true,"path_with_escaped_slashes_action":"UNESCAPE_AND_REDIRECT"}}]},"per_connection_buffer_limit_bytes":32768,"this":{"path":{"never":{"existed":{"name":"envoy.filters.http.ratelimit","typed_config":{"@type":"type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit","domain":"eg-ratelimit","failure_mode_deny":true,"rate_limit_service":{"grpc_service":{"envoy_grpc":{"cluster_name":"rate-limit-cluster"}},"transport_api_version":"V3"},"timeout":"1s"}}}}}}, + err:proto: (line 1:1099): unknown field "this"' reason: Invalid status: "False" type: Programmed diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-invalid-patch.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-invalid-patch.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-invalid-patch.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-invalid-patch.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-missing-resource.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-missing-resource.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-missing-resource.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-missing-resource.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-move-op-with-value.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-move-op-with-value.clusters.yaml new file mode 100644 index 00000000000..c8692b81602 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-move-op-with-value.clusters.yaml @@ -0,0 +1,14 @@ +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: first-route-dest + lbPolicy: LEAST_REQUEST + name: first-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-move-op-with-value.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-move-op-with-value.endpoints.yaml new file mode 100644 index 00000000000..3b3f2d09076 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-move-op-with-value.endpoints.yaml @@ -0,0 +1,12 @@ +- clusterName: first-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: first-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-move-op-with-value.envoypatchpolicies.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-move-op-with-value.envoypatchpolicies.yaml new file mode 100644 index 00000000000..fd77280814f --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-move-op-with-value.envoypatchpolicies.yaml @@ -0,0 +1,9 @@ +- name: first-policy + namespace: default + status: + conditions: + - lastTransitionTime: null + message: The value field can not be set for the remove operation + reason: Invalid + status: "False" + type: Programmed diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-move-op-with-value.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-move-op-with-value.listeners.yaml new file mode 100644 index 00000000000..d0e88f02b41 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-move-op-with-value.listeners.yaml @@ -0,0 +1,63 @@ +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10080 + filterChains: + - 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.ratelimit + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit + domain: eg-ratelimit + failureModeDeny: true + rateLimitService: + grpcService: + envoyGrpc: + clusterName: rate-limit-cluster + transportApiVersion: V3 + timeout: 1s + - 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: first-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: https + upgradeConfigs: + - upgradeType: websocket + useRemoteAddress: true + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + commonTlsContext: + alpnProtocols: + - h2 + - http/1.1 + tlsCertificateSdsSecretConfigs: + - name: secret-1 + sdsConfig: + ads: {} + resourceApiVersion: V3 + - name: secret-2 + sdsConfig: + ads: {} + resourceApiVersion: V3 + name: first-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-move-op-with-value.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-move-op-with-value.routes.yaml new file mode 100644 index 00000000000..dc48be19646 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-move-op-with-value.routes.yaml @@ -0,0 +1,16 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + headers: + - name: user + stringMatch: + exact: jason + prefix: / + name: first-route + route: + cluster: first-route-dest diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch.endpoints.yaml index a9249b45d31..bb6563435b1 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jsonpatch.endpoints.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch.endpoints.yaml @@ -10,3 +10,11 @@ loadBalancingWeight: 50 locality: region: first-route-dest/backend/0 + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 50 diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch.listeners.yaml index f99ed727079..d0e88f02b41 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jsonpatch.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch.listeners.yaml @@ -2,8 +2,8 @@ socketAddress: address: 0.0.0.0 portValue: 10080 - defaultFilterChain: - filters: + filterChains: + - filters: - name: envoy.filters.network.http_connection_manager typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager @@ -28,6 +28,7 @@ - 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 @@ -36,9 +37,27 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener - statPrefix: http + serverHeaderTransformation: PASS_THROUGH + statPrefix: https upgradeConfigs: - upgradeType: websocket useRemoteAddress: true + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + commonTlsContext: + alpnProtocols: + - h2 + - http/1.1 + tlsCertificateSdsSecretConfigs: + - name: secret-1 + sdsConfig: + ads: {} + resourceApiVersion: V3 + - name: secret-2 + sdsConfig: + ads: {} + resourceApiVersion: V3 name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch.secrets.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch.secrets.yaml new file mode 100644 index 00000000000..d1c4b32fd5f --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch.secrets.yaml @@ -0,0 +1,16 @@ +- name: secret-1 + tlsCertificate: + certificateChain: + inlineBytes: a2V5LWRhdGE= + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: secret-2 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: test_secret + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-custom-extractor.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-custom-extractor.clusters.yaml index 7c8285ba0f6..9b85cda2aa1 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-custom-extractor.clusters.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-custom-extractor.clusters.yaml @@ -43,4 +43,5 @@ validationContext: trustedCa: filename: /etc/ssl/certs/ca-certificates.crt + sni: localhost type: STRICT_DNS diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-custom-extractor.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-custom-extractor.listeners.yaml index 3bd76da8af0..b8a88fd7937 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-custom-extractor.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-custom-extractor.listeners.yaml @@ -24,6 +24,11 @@ forward: true fromCookies: - session_access_token + fromHeaders: + - name: Authorization + valuePrefix: 'Bearer ' + fromParams: + - token issuer: https://www.example.com payloadInMetadata: https://www.example.com remoteJwks: @@ -31,7 +36,7 @@ cacheDuration: 300s httpUri: cluster: localhost_443 - timeout: 5s + timeout: 10s uri: https://localhost/jwt/public-key/jwks.json retryPolicy: {} requirementMap: @@ -40,6 +45,7 @@ - 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 @@ -48,6 +54,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.clusters.yaml index ecb9808182b..d760d2ca25a 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.clusters.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.clusters.yaml @@ -71,4 +71,5 @@ validationContext: trustedCa: filename: /etc/ssl/certs/ca-certificates.crt + sni: 192.168.1.250 type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.listeners.yaml index 5eec374480d..df761c63a07 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.listeners.yaml @@ -32,7 +32,7 @@ cacheDuration: 300s httpUri: cluster: localhost_80 - timeout: 5s + timeout: 10s uri: http://localhost/jwt/public-key/jwks.json retryPolicy: {} first-route-www.test.com/example2: @@ -52,7 +52,7 @@ cacheDuration: 300s httpUri: cluster: "192_168_1_250_8080" - timeout: 5s + timeout: 10s uri: https://192.168.1.250:8080/jwt/public-key/jwks.json retryPolicy: {} second-route-www.test.com/example: @@ -69,7 +69,7 @@ cacheDuration: 300s httpUri: cluster: localhost_80 - timeout: 5s + timeout: 10s uri: http://localhost/jwt/public-key/jwks.json retryPolicy: {} second-route-www.test.com/example2: @@ -84,7 +84,7 @@ cacheDuration: 300s httpUri: cluster: "192_168_1_250_8080" - timeout: 5s + timeout: 10s uri: https://192.168.1.250:8080/jwt/public-key/jwks.json retryPolicy: {} requirementMap: @@ -101,6 +101,7 @@ - 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 @@ -109,6 +110,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.clusters.yaml index f18c018dd7c..45b8763385e 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.clusters.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.clusters.yaml @@ -57,4 +57,5 @@ validationContext: trustedCa: filename: /etc/ssl/certs/ca-certificates.crt + sni: localhost type: STRICT_DNS diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.listeners.yaml index bc515a98bb8..e16c2673208 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.listeners.yaml @@ -54,7 +54,7 @@ cacheDuration: 300s httpUri: cluster: localhost_443 - timeout: 5s + timeout: 10s uri: https://localhost/jwt/public-key/jwks.json retryPolicy: {} second-route/example: @@ -68,7 +68,7 @@ cacheDuration: 300s httpUri: cluster: localhost_443 - timeout: 5s + timeout: 10s uri: https://localhost/jwt/public-key/jwks.json retryPolicy: {} requirementMap: @@ -79,6 +79,7 @@ - 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 @@ -87,6 +88,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.clusters.yaml index 353a2a7f696..bc0cd764256 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.clusters.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.clusters.yaml @@ -61,6 +61,7 @@ validationContext: trustedCa: filename: /etc/ssl/certs/ca-certificates.crt + sni: 192.168.1.250 type: EDS - commonLbConfig: localityWeightedLbConfig: {} diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.listeners.yaml index 797be82e982..72c2f332e63 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.listeners.yaml @@ -29,7 +29,7 @@ cacheDuration: 300s httpUri: cluster: "192_168_1_250_443" - timeout: 5s + timeout: 10s uri: https://192.168.1.250/jwt/public-key/jwks.json retryPolicy: {} requirementMap: @@ -48,6 +48,7 @@ - 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 @@ -56,6 +57,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.clusters.yaml index 7c8285ba0f6..9b85cda2aa1 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.clusters.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.clusters.yaml @@ -43,4 +43,5 @@ validationContext: trustedCa: filename: /etc/ssl/certs/ca-certificates.crt + sni: localhost type: STRICT_DNS diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.listeners.yaml index e268247f475..945509a0522 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.listeners.yaml @@ -29,7 +29,7 @@ cacheDuration: 300s httpUri: cluster: localhost_443 - timeout: 5s + timeout: 10s uri: https://localhost/jwt/public-key/jwks.json retryPolicy: {} requirementMap: @@ -38,6 +38,7 @@ - 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 @@ -46,6 +47,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/listener-proxy-protocol.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/listener-proxy-protocol.listeners.yaml index 5d4a7fbce0f..4df723a0307 100644 --- a/internal/xds/translator/testdata/out/xds-ir/listener-proxy-protocol.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/listener-proxy-protocol.listeners.yaml @@ -20,6 +20,7 @@ - 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 @@ -28,6 +29,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: https upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.listeners.yaml index 09334586970..203f36be5a5 100644 --- a/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket @@ -55,6 +57,7 @@ - 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 @@ -63,6 +66,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: second-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/load-balancer.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/load-balancer.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/load-balancer.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/load-balancer.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/local-ratelimit.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/local-ratelimit.listeners.yaml index d9d4a248f2d..3841aa65768 100644 --- a/internal/xds/translator/testdata/out/xds-ir/local-ratelimit.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/local-ratelimit.listeners.yaml @@ -21,6 +21,7 @@ - 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 @@ -29,6 +30,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/metrics-virtual-host.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/metrics-virtual-host.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/metrics-virtual-host.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/metrics-virtual-host.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.listeners.yaml index 096b2e7add4..85bb8b4ac73 100644 --- a/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/mixed-tls-jwt-authn.listeners.yaml @@ -37,6 +37,7 @@ - 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 @@ -45,6 +46,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: https upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port.listeners.yaml index 632271fe590..102fe74e070 100644 --- a/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: third-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket @@ -47,6 +49,7 @@ - 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 @@ -55,6 +58,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: https upgradeConfigs: - upgradeType: websocket @@ -89,6 +93,7 @@ - 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 @@ -97,6 +102,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: second-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: https upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/mutual-tls.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/mutual-tls.clusters.yaml new file mode 100644 index 00000000000..c8692b81602 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/mutual-tls.clusters.yaml @@ -0,0 +1,14 @@ +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: first-route-dest + lbPolicy: LEAST_REQUEST + name: first-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/mutual-tls.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/mutual-tls.endpoints.yaml new file mode 100644 index 00000000000..3b3f2d09076 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/mutual-tls.endpoints.yaml @@ -0,0 +1,12 @@ +- clusterName: first-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: first-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/mutual-tls.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/mutual-tls.listeners.yaml new file mode 100644 index 00000000000..4726fb8aa0e --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/mutual-tls.listeners.yaml @@ -0,0 +1,58 @@ +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10080 + filterChains: + - 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: first-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: https + upgradeConfigs: + - upgradeType: websocket + useRemoteAddress: true + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext + commonTlsContext: + alpnProtocols: + - h2 + - http/1.1 + tlsCertificateSdsSecretConfigs: + - name: secret-1 + sdsConfig: + ads: {} + resourceApiVersion: V3 + - name: secret-2 + sdsConfig: + ads: {} + resourceApiVersion: V3 + validationContextSdsSecretConfig: + name: ca-cert + sdsConfig: + ads: {} + resourceApiVersion: V3 + requireClientCertificate: true + name: first-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/mutual-tls.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/mutual-tls.routes.yaml new file mode 100644 index 00000000000..2734c7cc42a --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/mutual-tls.routes.yaml @@ -0,0 +1,12 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + prefix: / + name: first-route + route: + cluster: first-route-dest diff --git a/internal/xds/translator/testdata/out/xds-ir/mutual-tls.secrets.yaml b/internal/xds/translator/testdata/out/xds-ir/mutual-tls.secrets.yaml new file mode 100644 index 00000000000..052882baf5f --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/mutual-tls.secrets.yaml @@ -0,0 +1,16 @@ +- name: secret-1 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: secret-2 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: ca-cert + validationContext: + trustedCa: + inlineBytes: Y2VydC1kYXRh diff --git a/internal/xds/translator/testdata/out/xds-ir/oidc.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/oidc.clusters.yaml index 7ea2bfaed89..2903bb5f9c4 100644 --- a/internal/xds/translator/testdata/out/xds-ir/oidc.clusters.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/oidc.clusters.yaml @@ -53,6 +53,10 @@ name: envoy.transport_sockets.tls typedConfig: '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + commonTlsContext: + validationContext: + trustedCa: + filename: /etc/ssl/certs/ca-certificates.crt sni: oauth.foo.com type: STRICT_DNS - commonLbConfig: @@ -82,5 +86,9 @@ name: envoy.transport_sockets.tls typedConfig: '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + commonTlsContext: + validationContext: + trustedCa: + filename: /etc/ssl/certs/ca-certificates.crt sni: oauth.bar.com type: STRICT_DNS diff --git a/internal/xds/translator/testdata/out/xds-ir/oidc.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/oidc.listeners.yaml index aec460ab569..abadd4dd23c 100644 --- a/internal/xds/translator/testdata/out/xds-ir/oidc.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/oidc.listeners.yaml @@ -14,7 +14,8 @@ initialStreamWindowSize: 65536 maxConcurrentStreams: 100 httpFilters: - - name: envoy.filters.http.oauth2_first-route + - disabled: true + name: envoy.filters.http.oauth2_first-route typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.http.oauth2.v3.OAuth2 config: @@ -26,6 +27,12 @@ authorizationEndpoint: https://oauth.foo.com/oauth2/v2/auth credentials: clientId: client.oauth.foo.com + cookieNames: + bearerToken: BearerToken-5F93C2E4 + idToken: IdToken-5F93C2E4 + oauthExpires: OauthExpires-5F93C2E4 + oauthHmac: OauthHMAC-5F93C2E4 + refreshToken: RefreshToken-5F93C2E4 hmacSecret: name: first-route/oauth2/hmac_secret sdsConfig: @@ -48,7 +55,8 @@ cluster: oauth_foo_com_443 timeout: 10s uri: https://oauth.foo.com/token - - name: envoy.filters.http.oauth2_second-route + - disabled: true + name: envoy.filters.http.oauth2_second-route typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.http.oauth2.v3.OAuth2 config: @@ -60,6 +68,12 @@ authorizationEndpoint: https://oauth.bar.com/oauth2/v2/auth credentials: clientId: client.oauth.bar.com + cookieNames: + bearerToken: BearerToken-B0A1B740 + idToken: IdToken-B0A1B740 + oauthExpires: OauthExpires-B0A1B740 + oauthHmac: OauthHMAC-B0A1B740 + refreshToken: RefreshToken-B0A1B740 hmacSecret: name: second-route/oauth2/hmac_secret sdsConfig: @@ -85,6 +99,7 @@ - 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 @@ -93,6 +108,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/oidc.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/oidc.routes.yaml index cffe6c9ebcb..f4ba1044899 100644 --- a/internal/xds/translator/testdata/out/xds-ir/oidc.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/oidc.routes.yaml @@ -1,12 +1,5 @@ - ignorePortInHostMatching: true name: first-listener - typedPerFilterConfig: - envoy.filters.http.oauth2_first-route: - '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig - disabled: true - envoy.filters.http.oauth2_second-route: - '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig - disabled: true virtualHosts: - domains: - '*' diff --git a/internal/xds/translator/testdata/out/xds-ir/path-settings.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/path-settings.listeners.yaml index c2a3253485a..88def256e95 100644 --- a/internal/xds/translator/testdata/out/xds-ir/path-settings.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/path-settings.listeners.yaml @@ -17,6 +17,7 @@ - name: envoy.filters.http.router typedConfig: '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + suppressEnvoyHeaders: true normalizePath: true pathWithEscapedSlashesAction: UNESCAPE_AND_FORWARD rds: @@ -24,6 +25,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/proxy-protocol-upstream.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/proxy-protocol-upstream.listeners.yaml index 73ee1b42ef6..046589e0fd8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/proxy-protocol-upstream.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/proxy-protocol-upstream.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/ratelimit-custom-domain.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/ratelimit-custom-domain.listeners.yaml index 664151e574d..be0d4a05bfd 100644 --- a/internal/xds/translator/testdata/out/xds-ir/ratelimit-custom-domain.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/ratelimit-custom-domain.listeners.yaml @@ -27,6 +27,7 @@ - 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 @@ -35,6 +36,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/ratelimit-sourceip.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/ratelimit-sourceip.listeners.yaml index 664151e574d..be0d4a05bfd 100644 --- a/internal/xds/translator/testdata/out/xds-ir/ratelimit-sourceip.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/ratelimit-sourceip.listeners.yaml @@ -27,6 +27,7 @@ - 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 @@ -35,6 +36,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/ratelimit.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/ratelimit.listeners.yaml index 664151e574d..be0d4a05bfd 100644 --- a/internal/xds/translator/testdata/out/xds-ir/ratelimit.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/ratelimit.listeners.yaml @@ -27,6 +27,7 @@ - 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 @@ -35,6 +36,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/simple-tls.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/simple-tls.listeners.yaml index bfefb01d958..3fd6384f903 100644 --- a/internal/xds/translator/testdata/out/xds-ir/simple-tls.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/simple-tls.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: https upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.listeners.yaml index d6373f2d41b..9c68dc1ab54 100644 --- a/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.listeners.yaml @@ -20,7 +20,6 @@ - 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 @@ -29,6 +28,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: https upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/timeout.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/timeout.clusters.yaml new file mode 100644 index 00000000000..7515ac9e7d6 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/timeout.clusters.yaml @@ -0,0 +1,22 @@ +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 31s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: first-route-dest + lbPolicy: LEAST_REQUEST + name: first-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS + typedExtensionProtocolOptions: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + commonHttpProtocolOptions: + idleTimeout: 32s + maxConnectionDuration: 33s + explicitHttpConfig: + httpProtocolOptions: {} diff --git a/internal/xds/translator/testdata/out/xds-ir/timeout.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/timeout.endpoints.yaml new file mode 100644 index 00000000000..3b3f2d09076 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/timeout.endpoints.yaml @@ -0,0 +1,12 @@ +- clusterName: first-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: first-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/timeout.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/timeout.listeners.yaml new file mode 100644 index 00000000000..046589e0fd8 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/timeout.listeners.yaml @@ -0,0 +1,35 @@ +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10080 + defaultFilterChain: + 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: first-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: http + upgradeConfigs: + - upgradeType: websocket + useRemoteAddress: true + name: first-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/timeout.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/timeout.routes.yaml new file mode 100644 index 00000000000..2734c7cc42a --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/timeout.routes.yaml @@ -0,0 +1,12 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + prefix: / + name: first-route + route: + cluster: first-route-dest diff --git a/internal/xds/translator/testdata/out/xds-ir/tls-with-ciphers-versions-alpn.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/tls-with-ciphers-versions-alpn.listeners.yaml index 9262e69ff1c..a404ab4d9f6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/tls-with-ciphers-versions-alpn.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/tls-with-ciphers-versions-alpn.listeners.yaml @@ -20,6 +20,7 @@ - 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 @@ -28,6 +29,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: https upgradeConfigs: - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/tracing.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/tracing.listeners.yaml index ab0c03da06a..e27bb6fec3a 100644 --- a/internal/xds/translator/testdata/out/xds-ir/tracing.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/tracing.listeners.yaml @@ -17,6 +17,7 @@ - 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 @@ -25,6 +26,7 @@ ads: {} resourceApiVersion: V3 routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH statPrefix: http tracing: clientSampling: diff --git a/internal/xds/translator/testdata/out/xds-ir/upstream-tcpkeepalive.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/upstream-tcpkeepalive.clusters.yaml new file mode 100644 index 00000000000..8064de8d285 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/upstream-tcpkeepalive.clusters.yaml @@ -0,0 +1,19 @@ +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: first-route-dest + lbPolicy: LEAST_REQUEST + name: first-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS + upstreamConnectionOptions: + tcpKeepalive: + keepaliveInterval: 60 + keepaliveProbes: 3 + keepaliveTime: 1200 diff --git a/internal/xds/translator/testdata/out/xds-ir/upstream-tcpkeepalive.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/upstream-tcpkeepalive.endpoints.yaml new file mode 100644 index 00000000000..3b3f2d09076 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/upstream-tcpkeepalive.endpoints.yaml @@ -0,0 +1,12 @@ +- clusterName: first-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: first-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/upstream-tcpkeepalive.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/upstream-tcpkeepalive.listeners.yaml new file mode 100644 index 00000000000..046589e0fd8 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/upstream-tcpkeepalive.listeners.yaml @@ -0,0 +1,35 @@ +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10080 + defaultFilterChain: + 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: first-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: http + upgradeConfigs: + - upgradeType: websocket + useRemoteAddress: true + name: first-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/upstream-tcpkeepalive.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/upstream-tcpkeepalive.routes.yaml new file mode 100644 index 00000000000..2734c7cc42a --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/upstream-tcpkeepalive.routes.yaml @@ -0,0 +1,12 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + prefix: / + name: first-route + route: + cluster: first-route-dest diff --git a/internal/xds/translator/translator.go b/internal/xds/translator/translator.go index bbb350565db..4ce82ca543f 100644 --- a/internal/xds/translator/translator.go +++ b/internal/xds/translator/translator.go @@ -19,7 +19,6 @@ import ( tlsv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" matcherv3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" resourcev3 "github.com/envoyproxy/go-control-plane/pkg/resource/v3" - "github.com/tetratelabs/multierror" "google.golang.org/protobuf/types/known/wrapperspb" extensionTypes "github.com/envoyproxy/gateway/internal/extension/types" @@ -79,32 +78,32 @@ func (t *Translator) Translate(ir *ir.Xds) (*types.ResourceVersionTable, error) var errs error if err := t.processHTTPListenerXdsTranslation( tCtx, ir.HTTP, ir.AccessLog, ir.Tracing, ir.Metrics); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } if err := processTCPListenerXdsTranslation(tCtx, ir.TCP, ir.AccessLog); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } if err := processUDPListenerXdsTranslation(tCtx, ir.UDP, ir.AccessLog); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } if err := processJSONPatches(tCtx, ir.EnvoyPatchPolicies); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } if err := processClusterForAccessLog(tCtx, ir.AccessLog); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } if err := processClusterForTracing(tCtx, ir.Tracing); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } // Check if an extension want to inject any clusters/secrets // If no extension exists (or it doesn't subscribe to this hook) then this is a quick no-op if err := processExtensionPostTranslationHook(tCtx, t.ExtensionManager); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } return tCtx, errs @@ -139,7 +138,7 @@ func (t *Translator) processHTTPListenerXdsTranslation( if err := tCtx.AddXdsResource(resourcev3.ListenerType, xdsListener); err != nil { // skip this listener if failed to add xds listener to the // resource version table. Normally, this should not happen. - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) continue } } else if httpListener.TLS == nil { @@ -154,7 +153,7 @@ func (t *Translator) processHTTPListenerXdsTranslation( xdsRouteCfg = findXdsRouteConfig(tCtx, routeName) if xdsRouteCfg == nil { // skip this listener if failed to find xds route config - errs = multierror.Append(errs, errors.New("unable to find xds route config")) + errs = errors.Join(errs, errors.New("unable to find xds route config")) continue } } @@ -179,16 +178,23 @@ func (t *Translator) processHTTPListenerXdsTranslation( } if err := tCtx.AddXdsResource(resourcev3.RouteType, xdsRouteCfg); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } // 1:1 between IR TLSListenerConfig and xDS Secret if httpListener.TLS != nil { for t := range httpListener.TLS.Certificates { - secret := buildXdsDownstreamTLSSecret(httpListener.TLS.Certificates[t]) + secret := buildXdsTLSCertSecret(httpListener.TLS.Certificates[t]) if err := tCtx.AddXdsResource(resourcev3.SecretType, secret); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) + } + } + + if httpListener.TLS.CACertificate != nil { + caSecret := buildXdsTLSCaCertSecret(httpListener.TLS.CACertificate) + if err := tCtx.AddXdsResource(resourcev3.SecretType, caSecret); err != nil { + errs = errors.Join(errs, err) } } } @@ -238,7 +244,7 @@ func (t *Translator) processHTTPListenerXdsTranslation( xdsRoute, err := buildXdsRoute(httpRoute) if err != nil { // skip this route if failed to build xds route - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) continue } @@ -246,7 +252,7 @@ func (t *Translator) processHTTPListenerXdsTranslation( // If no extension exists (or it doesn't subscribe to this hook) then this is a quick no-op. if err = processExtensionPostRouteHook(xdsRoute, vHost, httpRoute, t.ExtensionManager); err != nil { if err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } @@ -260,8 +266,8 @@ func (t *Translator) processHTTPListenerXdsTranslation( vHost.Routes = append(vHost.Routes, xdsRoute) if httpRoute.Destination != nil { - if err = processXdsCluster(tCtx, httpRoute); err != nil { - errs = multierror.Append(errs, err) + if err = processXdsCluster(tCtx, httpRoute, httpListener.HTTP1); err != nil { + errs = errors.Join(errs, err) } } @@ -273,7 +279,7 @@ func (t *Translator) processHTTPListenerXdsTranslation( tSocket: nil, endpointType: EndpointTypeStatic, }); err != nil && !errors.Is(err, ErrXdsClusterExists) { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } } @@ -283,16 +289,11 @@ func (t *Translator) processHTTPListenerXdsTranslation( // Check if an extension want to modify the Virtual Host we just generated // If no extension exists (or it doesn't subscribe to this hook) then this is a quick no-op. if err := processExtensionPostVHostHook(vHost, t.ExtensionManager); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } xdsRouteCfg.VirtualHosts = append(xdsRouteCfg.VirtualHosts, vHostsList...) - // Add per-route filter configs to the route config. - if err := patchRouteCfgWithPerRouteConfig(xdsRouteCfg, httpListener); err != nil { - errs = multierror.Append(errs, err) - } - // Add all the other needed resources referenced by this filter to the // resource version table. if err := patchResources(tCtx, httpListener.Routes); err != nil { @@ -303,13 +304,13 @@ func (t *Translator) processHTTPListenerXdsTranslation( // rate limit server configuration. // Check if a ratelimit cluster exists, if not, add it, if it's needed. if err := t.createRateLimitServiceCluster(tCtx, httpListener); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } // Check if an extension want to modify the listener that was just configured/created // If no extension exists (or it doesn't subscribe to this hook) then this is a quick no-op if err := processExtensionPostListenerHook(tCtx, xdsListener, t.ExtensionManager); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } @@ -337,13 +338,13 @@ func processTCPListenerXdsTranslation(tCtx *types.ResourceVersionTable, tcpListe xdsListener = buildXdsTCPListener(tcpListener.Name, tcpListener.Address, tcpListener.Port, tcpListener.TCPKeepalive, accesslog) if err := tCtx.AddXdsResource(resourcev3.ListenerType, xdsListener); err != nil { // skip this listener if failed to add xds listener to the - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) continue } } if err := addXdsTCPFilterChain(xdsListener, tcpListener, tcpListener.Destination.Name, accesslog); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } // 1:1 between IR TCPListener and xDS Cluster @@ -353,14 +354,20 @@ func processTCPListenerXdsTranslation(tCtx *types.ResourceVersionTable, tcpListe tSocket: nil, endpointType: EndpointTypeStatic, }); err != nil && !errors.Is(err, ErrXdsClusterExists) { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } if tcpListener.TLS != nil && tcpListener.TLS.Terminate != nil { for _, s := range tcpListener.TLS.Terminate.Certificates { - secret := buildXdsDownstreamTLSSecret(s) + secret := buildXdsTLSCertSecret(s) if err := tCtx.AddXdsResource(resourcev3.SecretType, secret); err != nil { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) + } + } + if tcpListener.TLS.Terminate.CACertificate != nil { + caSecret := buildXdsTLSCaCertSecret(tcpListener.TLS.Terminate.CACertificate) + if err := tCtx.AddXdsResource(resourcev3.SecretType, caSecret); err != nil { + errs = errors.Join(errs, err) } } } @@ -379,12 +386,12 @@ func processUDPListenerXdsTranslation(tCtx *types.ResourceVersionTable, udpListe xdsListener, err := buildXdsUDPListener(udpListener.Destination.Name, udpListener, accesslog) if err != nil { // skip this listener if failed to build xds listener - errs = multierror.Append(errs, err) + 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 = multierror.Append(errs, err) + errs = errors.Join(errs, err) continue } @@ -395,7 +402,7 @@ func processUDPListenerXdsTranslation(tCtx *types.ResourceVersionTable, udpListe tSocket: nil, endpointType: EndpointTypeStatic, }); err != nil && !errors.Is(err, ErrXdsClusterExists) { - errs = multierror.Append(errs, err) + errs = errors.Join(errs, err) } } return errs @@ -485,7 +492,7 @@ func findXdsEndpoint(tCtx *types.ResourceVersionTable, name string) *endpointv3. } // processXdsCluster processes a xds cluster by its endpoint address type. -func processXdsCluster(tCtx *types.ResourceVersionTable, httpRoute *ir.HTTPRoute) error { +func processXdsCluster(tCtx *types.ResourceVersionTable, httpRoute *ir.HTTPRoute, http1Settings *ir.HTTP1Settings) error { // Get endpoint address type for xds cluster by returning the first DestinationSetting's AddressType, // since there's no Mixed AddressType among all the DestinationSettings. addrTypeState := httpRoute.Destination.Settings[0].AddressType @@ -506,6 +513,9 @@ func processXdsCluster(tCtx *types.ResourceVersionTable, httpRoute *ir.HTTPRoute proxyProtocol: httpRoute.ProxyProtocol, circuitBreaker: httpRoute.CircuitBreaker, healthCheck: httpRoute.HealthCheck, + http1Settings: http1Settings, + timeout: httpRoute.Timeout, + tcpkeepalive: httpRoute.TCPKeepalive, }); err != nil && !errors.Is(err, ErrXdsClusterExists) { return err } diff --git a/internal/xds/translator/translator_test.go b/internal/xds/translator/translator_test.go index e319f876e8a..761b6345621 100644 --- a/internal/xds/translator/translator_test.go +++ b/internal/xds/translator/translator_test.go @@ -94,6 +94,10 @@ func TestTranslateXds(t *testing.T) { name: "simple-tls", requireSecrets: true, }, + { + name: "mutual-tls", + requireSecrets: true, + }, { name: "http3", requireSecrets: true, @@ -167,6 +171,7 @@ func TestTranslateXds(t *testing.T) { { name: "jsonpatch", requireEnvoyPatchPolicies: true, + requireSecrets: true, }, { name: "jsonpatch-missing-resource", @@ -176,6 +181,14 @@ func TestTranslateXds(t *testing.T) { name: "jsonpatch-invalid-patch", requireEnvoyPatchPolicies: true, }, + { + name: "jsonpatch-add-op-without-value", + requireEnvoyPatchPolicies: true, + }, + { + name: "jsonpatch-move-op-with-value", + requireEnvoyPatchPolicies: true, + }, { name: "listener-tcp-keepalive", }, @@ -236,6 +249,30 @@ func TestTranslateXds(t *testing.T) { { name: "path-settings", }, + { + name: "client-ip-detection", + }, + { + name: "http1-trailers", + }, + { + name: "http1-preserve-case", + }, + { + name: "timeout", + }, + { + name: "ext-auth", + }, + { + name: "http10", + }, + { + name: "upstream-tcpkeepalive", + }, + { + name: "client-timeout", + }, } for _, tc := range testCases { diff --git a/internal/xds/translator/utils.go b/internal/xds/translator/utils.go index 01518c69d2c..01d9939badb 100644 --- a/internal/xds/translator/utils.go +++ b/internal/xds/translator/utils.go @@ -8,7 +8,7 @@ package translator import ( "errors" "fmt" - "net" + "net/netip" "net/url" "strconv" "strings" @@ -20,8 +20,9 @@ import ( ) const ( - defaultHTTPSPort uint64 = 443 - defaultHTTPPort uint64 = 80 + defaultHTTPSPort uint64 = 443 + defaultHTTPPort uint64 = 80 + defaultExtServiceRequestTimeout = 10 // 10 seconds ) // urlCluster is a cluster that is created from a URL. @@ -61,10 +62,10 @@ func url2Cluster(strURL string, secure bool) (*urlCluster, error) { } } - name := fmt.Sprintf("%s_%d", strings.ReplaceAll(u.Hostname(), ".", "_"), port) + name := clusterName(u.Hostname(), uint32(port)) - if ip := net.ParseIP(u.Hostname()); ip != nil { - if v4 := ip.To4(); v4 != nil { + if ip, err := netip.ParseAddr(u.Hostname()); err == nil { + if ip.Unmap().Is4() { epType = EndpointTypeStatic } } @@ -78,6 +79,10 @@ func url2Cluster(strURL string, secure bool) (*urlCluster, error) { }, nil } +func clusterName(host string, port uint32) string { + return fmt.Sprintf("%s_%d", strings.ReplaceAll(host, ".", "_"), port) +} + // enableFilterOnRoute enables a filterType on the provided route. func enableFilterOnRoute(filterType string, route *routev3.Route, irRoute *ir.HTTPRoute) error { if route == nil { diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index def8eba49b2..07cfc0dc8ba 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -29,7 +29,7 @@ API group. #### ALPNProtocol -_Underlying type:_ `string` +_Underlying type:_ _string_ ALPNProtocol specifies the protocol to be negotiated using ALPN @@ -38,21 +38,95 @@ _Appears in:_ +#### ActiveHealthCheck + + + +ActiveHealthCheck defines the active health check configuration. EG supports various types of active health checking including HTTP, TCP. + +_Appears in:_ +- [HealthCheck](#healthcheck) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `timeout` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ | false | Timeout defines the time to wait for a health check response. | +| `interval` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ | false | Interval defines the time between active health checks. | +| `unhealthyThreshold` | _integer_ | false | UnhealthyThreshold defines the number of unhealthy health checks required before a backend host is marked unhealthy. | +| `healthyThreshold` | _integer_ | false | HealthyThreshold defines the number of healthy health checks required before a backend host is marked healthy. | +| `type` | _[ActiveHealthCheckerType](#activehealthcheckertype)_ | true | Type defines the type of health checker. | +| `http` | _[HTTPActiveHealthChecker](#httpactivehealthchecker)_ | false | HTTP defines the configuration of http health checker. It's required while the health checker type is HTTP. | +| `tcp` | _[TCPActiveHealthChecker](#tcpactivehealthchecker)_ | false | TCP defines the configuration of tcp health checker. It's required while the health checker type is TCP. | + + +#### ActiveHealthCheckPayload + + + +ActiveHealthCheckPayload defines the encoding of the payload bytes in the payload. + +_Appears in:_ +- [HTTPActiveHealthChecker](#httpactivehealthchecker) +- [TCPActiveHealthChecker](#tcpactivehealthchecker) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | _[ActiveHealthCheckPayloadType](#activehealthcheckpayloadtype)_ | true | Type defines the type of the payload. | +| `text` | _string_ | false | Text payload in plain text. | +| `binary` | _integer array_ | false | Binary payload base64 encoded. | + + +#### ActiveHealthCheckPayloadType + +_Underlying type:_ _string_ + +ActiveHealthCheckPayloadType is the type of the payload. + +_Appears in:_ +- [ActiveHealthCheckPayload](#activehealthcheckpayload) + + + +#### ActiveHealthCheckerType + +_Underlying type:_ _string_ + +ActiveHealthCheckerType is the type of health checker. + +_Appears in:_ +- [ActiveHealthCheck](#activehealthcheck) + + + +#### BackOffPolicy + + + + + +_Appears in:_ +- [PerRetryPolicy](#perretrypolicy) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `baseInterval` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ | true | BaseInterval is the base interval between retries. | +| `maxInterval` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ | false | MaxInterval is the maximum interval between retries. This parameter is optional, but must be greater than or equal to the base_interval if set. The default is 10 times the base_interval | + + #### BackendTrafficPolicy -BackendTrafficPolicy allows the user to configure the behavior of the connection between the downstream client and Envoy Proxy listener. +BackendTrafficPolicy allows the user to configure the behavior of the connection between the Envoy Proxy listener and the backend service. _Appears in:_ - [BackendTrafficPolicyList](#backendtrafficpolicylist) -| Field | Description | -| --- | --- | -| `apiVersion` _string_ | `gateway.envoyproxy.io/v1alpha1` -| `kind` _string_ | `BackendTrafficPolicy` -| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | -| `spec` _[BackendTrafficPolicySpec](#backendtrafficpolicyspec)_ | spec defines the desired state of BackendTrafficPolicy. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1` +| `kind` | _string_ | |`BackendTrafficPolicy` +| `metadata` | _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ | true | Refer to Kubernetes API documentation for fields of `metadata`. | +| `spec` | _[BackendTrafficPolicySpec](#backendtrafficpolicyspec)_ | true | spec defines the desired state of BackendTrafficPolicy. | #### BackendTrafficPolicyList @@ -63,12 +137,12 @@ BackendTrafficPolicyList contains a list of BackendTrafficPolicy resources. -| Field | Description | -| --- | --- | -| `apiVersion` _string_ | `gateway.envoyproxy.io/v1alpha1` -| `kind` _string_ | `BackendTrafficPolicyList` -| `metadata` _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#listmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | -| `items` _[BackendTrafficPolicy](#backendtrafficpolicy) array_ | | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1` +| `kind` | _string_ | |`BackendTrafficPolicyList` +| `metadata` | _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#listmeta-v1-meta)_ | true | Refer to Kubernetes API documentation for fields of `metadata`. | +| `items` | _[BackendTrafficPolicy](#backendtrafficpolicy) array_ | true | | #### BackendTrafficPolicySpec @@ -80,16 +154,19 @@ spec defines the desired state of BackendTrafficPolicy. _Appears in:_ - [BackendTrafficPolicy](#backendtrafficpolicy) -| Field | Description | -| --- | --- | -| `targetRef` _[PolicyTargetReferenceWithSectionName](#policytargetreferencewithsectionname)_ | targetRef is the name of the resource this policy is being attached to. This Policy and the TargetRef MUST be in the same namespace for this Policy to have effect and be applied to the Gateway. | -| `rateLimit` _[RateLimitSpec](#ratelimitspec)_ | RateLimit allows the user to limit the number of incoming requests to a predefined value based on attributes within the traffic flow. | -| `loadBalancer` _[LoadBalancer](#loadbalancer)_ | LoadBalancer policy to apply when routing traffic from the gateway to the backend endpoints | -| `proxyProtocol` _[ProxyProtocol](#proxyprotocol)_ | ProxyProtocol enables the Proxy Protocol when communicating with the backend. | -| `tcpKeepalive` _[TCPKeepalive](#tcpkeepalive)_ | TcpKeepalive settings associated with the upstream client connection. Disabled by default. | -| `healthCheck` _[HealthCheck](#healthcheck)_ | HealthCheck allows gateway to perform active health checking on backends. | -| `faultInjection` _[FaultInjection](#faultinjection)_ | FaultInjection defines the fault injection policy to be applied. This configuration can be used to inject delays and abort requests to mimic failure scenarios such as service failures and overloads | -| `circuitBreaker` _[CircuitBreaker](#circuitbreaker)_ | Circuit Breaker settings for the upstream connections and requests. If not set, circuit breakers will be enabled with the default thresholds | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `targetRef` | _[PolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.PolicyTargetReferenceWithSectionName)_ | true | targetRef is the name of the resource this policy is being attached to. This Policy and the TargetRef MUST be in the same namespace for this Policy to have effect and be applied to the Gateway. | +| `rateLimit` | _[RateLimitSpec](#ratelimitspec)_ | false | RateLimit allows the user to limit the number of incoming requests to a predefined value based on attributes within the traffic flow. | +| `loadBalancer` | _[LoadBalancer](#loadbalancer)_ | false | LoadBalancer policy to apply when routing traffic from the gateway to the backend endpoints | +| `proxyProtocol` | _[ProxyProtocol](#proxyprotocol)_ | false | ProxyProtocol enables the Proxy Protocol when communicating with the backend. | +| `tcpKeepalive` | _[TCPKeepalive](#tcpkeepalive)_ | false | TcpKeepalive settings associated with the upstream client connection. Disabled by default. | +| `healthCheck` | _[HealthCheck](#healthcheck)_ | false | HealthCheck allows gateway to perform active health checking on backends. | +| `faultInjection` | _[FaultInjection](#faultinjection)_ | false | FaultInjection defines the fault injection policy to be applied. This configuration can be used to inject delays and abort requests to mimic failure scenarios such as service failures and overloads | +| `circuitBreaker` | _[CircuitBreaker](#circuitbreaker)_ | false | Circuit Breaker settings for the upstream connections and requests. If not set, circuit breakers will be enabled with the default thresholds | +| `retry` | _[Retry](#retry)_ | false | Retry provides more advanced usage, allowing users to customize the number of retries, retry fallback strategy, and retry triggering conditions. If not set, retry will be disabled. | +| `timeout` | _[Timeout](#timeout)_ | false | Timeout settings for the backend connections. | +| `compression` | _[Compression](#compression) array_ | false | The compression config for the http streams. | @@ -103,16 +180,14 @@ BasicAuth defines the configuration for the HTTP Basic Authentication. _Appears in:_ - [SecurityPolicySpec](#securitypolicyspec) -| Field | Description | -| --- | --- | -| `users` _[SecretObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.SecretObjectReference)_ | The Kubernetes secret which contains the username-password pairs in htpasswd format, used to verify user credentials in the "Authorization" header. - This is an Opaque secret. The username-password pairs should be stored in the key ".htpasswd". As the key name indicates, the value needs to be the htpasswd format, for example: "user1:{SHA}hashed_user1_password". Right now, only SHA hash algorithm is supported. Reference to https://httpd.apache.org/docs/2.4/programs/htpasswd.html for more details. - Note: The secret must be in the same namespace as the SecurityPolicy. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `users` | _[SecretObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.SecretObjectReference)_ | true | The Kubernetes secret which contains the username-password pairs in htpasswd format, used to verify user credentials in the "Authorization" header.

This is an Opaque secret. The username-password pairs should be stored in the key ".htpasswd". As the key name indicates, the value needs to be the htpasswd format, for example: "user1:{SHA}hashed_user1_password". Right now, only SHA hash algorithm is supported. Reference to https://httpd.apache.org/docs/2.4/programs/htpasswd.html for more details.

Note: The secret must be in the same namespace as the SecurityPolicy. | #### BootstrapType -_Underlying type:_ `string` +_Underlying type:_ _string_ BootstrapType defines the types of bootstrap supported by Envoy Gateway. @@ -130,14 +205,14 @@ CORS defines the configuration for Cross-Origin Resource Sharing (CORS). _Appears in:_ - [SecurityPolicySpec](#securitypolicyspec) -| Field | Description | -| --- | --- | -| `allowOrigins` _Origin array_ | AllowOrigins defines the origins that are allowed to make requests. | -| `allowMethods` _string array_ | AllowMethods defines the methods that are allowed to make requests. | -| `allowHeaders` _string array_ | AllowHeaders defines the headers that are allowed to be sent with requests. | -| `exposeHeaders` _string array_ | ExposeHeaders defines the headers that can be exposed in the responses. | -| `maxAge` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ | MaxAge defines how long the results of a preflight request can be cached. | -| `allowCredentials` _boolean_ | AllowCredentials indicates whether a request can include user credentials like cookies, authentication headers, or TLS client certificates. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `allowOrigins` | _[Origin](#origin) array_ | true | AllowOrigins defines the origins that are allowed to make requests. | +| `allowMethods` | _string array_ | true | AllowMethods defines the methods that are allowed to make requests. | +| `allowHeaders` | _string array_ | true | AllowHeaders defines the headers that are allowed to be sent with requests. | +| `exposeHeaders` | _string array_ | true | ExposeHeaders defines the headers that can be exposed in the responses. | +| `maxAge` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ | true | MaxAge defines how long the results of a preflight request can be cached. | +| `allowCredentials` | _boolean_ | true | AllowCredentials indicates whether a request can include user credentials like cookies, authentication headers, or TLS client certificates. | #### CircuitBreaker @@ -149,11 +224,12 @@ CircuitBreaker defines the Circuit Breaker configuration. _Appears in:_ - [BackendTrafficPolicySpec](#backendtrafficpolicyspec) -| Field | Description | -| --- | --- | -| `maxConnections` _integer_ | The maximum number of connections that Envoy will establish to the referenced backend defined within a xRoute rule. | -| `maxPendingRequests` _integer_ | The maximum number of pending requests that Envoy will queue to the referenced backend defined within a xRoute rule. | -| `maxParallelRequests` _integer_ | The maximum number of parallel requests that Envoy will make to the referenced backend defined within a xRoute rule. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `maxConnections` | _integer_ | false | The maximum number of connections that Envoy will establish to the referenced backend defined within a xRoute rule. | +| `maxPendingRequests` | _integer_ | false | The maximum number of pending requests that Envoy will queue to the referenced backend defined within a xRoute rule. | +| `maxParallelRequests` | _integer_ | false | The maximum number of parallel requests that Envoy will make to the referenced backend defined within a xRoute rule. | +| `maxRequestsPerConnection` | _integer_ | false | The maximum number of requests that Envoy will make over a single connection to the referenced backend defined within a xRoute rule. Default: unlimited. | #### ClaimToHeader @@ -165,10 +241,39 @@ ClaimToHeader defines a configuration to convert JWT claims into HTTP headers _Appears in:_ - [JWTProvider](#jwtprovider) -| Field | Description | -| --- | --- | -| `header` _string_ | Header defines the name of the HTTP request header that the JWT Claim will be saved into. | -| `claim` _string_ | Claim is the JWT Claim that should be saved into the header : it can be a nested claim of type (eg. "claim.nested.key", "sub"). The nested claim name must use dot "." to separate the JSON name path. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `header` | _string_ | true | Header defines the name of the HTTP request header that the JWT Claim will be saved into. | +| `claim` | _string_ | true | Claim is the JWT Claim that should be saved into the header : it can be a nested claim of type (eg. "claim.nested.key", "sub"). The nested claim name must use dot "." to separate the JSON name path. | + + +#### ClientIPDetectionSettings + + + +ClientIPDetectionSettings provides configuration for determining the original client IP address for requests. + +_Appears in:_ +- [ClientTrafficPolicySpec](#clienttrafficpolicyspec) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `xForwardedFor` | _[XForwardedForSettings](#xforwardedforsettings)_ | false | XForwardedForSettings provides configuration for using X-Forwarded-For headers for determining the client IP address. | +| `customHeader` | _[CustomHeaderExtensionSettings](#customheaderextensionsettings)_ | false | CustomHeader provides configuration for determining the client IP address for a request based on a trusted custom HTTP header. This uses the the custom_header original IP detection extension. Refer to https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/http/original_ip_detection/custom_header/v3/custom_header.proto for more details. | + + +#### ClientTimeout + + + + + +_Appears in:_ +- [ClientTrafficPolicySpec](#clienttrafficpolicyspec) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `http` | _[HTTPClientTimeout](#httpclienttimeout)_ | false | Timeout settings for HTTP. | #### ClientTrafficPolicy @@ -180,12 +285,12 @@ ClientTrafficPolicy allows the user to configure the behavior of the connection _Appears in:_ - [ClientTrafficPolicyList](#clienttrafficpolicylist) -| Field | Description | -| --- | --- | -| `apiVersion` _string_ | `gateway.envoyproxy.io/v1alpha1` -| `kind` _string_ | `ClientTrafficPolicy` -| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | -| `spec` _[ClientTrafficPolicySpec](#clienttrafficpolicyspec)_ | Spec defines the desired state of ClientTrafficPolicy. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1` +| `kind` | _string_ | |`ClientTrafficPolicy` +| `metadata` | _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ | true | Refer to Kubernetes API documentation for fields of `metadata`. | +| `spec` | _[ClientTrafficPolicySpec](#clienttrafficpolicyspec)_ | true | Spec defines the desired state of ClientTrafficPolicy. | #### ClientTrafficPolicyList @@ -196,12 +301,12 @@ ClientTrafficPolicyList contains a list of ClientTrafficPolicy resources. -| Field | Description | -| --- | --- | -| `apiVersion` _string_ | `gateway.envoyproxy.io/v1alpha1` -| `kind` _string_ | `ClientTrafficPolicyList` -| `metadata` _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#listmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | -| `items` _[ClientTrafficPolicy](#clienttrafficpolicy) array_ | | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1` +| `kind` | _string_ | |`ClientTrafficPolicyList` +| `metadata` | _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#listmeta-v1-meta)_ | true | Refer to Kubernetes API documentation for fields of `metadata`. | +| `items` | _[ClientTrafficPolicy](#clienttrafficpolicy) array_ | true | | #### ClientTrafficPolicySpec @@ -213,17 +318,60 @@ ClientTrafficPolicySpec defines the desired state of ClientTrafficPolicy. _Appears in:_ - [ClientTrafficPolicy](#clienttrafficpolicy) -| Field | Description | -| --- | --- | -| `targetRef` _[PolicyTargetReferenceWithSectionName](#policytargetreferencewithsectionname)_ | TargetRef is the name of the Gateway resource this policy is being attached to. This Policy and the TargetRef MUST be in the same namespace for this Policy to have effect and be applied to the Gateway. TargetRef | -| `tcpKeepalive` _[TCPKeepalive](#tcpkeepalive)_ | TcpKeepalive settings associated with the downstream client connection. If defined, sets SO_KEEPALIVE on the listener socket to enable TCP Keepalives. Disabled by default. | -| `suppressEnvoyHeaders` _boolean_ | SuppressEnvoyHeaders configures the Envoy Router filter to suppress the "x-envoy-' headers from both requests and responses. By default these headers are added to both requests and responses. | -| `enableProxyProtocol` _boolean_ | EnableProxyProtocol interprets the ProxyProtocol header and adds the Client Address into the X-Forwarded-For header. Note Proxy Protocol must be present when this field is set, else the connection is closed. | -| `http3` _[HTTP3Settings](#http3settings)_ | HTTP3 provides HTTP/3 configuration on the listener. | -| `tls` _[TLSSettings](#tlssettings)_ | TLS settings configure TLS termination settings with the downstream client. | -| `path` _[PathSettings](#pathsettings)_ | Path enables managing how the incoming path set by clients can be normalized. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `targetRef` | _[PolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.PolicyTargetReferenceWithSectionName)_ | true | TargetRef is the name of the Gateway resource this policy is being attached to. This Policy and the TargetRef MUST be in the same namespace for this Policy to have effect and be applied to the Gateway. TargetRef | +| `tcpKeepalive` | _[TCPKeepalive](#tcpkeepalive)_ | false | TcpKeepalive settings associated with the downstream client connection. If defined, sets SO_KEEPALIVE on the listener socket to enable TCP Keepalives. Disabled by default. | +| `enableProxyProtocol` | _boolean_ | false | EnableProxyProtocol interprets the ProxyProtocol header and adds the Client Address into the X-Forwarded-For header. Note Proxy Protocol must be present when this field is set, else the connection is closed. | +| `clientIPDetection` | _[ClientIPDetectionSettings](#clientipdetectionsettings)_ | false | ClientIPDetectionSettings provides configuration for determining the original client IP address for requests. | +| `http3` | _[HTTP3Settings](#http3settings)_ | false | HTTP3 provides HTTP/3 configuration on the listener. | +| `tls` | _[TLSSettings](#tlssettings)_ | false | TLS settings configure TLS termination settings with the downstream client. | +| `path` | _[PathSettings](#pathsettings)_ | false | Path enables managing how the incoming path set by clients can be normalized. | +| `http1` | _[HTTP1Settings](#http1settings)_ | false | HTTP1 provides HTTP/1 configuration on the listener. | +| `headers` | _[HeaderSettings](#headersettings)_ | false | HeaderSettings provides configuration for header management. | +| `timeout` | _[ClientTimeout](#clienttimeout)_ | false | Timeout settings for the client connections. | + + +#### ClientValidationContext + + + +ClientValidationContext holds configuration that can be used to validate the client initiating the TLS connection to the Gateway. By default, no client specific configuration is validated. + +_Appears in:_ +- [TLSSettings](#tlssettings) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `caCertificateRefs` | _[SecretObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.SecretObjectReference) array_ | false | CACertificateRefs contains one or more references to Kubernetes objects that contain TLS certificates of the Certificate Authorities that can be used as a trust anchor to validate the certificates presented by the client.

A single reference to a Kubernetes ConfigMap or a Kubernetes Secret, with the CA certificate in a key named `ca.crt` is currently supported.

References to a resource in different namespace are invalid UNLESS there is a ReferenceGrant in the target namespace that allows the certificate to be attached. | + + +#### Compression + + + +Compression defines the config of enabling compression. This can help reduce the bandwidth at the expense of higher CPU. + +_Appears in:_ +- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | _[CompressorType](#compressortype)_ | true | CompressorType defines the compressor type to use for compression. | +| `gzip` | _[GzipCompressor](#gzipcompressor)_ | false | The configuration for GZIP compressor. | + + +#### CompressorType + +_Underlying type:_ _string_ + +CompressorType defines the types of compressor library supported by Envoy Gateway. + +_Appears in:_ +- [Compression](#compression) + #### ConsistentHash @@ -235,14 +383,14 @@ ConsistentHash defines the configuration related to the consistent hash load bal _Appears in:_ - [LoadBalancer](#loadbalancer) -| Field | Description | -| --- | --- | -| `type` _[ConsistentHashType](#consistenthashtype)_ | | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | _[ConsistentHashType](#consistenthashtype)_ | true | | #### ConsistentHashType -_Underlying type:_ `string` +_Underlying type:_ _string_ ConsistentHashType defines the type of input to hash on. @@ -251,6 +399,21 @@ _Appears in:_ +#### CustomHeaderExtensionSettings + + + +CustomHeader provides configuration for determining the client IP address for a request based on a trusted custom HTTP header. This uses the the custom_header original IP detection extension. Refer to https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/http/original_ip_detection/custom_header/v3/custom_header.proto for more details. + +_Appears in:_ +- [ClientIPDetectionSettings](#clientipdetectionsettings) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `name` | _string_ | true | Name of the header containing the original downstream remote address, if present. | +| `failClosed` | _boolean_ | false | FailClosed is a switch used to control the flow of traffic when client IP detection fails. If set to true, the listener will respond with 403 Forbidden when the client IP address cannot be determined. | + + #### CustomTag @@ -260,17 +423,17 @@ _Appears in:_ _Appears in:_ - [ProxyTracing](#proxytracing) -| Field | Description | -| --- | --- | -| `type` _[CustomTagType](#customtagtype)_ | Type defines the type of custom tag. | -| `literal` _[LiteralCustomTag](#literalcustomtag)_ | Literal adds hard-coded value to each span. It's required when the type is "Literal". | -| `environment` _[EnvironmentCustomTag](#environmentcustomtag)_ | Environment adds value from environment variable to each span. It's required when the type is "Environment". | -| `requestHeader` _[RequestHeaderCustomTag](#requestheadercustomtag)_ | RequestHeader adds value from request header to each span. It's required when the type is "RequestHeader". | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | _[CustomTagType](#customtagtype)_ | true | Type defines the type of custom tag. | +| `literal` | _[LiteralCustomTag](#literalcustomtag)_ | true | Literal adds hard-coded value to each span. It's required when the type is "Literal". | +| `environment` | _[EnvironmentCustomTag](#environmentcustomtag)_ | true | Environment adds value from environment variable to each span. It's required when the type is "Environment". | +| `requestHeader` | _[RequestHeaderCustomTag](#requestheadercustomtag)_ | true | RequestHeader adds value from request header to each span. It's required when the type is "RequestHeader". | #### CustomTagType -_Underlying type:_ `string` +_Underlying type:_ _string_ @@ -288,10 +451,10 @@ EnvironmentCustomTag adds value from environment variable to each span. _Appears in:_ - [CustomTag](#customtag) -| Field | Description | -| --- | --- | -| `name` _string_ | Name defines the name of the environment variable which to extract the value from. | -| `defaultValue` _string_ | DefaultValue defines the default value to use if the environment variable is not set. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `name` | _string_ | true | Name defines the name of the environment variable which to extract the value from. | +| `defaultValue` | _string_ | false | DefaultValue defines the default value to use if the environment variable is not set. | #### EnvoyGateway @@ -302,18 +465,18 @@ EnvoyGateway is the schema for the envoygateways API. -| Field | Description | -| --- | --- | -| `apiVersion` _string_ | `gateway.envoyproxy.io/v1alpha1` -| `kind` _string_ | `EnvoyGateway` -| `gateway` _[Gateway](#gateway)_ | Gateway defines desired Gateway API specific configuration. If unset, default configuration parameters will apply. | -| `provider` _[EnvoyGatewayProvider](#envoygatewayprovider)_ | Provider defines the desired provider and provider-specific configuration. If unspecified, the Kubernetes provider is used with default configuration parameters. | -| `logging` _[EnvoyGatewayLogging](#envoygatewaylogging)_ | Logging defines logging parameters for Envoy Gateway. | -| `admin` _[EnvoyGatewayAdmin](#envoygatewayadmin)_ | Admin defines the desired admin related abilities. If unspecified, the Admin is used with default configuration parameters. | -| `telemetry` _[EnvoyGatewayTelemetry](#envoygatewaytelemetry)_ | Telemetry defines the desired control plane telemetry related abilities. If unspecified, the telemetry is used with default configuration. | -| `rateLimit` _[RateLimit](#ratelimit)_ | RateLimit defines the configuration associated with the Rate Limit service deployed by Envoy Gateway required to implement the Global Rate limiting functionality. The specific rate limit service used here is the reference implementation in Envoy. For more details visit https://github.com/envoyproxy/ratelimit. This configuration is unneeded for "Local" rate limiting. | -| `extensionManager` _[ExtensionManager](#extensionmanager)_ | ExtensionManager defines an extension manager to register for the Envoy Gateway Control Plane. | -| `extensionApis` _[ExtensionAPISettings](#extensionapisettings)_ | ExtensionAPIs defines the settings related to specific Gateway API Extensions implemented by Envoy Gateway | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1` +| `kind` | _string_ | |`EnvoyGateway` +| `gateway` | _[Gateway](#gateway)_ | false | Gateway defines desired Gateway API specific configuration. If unset, default configuration parameters will apply. | +| `provider` | _[EnvoyGatewayProvider](#envoygatewayprovider)_ | false | Provider defines the desired provider and provider-specific configuration. If unspecified, the Kubernetes provider is used with default configuration parameters. | +| `logging` | _[EnvoyGatewayLogging](#envoygatewaylogging)_ | false | Logging defines logging parameters for Envoy Gateway. | +| `admin` | _[EnvoyGatewayAdmin](#envoygatewayadmin)_ | false | Admin defines the desired admin related abilities. If unspecified, the Admin is used with default configuration parameters. | +| `telemetry` | _[EnvoyGatewayTelemetry](#envoygatewaytelemetry)_ | false | Telemetry defines the desired control plane telemetry related abilities. If unspecified, the telemetry is used with default configuration. | +| `rateLimit` | _[RateLimit](#ratelimit)_ | false | RateLimit defines the configuration associated with the Rate Limit service deployed by Envoy Gateway required to implement the Global Rate limiting functionality. The specific rate limit service used here is the reference implementation in Envoy. For more details visit https://github.com/envoyproxy/ratelimit. This configuration is unneeded for "Local" rate limiting. | +| `extensionManager` | _[ExtensionManager](#extensionmanager)_ | false | ExtensionManager defines an extension manager to register for the Envoy Gateway Control Plane. | +| `extensionApis` | _[ExtensionAPISettings](#extensionapisettings)_ | false | ExtensionAPIs defines the settings related to specific Gateway API Extensions implemented by Envoy Gateway | #### EnvoyGatewayAdmin @@ -326,11 +489,11 @@ _Appears in:_ - [EnvoyGateway](#envoygateway) - [EnvoyGatewaySpec](#envoygatewayspec) -| Field | Description | -| --- | --- | -| `address` _[EnvoyGatewayAdminAddress](#envoygatewayadminaddress)_ | Address defines the address of Envoy Gateway Admin Server. | -| `enableDumpConfig` _boolean_ | EnableDumpConfig defines if enable dump config in Envoy Gateway logs. | -| `enablePprof` _boolean_ | EnablePprof defines if enable pprof in Envoy Gateway Admin Server. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `address` | _[EnvoyGatewayAdminAddress](#envoygatewayadminaddress)_ | false | Address defines the address of Envoy Gateway Admin Server. | +| `enableDumpConfig` | _boolean_ | false | EnableDumpConfig defines if enable dump config in Envoy Gateway logs. | +| `enablePprof` | _boolean_ | false | EnablePprof defines if enable pprof in Envoy Gateway Admin Server. | #### EnvoyGatewayAdminAddress @@ -342,10 +505,10 @@ EnvoyGatewayAdminAddress defines the Envoy Gateway Admin Address configuration. _Appears in:_ - [EnvoyGatewayAdmin](#envoygatewayadmin) -| Field | Description | -| --- | --- | -| `port` _integer_ | Port defines the port the admin server is exposed on. | -| `host` _string_ | Host defines the admin server hostname. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `port` | _integer_ | false | Port defines the port the admin server is exposed on. | +| `host` | _string_ | false | Host defines the admin server hostname. | #### EnvoyGatewayCustomProvider @@ -357,10 +520,10 @@ EnvoyGatewayCustomProvider defines configuration for the Custom provider. _Appears in:_ - [EnvoyGatewayProvider](#envoygatewayprovider) -| Field | Description | -| --- | --- | -| `resource` _[EnvoyGatewayResourceProvider](#envoygatewayresourceprovider)_ | Resource defines the desired resource provider. This provider is used to specify the provider to be used to retrieve the resource configurations such as Gateway API resources | -| `infrastructure` _[EnvoyGatewayInfrastructureProvider](#envoygatewayinfrastructureprovider)_ | Infrastructure defines the desired infrastructure provider. This provider is used to specify the provider to be used to provide an environment to deploy the out resources like the Envoy Proxy data plane. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `resource` | _[EnvoyGatewayResourceProvider](#envoygatewayresourceprovider)_ | true | Resource defines the desired resource provider. This provider is used to specify the provider to be used to retrieve the resource configurations such as Gateway API resources | +| `infrastructure` | _[EnvoyGatewayInfrastructureProvider](#envoygatewayinfrastructureprovider)_ | true | Infrastructure defines the desired infrastructure provider. This provider is used to specify the provider to be used to provide an environment to deploy the out resources like the Envoy Proxy data plane. | #### EnvoyGatewayFileResourceProvider @@ -372,9 +535,9 @@ EnvoyGatewayFileResourceProvider defines configuration for the File Resource pro _Appears in:_ - [EnvoyGatewayResourceProvider](#envoygatewayresourceprovider) -| Field | Description | -| --- | --- | -| `paths` _string array_ | Paths are the paths to a directory or file containing the resource configuration. Recursive sub directories are not currently supported. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `paths` | _string array_ | true | Paths are the paths to a directory or file containing the resource configuration. Recursive sub directories are not currently supported. | #### EnvoyGatewayHostInfrastructureProvider @@ -397,10 +560,10 @@ EnvoyGatewayInfrastructureProvider defines configuration for the Custom Infrastr _Appears in:_ - [EnvoyGatewayCustomProvider](#envoygatewaycustomprovider) -| Field | Description | -| --- | --- | -| `type` _[InfrastructureProviderType](#infrastructureprovidertype)_ | Type is the type of infrastructure providers to use. Supported types are "Host". | -| `host` _[EnvoyGatewayHostInfrastructureProvider](#envoygatewayhostinfrastructureprovider)_ | Host defines the configuration of the Host provider. Host provides runtime deployment of the data plane as a child process on the host environment. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | _[InfrastructureProviderType](#infrastructureprovidertype)_ | true | Type is the type of infrastructure providers to use. Supported types are "Host". | +| `host` | _[EnvoyGatewayHostInfrastructureProvider](#envoygatewayhostinfrastructureprovider)_ | false | Host defines the configuration of the Host provider. Host provides runtime deployment of the data plane as a child process on the host environment. | #### EnvoyGatewayKubernetesProvider @@ -412,17 +575,17 @@ EnvoyGatewayKubernetesProvider defines configuration for the Kubernetes provider _Appears in:_ - [EnvoyGatewayProvider](#envoygatewayprovider) -| Field | Description | -| --- | --- | -| `rateLimitDeployment` _[KubernetesDeploymentSpec](#kubernetesdeploymentspec)_ | RateLimitDeployment defines the desired state of the Envoy ratelimit deployment resource. If unspecified, default settings for the managed Envoy ratelimit deployment resource are applied. | -| `watch` _[KubernetesWatchMode](#kuberneteswatchmode)_ | Watch holds configuration of which input resources should be watched and reconciled. | -| `deploy` _[KubernetesDeployMode](#kubernetesdeploymode)_ | Deploy holds configuration of how output managed resources such as the Envoy Proxy data plane should be deployed | -| `overwriteControlPlaneCerts` _boolean_ | OverwriteControlPlaneCerts updates the secrets containing the control plane certs, when set. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `rateLimitDeployment` | _[KubernetesDeploymentSpec](#kubernetesdeploymentspec)_ | false | RateLimitDeployment defines the desired state of the Envoy ratelimit deployment resource. If unspecified, default settings for the managed Envoy ratelimit deployment resource are applied. | +| `watch` | _[KubernetesWatchMode](#kuberneteswatchmode)_ | false | Watch holds configuration of which input resources should be watched and reconciled. | +| `deploy` | _[KubernetesDeployMode](#kubernetesdeploymode)_ | false | Deploy holds configuration of how output managed resources such as the Envoy Proxy data plane should be deployed | +| `overwriteControlPlaneCerts` | _boolean_ | false | OverwriteControlPlaneCerts updates the secrets containing the control plane certs, when set. | #### EnvoyGatewayLogComponent -_Underlying type:_ `string` +_Underlying type:_ _string_ EnvoyGatewayLogComponent defines a component that supports a configured logging level. @@ -441,9 +604,9 @@ _Appears in:_ - [EnvoyGateway](#envoygateway) - [EnvoyGatewaySpec](#envoygatewayspec) -| Field | Description | -| --- | --- | -| `level` _object (keys:[EnvoyGatewayLogComponent](#envoygatewaylogcomponent), values:[LogLevel](#loglevel))_ | Level is the logging level. If unspecified, defaults to "info". EnvoyGatewayLogComponent options: default/provider/gateway-api/xds-translator/xds-server/infrastructure/global-ratelimit. LogLevel options: debug/info/error/warn. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `level` | _object (keys:[EnvoyGatewayLogComponent](#envoygatewaylogcomponent), values:[LogLevel](#loglevel))_ | true | Level is the logging level. If unspecified, defaults to "info". EnvoyGatewayLogComponent options: default/provider/gateway-api/xds-translator/xds-server/infrastructure/global-ratelimit. LogLevel options: debug/info/error/warn. | #### EnvoyGatewayMetricSink @@ -455,10 +618,10 @@ EnvoyGatewayMetricSink defines control plane metric sinks where metrics are sent _Appears in:_ - [EnvoyGatewayMetrics](#envoygatewaymetrics) -| Field | Description | -| --- | --- | -| `type` _[MetricSinkType](#metricsinktype)_ | Type defines the metric sink type. EG control plane currently supports OpenTelemetry. | -| `openTelemetry` _[EnvoyGatewayOpenTelemetrySink](#envoygatewayopentelemetrysink)_ | OpenTelemetry defines the configuration for OpenTelemetry sink. It's required if the sink type is OpenTelemetry. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | _[MetricSinkType](#metricsinktype)_ | true | Type defines the metric sink type. EG control plane currently supports OpenTelemetry. | +| `openTelemetry` | _[EnvoyGatewayOpenTelemetrySink](#envoygatewayopentelemetrysink)_ | true | OpenTelemetry defines the configuration for OpenTelemetry sink. It's required if the sink type is OpenTelemetry. | #### EnvoyGatewayMetrics @@ -470,10 +633,10 @@ EnvoyGatewayMetrics defines control plane push/pull metrics configurations. _Appears in:_ - [EnvoyGatewayTelemetry](#envoygatewaytelemetry) -| Field | Description | -| --- | --- | -| `sinks` _[EnvoyGatewayMetricSink](#envoygatewaymetricsink) array_ | Sinks defines the metric sinks where metrics are sent to. | -| `prometheus` _[EnvoyGatewayPrometheusProvider](#envoygatewayprometheusprovider)_ | Prometheus defines the configuration for prometheus endpoint. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `sinks` | _[EnvoyGatewayMetricSink](#envoygatewaymetricsink) array_ | true | Sinks defines the metric sinks where metrics are sent to. | +| `prometheus` | _[EnvoyGatewayPrometheusProvider](#envoygatewayprometheusprovider)_ | true | Prometheus defines the configuration for prometheus endpoint. | #### EnvoyGatewayOpenTelemetrySink @@ -485,11 +648,11 @@ _Appears in:_ _Appears in:_ - [EnvoyGatewayMetricSink](#envoygatewaymetricsink) -| Field | Description | -| --- | --- | -| `host` _string_ | Host define the sink service hostname. | -| `protocol` _string_ | Protocol define the sink service protocol. | -| `port` _integer_ | Port defines the port the sink service is exposed on. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `host` | _string_ | true | Host define the sink service hostname. | +| `protocol` | _string_ | true | Protocol define the sink service protocol. | +| `port` | _integer_ | false | Port defines the port the sink service is exposed on. | #### EnvoyGatewayPrometheusProvider @@ -501,9 +664,9 @@ EnvoyGatewayPrometheusProvider will expose prometheus endpoint in pull mode. _Appears in:_ - [EnvoyGatewayMetrics](#envoygatewaymetrics) -| Field | Description | -| --- | --- | -| `disable` _boolean_ | Disable defines if disables the prometheus metrics in pull mode. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `disable` | _boolean_ | true | Disable defines if disables the prometheus metrics in pull mode. | #### EnvoyGatewayProvider @@ -516,11 +679,11 @@ _Appears in:_ - [EnvoyGateway](#envoygateway) - [EnvoyGatewaySpec](#envoygatewayspec) -| Field | Description | -| --- | --- | -| `type` _[ProviderType](#providertype)_ | Type is the type of provider to use. Supported types are "Kubernetes". | -| `kubernetes` _[EnvoyGatewayKubernetesProvider](#envoygatewaykubernetesprovider)_ | Kubernetes defines the configuration of the Kubernetes provider. Kubernetes provides runtime configuration via the Kubernetes API. | -| `custom` _[EnvoyGatewayCustomProvider](#envoygatewaycustomprovider)_ | Custom defines the configuration for the Custom provider. This provider allows you to define a specific resource provider and a infrastructure provider. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | _[ProviderType](#providertype)_ | true | Type is the type of provider to use. Supported types are "Kubernetes". | +| `kubernetes` | _[EnvoyGatewayKubernetesProvider](#envoygatewaykubernetesprovider)_ | false | Kubernetes defines the configuration of the Kubernetes provider. Kubernetes provides runtime configuration via the Kubernetes API. | +| `custom` | _[EnvoyGatewayCustomProvider](#envoygatewaycustomprovider)_ | false | Custom defines the configuration for the Custom provider. This provider allows you to define a specific resource provider and a infrastructure provider. | #### EnvoyGatewayResourceProvider @@ -532,10 +695,10 @@ EnvoyGatewayResourceProvider defines configuration for the Custom Resource provi _Appears in:_ - [EnvoyGatewayCustomProvider](#envoygatewaycustomprovider) -| Field | Description | -| --- | --- | -| `type` _[ResourceProviderType](#resourceprovidertype)_ | Type is the type of resource provider to use. Supported types are "File". | -| `file` _[EnvoyGatewayFileResourceProvider](#envoygatewayfileresourceprovider)_ | File defines the configuration of the File provider. File provides runtime configuration defined by one or more files. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | _[ResourceProviderType](#resourceprovidertype)_ | true | Type is the type of resource provider to use. Supported types are "File". | +| `file` | _[EnvoyGatewayFileResourceProvider](#envoygatewayfileresourceprovider)_ | false | File defines the configuration of the File provider. File provides runtime configuration defined by one or more files. | #### EnvoyGatewaySpec @@ -547,16 +710,16 @@ EnvoyGatewaySpec defines the desired state of Envoy Gateway. _Appears in:_ - [EnvoyGateway](#envoygateway) -| Field | Description | -| --- | --- | -| `gateway` _[Gateway](#gateway)_ | Gateway defines desired Gateway API specific configuration. If unset, default configuration parameters will apply. | -| `provider` _[EnvoyGatewayProvider](#envoygatewayprovider)_ | Provider defines the desired provider and provider-specific configuration. If unspecified, the Kubernetes provider is used with default configuration parameters. | -| `logging` _[EnvoyGatewayLogging](#envoygatewaylogging)_ | Logging defines logging parameters for Envoy Gateway. | -| `admin` _[EnvoyGatewayAdmin](#envoygatewayadmin)_ | Admin defines the desired admin related abilities. If unspecified, the Admin is used with default configuration parameters. | -| `telemetry` _[EnvoyGatewayTelemetry](#envoygatewaytelemetry)_ | Telemetry defines the desired control plane telemetry related abilities. If unspecified, the telemetry is used with default configuration. | -| `rateLimit` _[RateLimit](#ratelimit)_ | RateLimit defines the configuration associated with the Rate Limit service deployed by Envoy Gateway required to implement the Global Rate limiting functionality. The specific rate limit service used here is the reference implementation in Envoy. For more details visit https://github.com/envoyproxy/ratelimit. This configuration is unneeded for "Local" rate limiting. | -| `extensionManager` _[ExtensionManager](#extensionmanager)_ | ExtensionManager defines an extension manager to register for the Envoy Gateway Control Plane. | -| `extensionApis` _[ExtensionAPISettings](#extensionapisettings)_ | ExtensionAPIs defines the settings related to specific Gateway API Extensions implemented by Envoy Gateway | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `gateway` | _[Gateway](#gateway)_ | false | Gateway defines desired Gateway API specific configuration. If unset, default configuration parameters will apply. | +| `provider` | _[EnvoyGatewayProvider](#envoygatewayprovider)_ | false | Provider defines the desired provider and provider-specific configuration. If unspecified, the Kubernetes provider is used with default configuration parameters. | +| `logging` | _[EnvoyGatewayLogging](#envoygatewaylogging)_ | false | Logging defines logging parameters for Envoy Gateway. | +| `admin` | _[EnvoyGatewayAdmin](#envoygatewayadmin)_ | false | Admin defines the desired admin related abilities. If unspecified, the Admin is used with default configuration parameters. | +| `telemetry` | _[EnvoyGatewayTelemetry](#envoygatewaytelemetry)_ | false | Telemetry defines the desired control plane telemetry related abilities. If unspecified, the telemetry is used with default configuration. | +| `rateLimit` | _[RateLimit](#ratelimit)_ | false | RateLimit defines the configuration associated with the Rate Limit service deployed by Envoy Gateway required to implement the Global Rate limiting functionality. The specific rate limit service used here is the reference implementation in Envoy. For more details visit https://github.com/envoyproxy/ratelimit. This configuration is unneeded for "Local" rate limiting. | +| `extensionManager` | _[ExtensionManager](#extensionmanager)_ | false | ExtensionManager defines an extension manager to register for the Envoy Gateway Control Plane. | +| `extensionApis` | _[ExtensionAPISettings](#extensionapisettings)_ | false | ExtensionAPIs defines the settings related to specific Gateway API Extensions implemented by Envoy Gateway | #### EnvoyGatewayTelemetry @@ -569,9 +732,9 @@ _Appears in:_ - [EnvoyGateway](#envoygateway) - [EnvoyGatewaySpec](#envoygatewayspec) -| Field | Description | -| --- | --- | -| `metrics` _[EnvoyGatewayMetrics](#envoygatewaymetrics)_ | Metrics defines metrics configuration for envoy gateway. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `metrics` | _[EnvoyGatewayMetrics](#envoygatewaymetrics)_ | true | Metrics defines metrics configuration for envoy gateway. | #### EnvoyJSONPatchConfig @@ -583,11 +746,11 @@ EnvoyJSONPatchConfig defines the configuration for patching a Envoy xDS Resource _Appears in:_ - [EnvoyPatchPolicySpec](#envoypatchpolicyspec) -| Field | Description | -| --- | --- | -| `type` _[EnvoyResourceType](#envoyresourcetype)_ | Type is the typed URL of the Envoy xDS Resource | -| `name` _string_ | Name is the name of the resource | -| `operation` _[JSONPatchOperation](#jsonpatchoperation)_ | Patch defines the JSON Patch Operation | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | _[EnvoyResourceType](#envoyresourcetype)_ | true | Type is the typed URL of the Envoy xDS Resource | +| `name` | _string_ | true | Name is the name of the resource | +| `operation` | _[JSONPatchOperation](#jsonpatchoperation)_ | true | Patch defines the JSON Patch Operation | #### EnvoyPatchPolicy @@ -599,12 +762,12 @@ EnvoyPatchPolicy allows the user to modify the generated Envoy xDS resources by _Appears in:_ - [EnvoyPatchPolicyList](#envoypatchpolicylist) -| Field | Description | -| --- | --- | -| `apiVersion` _string_ | `gateway.envoyproxy.io/v1alpha1` -| `kind` _string_ | `EnvoyPatchPolicy` -| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | -| `spec` _[EnvoyPatchPolicySpec](#envoypatchpolicyspec)_ | Spec defines the desired state of EnvoyPatchPolicy. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1` +| `kind` | _string_ | |`EnvoyPatchPolicy` +| `metadata` | _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ | true | Refer to Kubernetes API documentation for fields of `metadata`. | +| `spec` | _[EnvoyPatchPolicySpec](#envoypatchpolicyspec)_ | true | Spec defines the desired state of EnvoyPatchPolicy. | #### EnvoyPatchPolicyList @@ -615,12 +778,12 @@ EnvoyPatchPolicyList contains a list of EnvoyPatchPolicy resources. -| Field | Description | -| --- | --- | -| `apiVersion` _string_ | `gateway.envoyproxy.io/v1alpha1` -| `kind` _string_ | `EnvoyPatchPolicyList` -| `metadata` _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#listmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | -| `items` _[EnvoyPatchPolicy](#envoypatchpolicy) array_ | | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1` +| `kind` | _string_ | |`EnvoyPatchPolicyList` +| `metadata` | _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#listmeta-v1-meta)_ | true | Refer to Kubernetes API documentation for fields of `metadata`. | +| `items` | _[EnvoyPatchPolicy](#envoypatchpolicy) array_ | true | | #### EnvoyPatchPolicySpec @@ -632,19 +795,19 @@ EnvoyPatchPolicySpec defines the desired state of EnvoyPatchPolicy. _Appears in:_ - [EnvoyPatchPolicy](#envoypatchpolicy) -| Field | Description | -| --- | --- | -| `type` _[EnvoyPatchType](#envoypatchtype)_ | Type decides the type of patch. Valid EnvoyPatchType values are "JSONPatch". | -| `jsonPatches` _[EnvoyJSONPatchConfig](#envoyjsonpatchconfig) array_ | JSONPatch defines the JSONPatch configuration. | -| `targetRef` _[PolicyTargetReference](#policytargetreference)_ | TargetRef is the name of the Gateway API resource this policy is being attached to. By default attaching to Gateway is supported and when mergeGateways is enabled it should attach to GatewayClass. This Policy and the TargetRef MUST be in the same namespace for this Policy to have effect and be applied to the Gateway TargetRef | -| `priority` _integer_ | Priority of the EnvoyPatchPolicy. If multiple EnvoyPatchPolicies are applied to the same TargetRef, they will be applied in the ascending order of the priority i.e. int32.min has the highest priority and int32.max has the lowest priority. Defaults to 0. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | _[EnvoyPatchType](#envoypatchtype)_ | true | Type decides the type of patch. Valid EnvoyPatchType values are "JSONPatch". | +| `jsonPatches` | _[EnvoyJSONPatchConfig](#envoyjsonpatchconfig) array_ | false | JSONPatch defines the JSONPatch configuration. | +| `targetRef` | _[PolicyTargetReference](#policytargetreference)_ | true | TargetRef is the name of the Gateway API resource this policy is being attached to. By default attaching to Gateway is supported and when mergeGateways is enabled it should attach to GatewayClass. This Policy and the TargetRef MUST be in the same namespace for this Policy to have effect and be applied to the Gateway TargetRef | +| `priority` | _integer_ | true | Priority of the EnvoyPatchPolicy. If multiple EnvoyPatchPolicies are applied to the same TargetRef, they will be applied in the ascending order of the priority i.e. int32.min has the highest priority and int32.max has the lowest priority. Defaults to 0. | #### EnvoyPatchType -_Underlying type:_ `string` +_Underlying type:_ _string_ EnvoyPatchType specifies the types of Envoy patching mechanisms. @@ -661,12 +824,12 @@ EnvoyProxy is the schema for the envoyproxies API. -| Field | Description | -| --- | --- | -| `apiVersion` _string_ | `gateway.envoyproxy.io/v1alpha1` -| `kind` _string_ | `EnvoyProxy` -| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | -| `spec` _[EnvoyProxySpec](#envoyproxyspec)_ | EnvoyProxySpec defines the desired state of EnvoyProxy. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1` +| `kind` | _string_ | |`EnvoyProxy` +| `metadata` | _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ | true | Refer to Kubernetes API documentation for fields of `metadata`. | +| `spec` | _[EnvoyProxySpec](#envoyproxyspec)_ | true | EnvoyProxySpec defines the desired state of EnvoyProxy. | #### EnvoyProxyKubernetesProvider @@ -678,11 +841,11 @@ EnvoyProxyKubernetesProvider defines configuration for the Kubernetes resource p _Appears in:_ - [EnvoyProxyProvider](#envoyproxyprovider) -| Field | Description | -| --- | --- | -| `envoyDeployment` _[KubernetesDeploymentSpec](#kubernetesdeploymentspec)_ | EnvoyDeployment defines the desired state of the Envoy deployment resource. If unspecified, default settings for the managed Envoy deployment resource are applied. | -| `envoyService` _[KubernetesServiceSpec](#kubernetesservicespec)_ | EnvoyService defines the desired state of the Envoy service resource. If unspecified, default settings for the managed Envoy service resource are applied. | -| `envoyHpa` _[KubernetesHorizontalPodAutoscalerSpec](#kuberneteshorizontalpodautoscalerspec)_ | EnvoyHpa defines the Horizontal Pod Autoscaler settings for Envoy Proxy Deployment. Once the HPA is being set, Replicas field from EnvoyDeployment will be ignored. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `envoyDeployment` | _[KubernetesDeploymentSpec](#kubernetesdeploymentspec)_ | false | EnvoyDeployment defines the desired state of the Envoy deployment resource. If unspecified, default settings for the managed Envoy deployment resource are applied. | +| `envoyService` | _[KubernetesServiceSpec](#kubernetesservicespec)_ | false | EnvoyService defines the desired state of the Envoy service resource. If unspecified, default settings for the managed Envoy service resource are applied. | +| `envoyHpa` | _[KubernetesHorizontalPodAutoscalerSpec](#kuberneteshorizontalpodautoscalerspec)_ | false | EnvoyHpa defines the Horizontal Pod Autoscaler settings for Envoy Proxy Deployment. Once the HPA is being set, Replicas field from EnvoyDeployment will be ignored. | #### EnvoyProxyProvider @@ -694,10 +857,10 @@ EnvoyProxyProvider defines the desired state of a resource provider. _Appears in:_ - [EnvoyProxySpec](#envoyproxyspec) -| Field | Description | -| --- | --- | -| `type` _[ProviderType](#providertype)_ | Type is the type of resource provider to use. A resource provider provides infrastructure resources for running the data plane, e.g. Envoy proxy, and optional auxiliary control planes. Supported types are "Kubernetes". | -| `kubernetes` _[EnvoyProxyKubernetesProvider](#envoyproxykubernetesprovider)_ | Kubernetes defines the desired state of the Kubernetes resource provider. Kubernetes provides infrastructure resources for running the data plane, e.g. Envoy proxy. If unspecified and type is "Kubernetes", default settings for managed Kubernetes resources are applied. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | _[ProviderType](#providertype)_ | true | Type is the type of resource provider to use. A resource provider provides infrastructure resources for running the data plane, e.g. Envoy proxy, and optional auxiliary control planes. Supported types are "Kubernetes". | +| `kubernetes` | _[EnvoyProxyKubernetesProvider](#envoyproxykubernetesprovider)_ | false | Kubernetes defines the desired state of the Kubernetes resource provider. Kubernetes provides infrastructure resources for running the data plane, e.g. Envoy proxy. If unspecified and type is "Kubernetes", default settings for managed Kubernetes resources are applied. | #### EnvoyProxySpec @@ -709,21 +872,22 @@ EnvoyProxySpec defines the desired state of EnvoyProxy. _Appears in:_ - [EnvoyProxy](#envoyproxy) -| Field | Description | -| --- | --- | -| `provider` _[EnvoyProxyProvider](#envoyproxyprovider)_ | Provider defines the desired resource provider and provider-specific configuration. If unspecified, the "Kubernetes" resource provider is used with default configuration parameters. | -| `logging` _[ProxyLogging](#proxylogging)_ | Logging defines logging parameters for managed proxies. | -| `telemetry` _[ProxyTelemetry](#proxytelemetry)_ | Telemetry defines telemetry parameters for managed proxies. | -| `bootstrap` _[ProxyBootstrap](#proxybootstrap)_ | Bootstrap defines the Envoy Bootstrap as a YAML string. Visit https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/bootstrap/v3/bootstrap.proto#envoy-v3-api-msg-config-bootstrap-v3-bootstrap to learn more about the syntax. If set, this is the Bootstrap configuration used for the managed Envoy Proxy fleet instead of the default Bootstrap configuration set by Envoy Gateway. Some fields within the Bootstrap that are required to communicate with the xDS Server (Envoy Gateway) and receive xDS resources from it are not configurable and will result in the `EnvoyProxy` resource being rejected. Backward compatibility across minor versions is not guaranteed. We strongly recommend using `egctl x translate` to generate a `EnvoyProxy` resource with the `Bootstrap` field set to the default Bootstrap configuration used. You can edit this configuration, and rerun `egctl x translate` to ensure there are no validation errors. | -| `concurrency` _integer_ | Concurrency defines the number of worker threads to run. If unset, it defaults to the number of cpuset threads on the platform. | -| `mergeGateways` _boolean_ | MergeGateways defines if Gateway resources should be merged onto the same Envoy Proxy Infrastructure. Setting this field to true would merge all Gateway Listeners under the parent Gateway Class. This means that the port, protocol and hostname tuple must be unique for every listener. If a duplicate listener is detected, the newer listener (based on timestamp) will be rejected and its status will be updated with a "Accepted=False" condition. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `provider` | _[EnvoyProxyProvider](#envoyproxyprovider)_ | false | Provider defines the desired resource provider and provider-specific configuration. If unspecified, the "Kubernetes" resource provider is used with default configuration parameters. | +| `logging` | _[ProxyLogging](#proxylogging)_ | true | Logging defines logging parameters for managed proxies. | +| `telemetry` | _[ProxyTelemetry](#proxytelemetry)_ | false | Telemetry defines telemetry parameters for managed proxies. | +| `bootstrap` | _[ProxyBootstrap](#proxybootstrap)_ | false | Bootstrap defines the Envoy Bootstrap as a YAML string. Visit https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/bootstrap/v3/bootstrap.proto#envoy-v3-api-msg-config-bootstrap-v3-bootstrap to learn more about the syntax. If set, this is the Bootstrap configuration used for the managed Envoy Proxy fleet instead of the default Bootstrap configuration set by Envoy Gateway. Some fields within the Bootstrap that are required to communicate with the xDS Server (Envoy Gateway) and receive xDS resources from it are not configurable and will result in the `EnvoyProxy` resource being rejected. Backward compatibility across minor versions is not guaranteed. We strongly recommend using `egctl x translate` to generate a `EnvoyProxy` resource with the `Bootstrap` field set to the default Bootstrap configuration used. You can edit this configuration, and rerun `egctl x translate` to ensure there are no validation errors. | +| `concurrency` | _integer_ | false | Concurrency defines the number of worker threads to run. If unset, it defaults to the number of cpuset threads on the platform. | +| `extraArgs` | _string array_ | false | ExtraArgs defines additional command line options that are provided to Envoy. More info: https://www.envoyproxy.io/docs/envoy/latest/operations/cli#command-line-options Note: some command line options are used internally(e.g. --log-level) so they cannot be provided here. | +| `mergeGateways` | _boolean_ | false | MergeGateways defines if Gateway resources should be merged onto the same Envoy Proxy Infrastructure. Setting this field to true would merge all Gateway Listeners under the parent Gateway Class. This means that the port, protocol and hostname tuple must be unique for every listener. If a duplicate listener is detected, the newer listener (based on timestamp) will be rejected and its status will be updated with a "Accepted=False" condition. | #### EnvoyResourceType -_Underlying type:_ `string` +_Underlying type:_ _string_ EnvoyResourceType specifies the type URL of the Envoy resource. @@ -732,6 +896,22 @@ _Appears in:_ +#### ExtAuth + + + +ExtAuth defines the configuration for External Authorization. + +_Appears in:_ +- [SecurityPolicySpec](#securitypolicyspec) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `grpc` | _[GRPCExtAuthService](#grpcextauthservice)_ | true | GRPC defines the gRPC External Authorization service. Either GRPCService or HTTPService must be specified, and only one of them can be provided. | +| `http` | _[HTTPExtAuthService](#httpextauthservice)_ | true | HTTP defines the HTTP External Authorization service. Either GRPCService or HTTPService must be specified, and only one of them can be provided. | +| `headersToExtAuth` | _string array_ | false | HeadersToExtAuth defines the client request headers that will be included in the request to the external authorization service. Note: If not specified, the default behavior for gRPC and HTTP external authorization services is different due to backward compatibility reasons. All headers will be included in the check request to a gRPC authorization server. Only the following headers will be included in the check request to an HTTP authorization server: Host, Method, Path, Content-Length, and Authorization. And these headers will always be included to the check request to an HTTP authorization server by default, no matter whether they are specified in HeadersToExtAuth or not. | + + #### ExtensionAPISettings @@ -742,9 +922,9 @@ _Appears in:_ - [EnvoyGateway](#envoygateway) - [EnvoyGatewaySpec](#envoygatewayspec) -| Field | Description | -| --- | --- | -| `enableEnvoyPatchPolicy` _boolean_ | EnableEnvoyPatchPolicy enables Envoy Gateway to reconcile and implement the EnvoyPatchPolicy resources. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `enableEnvoyPatchPolicy` | _boolean_ | true | EnableEnvoyPatchPolicy enables Envoy Gateway to reconcile and implement the EnvoyPatchPolicy resources. | #### ExtensionHooks @@ -756,9 +936,9 @@ ExtensionHooks defines extension hooks across all supported runners _Appears in:_ - [ExtensionManager](#extensionmanager) -| Field | Description | -| --- | --- | -| `xdsTranslator` _[XDSTranslatorHooks](#xdstranslatorhooks)_ | XDSTranslator defines all the supported extension hooks for the xds-translator runner | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `xdsTranslator` | _[XDSTranslatorHooks](#xdstranslatorhooks)_ | true | XDSTranslator defines all the supported extension hooks for the xds-translator runner | #### ExtensionManager @@ -771,11 +951,11 @@ _Appears in:_ - [EnvoyGateway](#envoygateway) - [EnvoyGatewaySpec](#envoygatewayspec) -| Field | Description | -| --- | --- | -| `resources` _[GroupVersionKind](#groupversionkind) array_ | Resources defines the set of K8s resources the extension will handle. | -| `hooks` _[ExtensionHooks](#extensionhooks)_ | Hooks defines the set of hooks the extension supports | -| `service` _[ExtensionService](#extensionservice)_ | Service defines the configuration of the extension service that the Envoy Gateway Control Plane will call through extension hooks. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `resources` | _[GroupVersionKind](#groupversionkind) array_ | false | Resources defines the set of K8s resources the extension will handle. | +| `hooks` | _[ExtensionHooks](#extensionhooks)_ | true | Hooks defines the set of hooks the extension supports | +| `service` | _[ExtensionService](#extensionservice)_ | true | Service defines the configuration of the extension service that the Envoy Gateway Control Plane will call through extension hooks. | #### ExtensionService @@ -787,11 +967,11 @@ ExtensionService defines the configuration for connecting to a registered extens _Appears in:_ - [ExtensionManager](#extensionmanager) -| Field | Description | -| --- | --- | -| `host` _string_ | Host define the extension service hostname. | -| `port` _integer_ | Port defines the port the extension service is exposed on. | -| `tls` _[ExtensionTLS](#extensiontls)_ | TLS defines TLS configuration for communication between Envoy Gateway and the extension service. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `host` | _string_ | true | Host define the extension service hostname. | +| `port` | _integer_ | false | Port defines the port the extension service is exposed on. | +| `tls` | _[ExtensionTLS](#extensiontls)_ | false | TLS defines TLS configuration for communication between Envoy Gateway and the extension service. | #### ExtensionTLS @@ -803,10 +983,9 @@ ExtensionTLS defines the TLS configuration when connecting to an extension servi _Appears in:_ - [ExtensionService](#extensionservice) -| Field | Description | -| --- | --- | -| `certificateRef` _[SecretObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.SecretObjectReference)_ | CertificateRef contains a references to objects (Kubernetes objects or otherwise) that contains a TLS certificate and private keys. These certificates are used to establish a TLS handshake to the extension server. - CertificateRef can only reference a Kubernetes Secret at this time. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `certificateRef` | _[SecretObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.SecretObjectReference)_ | true | CertificateRef contains a references to objects (Kubernetes objects or otherwise) that contains a TLS certificate and private keys. These certificates are used to establish a TLS handshake to the extension server.

CertificateRef can only reference a Kubernetes Secret at this time. | #### FaultInjection @@ -818,10 +997,10 @@ FaultInjection defines the fault injection policy to be applied. This configurat _Appears in:_ - [BackendTrafficPolicySpec](#backendtrafficpolicyspec) -| Field | Description | -| --- | --- | -| `delay` _[FaultInjectionDelay](#faultinjectiondelay)_ | If specified, a delay will be injected into the request. | -| `abort` _[FaultInjectionAbort](#faultinjectionabort)_ | If specified, the request will be aborted if it meets the configuration criteria. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `delay` | _[FaultInjectionDelay](#faultinjectiondelay)_ | false | If specified, a delay will be injected into the request. | +| `abort` | _[FaultInjectionAbort](#faultinjectionabort)_ | false | If specified, the request will be aborted if it meets the configuration criteria. | #### FaultInjectionAbort @@ -833,11 +1012,11 @@ FaultInjectionAbort defines the abort fault injection configuration _Appears in:_ - [FaultInjection](#faultinjection) -| Field | Description | -| --- | --- | -| `httpStatus` _integer_ | StatusCode specifies the HTTP status code to be returned | -| `grpcStatus` _integer_ | GrpcStatus specifies the GRPC status code to be returned | -| `percentage` _float_ | Percentage specifies the percentage of requests to be aborted. Default 100%, if set 0, no requests will be aborted. Accuracy to 0.0001%. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `httpStatus` | _integer_ | false | StatusCode specifies the HTTP status code to be returned | +| `grpcStatus` | _integer_ | false | GrpcStatus specifies the GRPC status code to be returned | +| `percentage` | _float_ | false | Percentage specifies the percentage of requests to be aborted. Default 100%, if set 0, no requests will be aborted. Accuracy to 0.0001%. | #### FaultInjectionDelay @@ -849,10 +1028,10 @@ FaultInjectionDelay defines the delay fault injection configuration _Appears in:_ - [FaultInjection](#faultinjection) -| Field | Description | -| --- | --- | -| `fixedDelay` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ | FixedDelay specifies the fixed delay duration | -| `percentage` _float_ | Percentage specifies the percentage of requests to be delayed. Default 100%, if set 0, no requests will be delayed. Accuracy to 0.0001%. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `fixedDelay` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ | true | FixedDelay specifies the fixed delay duration | +| `percentage` | _float_ | false | Percentage specifies the percentage of requests to be delayed. Default 100%, if set 0, no requests will be delayed. Accuracy to 0.0001%. | #### FileEnvoyProxyAccessLog @@ -864,9 +1043,23 @@ _Appears in:_ _Appears in:_ - [ProxyAccessLogSink](#proxyaccesslogsink) -| Field | Description | -| --- | --- | -| `path` _string_ | Path defines the file path used to expose envoy access log(e.g. /dev/stdout). | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `path` | _string_ | true | Path defines the file path used to expose envoy access log(e.g. /dev/stdout). | + + +#### GRPCExtAuthService + + + +GRPCExtAuthService defines the gRPC External Authorization service The authorization request message is defined in https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto + +_Appears in:_ +- [ExtAuth](#extauth) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `backendRef` | _[BackendObjectReference](#backendobjectreference)_ | true | BackendRef references a Kubernetes object that represents the backend server to which the authorization request will be sent. Only service Kind is supported for now. | #### Gateway @@ -879,9 +1072,9 @@ _Appears in:_ - [EnvoyGateway](#envoygateway) - [EnvoyGatewaySpec](#envoygatewayspec) -| Field | Description | -| --- | --- | -| `controllerName` _string_ | ControllerName defines the name of the Gateway API controller. If unspecified, defaults to "gateway.envoyproxy.io/gatewayclass-controller". See the following for additional details: https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1.GatewayClass | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `controllerName` | _string_ | false | ControllerName defines the name of the Gateway API controller. If unspecified, defaults to "gateway.envoyproxy.io/gatewayclass-controller". See the following for additional details: https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1.GatewayClass | #### GlobalRateLimit @@ -893,9 +1086,9 @@ GlobalRateLimit defines global rate limit configuration. _Appears in:_ - [RateLimitSpec](#ratelimitspec) -| Field | Description | -| --- | --- | -| `rules` _[RateLimitRule](#ratelimitrule) array_ | Rules are a list of RateLimit selectors and limits. Each rule and its associated limit is applied in a mutually exclusive way. If a request matches multiple rules, each of their associated limits get applied, so a single request might increase the rate limit counters for multiple rules if selected. The rate limit service will return a logical OR of the individual rate limit decisions of all matching rules. For example, if a request matches two rules, one rate limited and one not, the final decision will be to rate limit the request. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `rules` | _[RateLimitRule](#ratelimitrule) array_ | true | Rules are a list of RateLimit selectors and limits. Each rule and its associated limit is applied in a mutually exclusive way. If a request matches multiple rules, each of their associated limits get applied, so a single request might increase the rate limit counters for multiple rules if selected. The rate limit service will return a logical OR of the individual rate limit decisions of all matching rules. For example, if a request matches two rules, one rate limited and one not, the final decision will be to rate limit the request. | #### GroupVersionKind @@ -907,11 +1100,52 @@ GroupVersionKind unambiguously identifies a Kind. It can be converted to k8s.io/ _Appears in:_ - [ExtensionManager](#extensionmanager) -| Field | Description | -| --- | --- | -| `group` _string_ | | -| `version` _string_ | | -| `kind` _string_ | | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `group` | _string_ | true | | +| `version` | _string_ | true | | +| `kind` | _string_ | true | | + + +#### GzipCompressor + + + +GzipCompressor defines the config for the Gzip compressor. The default values can be found here: https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/compression/gzip/compressor/v3/gzip.proto#extension-envoy-compression-gzip-compressor + +_Appears in:_ +- [Compression](#compression) + + + +#### HTTP10Settings + + + +HTTP10Settings provides HTTP/1.0 configuration on the listener. + +_Appears in:_ +- [HTTP1Settings](#http1settings) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `useDefaultHost` | _boolean_ | false | UseDefaultHost defines if the HTTP/1.0 request is missing the Host header, then the hostname associated with the listener should be injected into the request. If this is not set and an HTTP/1.0 request arrives without a host, then it will be rejected. | + + +#### HTTP1Settings + + + +HTTP1Settings provides HTTP/1 configuration on the listener. + +_Appears in:_ +- [ClientTrafficPolicySpec](#clienttrafficpolicyspec) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `enableTrailers` | _boolean_ | false | EnableTrailers defines if HTTP/1 trailers should be proxied by Envoy. | +| `preserveHeaderCase` | _boolean_ | false | PreserveHeaderCase defines if Envoy should preserve the letter case of headers. By default, Envoy will lowercase all the headers. | +| `http10` | _[HTTP10Settings](#http10settings)_ | false | HTTP10 turns on support for HTTP/1.0 and HTTP/0.9 requests. | #### HTTP3Settings @@ -925,107 +1159,125 @@ _Appears in:_ -#### HTTPHealthChecker +#### HTTPActiveHealthChecker -HTTPHealthChecker defines the settings of http health check. +HTTPActiveHealthChecker defines the settings of http health check. _Appears in:_ -- [HealthCheck](#healthcheck) +- [ActiveHealthCheck](#activehealthcheck) -| Field | Description | -| --- | --- | -| `path` _string_ | Path defines the HTTP path that will be requested during health checking. | -| `method` _string_ | Method defines the HTTP method used for health checking. Defaults to GET | -| `expectedStatuses` _[HTTPStatus](#httpstatus) array_ | ExpectedStatuses defines a list of HTTP response statuses considered healthy. Defaults to 200 only | -| `expectedResponse` _[HealthCheckPayload](#healthcheckpayload)_ | ExpectedResponse defines a list of HTTP expected responses to match. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `path` | _string_ | true | Path defines the HTTP path that will be requested during health checking. | +| `method` | _string_ | false | Method defines the HTTP method used for health checking. Defaults to GET | +| `expectedStatuses` | _[HTTPStatus](#httpstatus) array_ | false | ExpectedStatuses defines a list of HTTP response statuses considered healthy. Defaults to 200 only | +| `expectedResponse` | _[ActiveHealthCheckPayload](#activehealthcheckpayload)_ | false | ExpectedResponse defines a list of HTTP expected responses to match. | + + +#### HTTPClientTimeout -#### HTTPStatus -_Underlying type:_ `integer` -HTTPStatus defines the http status code. _Appears in:_ -- [HTTPHealthChecker](#httphealthchecker) +- [ClientTimeout](#clienttimeout) +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `requestReceivedTimeout` | _[Duration](#duration)_ | false | The duration envoy waits for the complete request reception. This timer starts upon request initiation and stops when either the last byte of the request is sent upstream or when the response begins. | -#### HeaderMatch +#### HTTPExtAuthService -HeaderMatch defines the match attributes within the HTTP Headers of the request. +HTTPExtAuthService defines the HTTP External Authorization service _Appears in:_ -- [RateLimitSelectCondition](#ratelimitselectcondition) +- [ExtAuth](#extauth) +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `backendRef` | _[BackendObjectReference](#backendobjectreference)_ | true | BackendRef references a Kubernetes object that represents the backend server to which the authorization request will be sent. Only service Kind is supported for now. | +| `path` | _string_ | true | Path is the path of the HTTP External Authorization service. If path is specified, the authorization request will be sent to that path, or else the authorization request will be sent to the root path. | +| `headersToBackend` | _string array_ | false | HeadersToBackend are the authorization response headers that will be added to the original client request before sending it to the backend server. Note that coexisting headers will be overridden. If not specified, no authorization response headers will be added to the original client request. | -#### HealthCheck +#### HTTPStatus + +_Underlying type:_ _integer_ + +HTTPStatus defines the http status code. + +_Appears in:_ +- [HTTPActiveHealthChecker](#httpactivehealthchecker) +- [RetryOn](#retryon) + + + +#### HTTPTimeout + -HealthCheck defines the health check configuration. EG supports various types of health checking including HTTP, TCP. _Appears in:_ -- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) +- [Timeout](#timeout) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `connectionIdleTimeout` | _[Duration](#duration)_ | false | The idle timeout for an HTTP connection. Idle time is defined as a period in which there are no active requests in the connection. Default: 1 hour. | +| `maxConnectionDuration` | _[Duration](#duration)_ | false | The maximum duration of an HTTP connection. Default: unlimited. | -| Field | Description | -| --- | --- | -| `timeout` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ | Timeout defines the time to wait for a health check response. | -| `interval` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ | Interval defines the time between health checks. | -| `unhealthyThreshold` _integer_ | UnhealthyThreshold defines the number of unhealthy health checks required before a backend host is marked unhealthy. | -| `healthyThreshold` _integer_ | HealthyThreshold defines the number of healthy health checks required before a backend host is marked healthy. | -| `type` _[HealthCheckerType](#healthcheckertype)_ | Type defines the type of health checker. | -| `http` _[HTTPHealthChecker](#httphealthchecker)_ | HTTP defines the configuration of http health checker. It's required while the health checker type is HTTP. | -| `tcp` _[TCPHealthChecker](#tcphealthchecker)_ | TCP defines the configuration of tcp health checker. It's required while the health checker type is TCP. | -#### HealthCheckPayload +#### HeaderMatchType +_Underlying type:_ _string_ -HealthCheckPayload defines the encoding of the payload bytes in the payload. +HeaderMatchType specifies the semantics of how HTTP header values should be compared. Valid HeaderMatchType values are "Exact", "RegularExpression", and "Distinct". _Appears in:_ -- [HTTPHealthChecker](#httphealthchecker) -- [TCPHealthChecker](#tcphealthchecker) +- [HeaderMatch](#headermatch) + -| Field | Description | -| --- | --- | -| `type` _[HealthCheckPayloadType](#healthcheckpayloadtype)_ | Type defines the type of the payload. | -| `text` _string_ | Text payload in plain text. | -| `binary` _integer array_ | Binary payload base64 encoded. | +#### HeaderSettings -#### HealthCheckPayloadType -_Underlying type:_ `string` -HealthCheckPayloadType is the type of the payload. +HeaderSettings providess configuration options for headers on the listener. _Appears in:_ -- [HealthCheckPayload](#healthcheckpayload) +- [ClientTrafficPolicySpec](#clienttrafficpolicyspec) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `enableEnvoyHeaders` | _boolean_ | false | EnableEnvoyHeaders configures Envoy Proxy to add the "X-Envoy-" headers to requests and responses. | +#### HealthCheck -#### HealthCheckerType -_Underlying type:_ `string` -HealthCheckerType is the type of health checker. +HealthCheck configuration to decide which endpoints are healthy and can be used for routing. _Appears in:_ -- [HealthCheck](#healthcheck) +- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `active` | _[ActiveHealthCheck](#activehealthcheck)_ | false | Active health check configuration | +| `passive` | _[PassiveHealthCheck](#passivehealthcheck)_ | false | Passive passive check configuration | #### InfrastructureProviderType -_Underlying type:_ `string` +_Underlying type:_ _string_ InfrastructureProviderType defines the types of custom infrastructure providers supported by Envoy Gateway. @@ -1043,16 +1295,17 @@ JSONPatchOperation defines the JSON Patch Operation as defined in https://datatr _Appears in:_ - [EnvoyJSONPatchConfig](#envoyjsonpatchconfig) -| Field | Description | -| --- | --- | -| `op` _[JSONPatchOperationType](#jsonpatchoperationtype)_ | Op is the type of operation to perform | -| `path` _string_ | Path is the location of the target document/field where the operation will be performed Refer to https://datatracker.ietf.org/doc/html/rfc6901 for more details. | -| `value` _[JSON](#json)_ | Value is the new value of the path location. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `op` | _[JSONPatchOperationType](#jsonpatchoperationtype)_ | true | Op is the type of operation to perform | +| `path` | _string_ | true | Path is the location of the target document/field where the operation will be performed Refer to https://datatracker.ietf.org/doc/html/rfc6901 for more details. | +| `from` | _string_ | false | From is the source location of the value to be copied or moved. Only valid for move or copy operations Refer to https://datatracker.ietf.org/doc/html/rfc6901 for more details. | +| `value` | _[JSON](#json)_ | false | Value is the new value of the path location. The value is only used by the `add` and `replace` operations. | #### JSONPatchOperationType -_Underlying type:_ `string` +_Underlying type:_ _string_ JSONPatchOperationType specifies the JSON Patch operations that can be performed. @@ -1070,23 +1323,40 @@ JWT defines the configuration for JSON Web Token (JWT) authentication. _Appears in:_ - [SecurityPolicySpec](#securitypolicyspec) -| Field | Description | -| --- | --- | -| `providers` _[JWTProvider](#jwtprovider) array_ | Providers defines the JSON Web Token (JWT) authentication provider type. When multiple JWT providers are specified, the JWT is considered valid if any of the providers successfully validate the JWT. For additional details, see https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/jwt_authn_filter.html. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `providers` | _[JWTProvider](#jwtprovider) array_ | true | Providers defines the JSON Web Token (JWT) authentication provider type. When multiple JWT providers are specified, the JWT is considered valid if any of the providers successfully validate the JWT. For additional details, see https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/jwt_authn_filter.html. | #### JWTExtractor -JWTExtractor defines a custom JWT token extraction from HTTP request. +JWTExtractor defines a custom JWT token extraction from HTTP request. If specified, Envoy will extract the JWT token from the listed extractors (headers, cookies, or params) and validate each of them. If any value extracted is found to be an invalid JWT, a 401 error will be returned. _Appears in:_ - [JWTProvider](#jwtprovider) -| Field | Description | -| --- | --- | -| `cookies` _string array_ | Cookies represents a list of cookie names to extract the JWT token from. If specified, Envoy will extract the JWT token from the listed cookies and validate each of them. If any cookie is found to be an invalid JWT, a 401 error will be returned. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `headers` | _[JWTHeaderExtractor](#jwtheaderextractor) array_ | false | Headers represents a list of HTTP request headers to extract the JWT token from. | +| `cookies` | _string array_ | false | Cookies represents a list of cookie names to extract the JWT token from. | +| `params` | _string array_ | false | Params represents a list of query parameters to extract the JWT token from. | + + +#### JWTHeaderExtractor + + + +JWTHeaderExtractor defines an HTTP header location to extract JWT token + +_Appears in:_ +- [JWTExtractor](#jwtextractor) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `name` | _string_ | true | Name is the HTTP header name to retrieve the token | +| `valuePrefix` | _string_ | false | ValuePrefix is the prefix that should be stripped before extracting the token. The format would be used by Envoy like "{ValuePrefix}". For example, "Authorization: Bearer ", then the ValuePrefix="Bearer " with a space at the end. | #### JWTProvider @@ -1098,14 +1368,14 @@ JWTProvider defines how a JSON Web Token (JWT) can be verified. _Appears in:_ - [JWT](#jwt) -| Field | Description | -| --- | --- | -| `name` _string_ | Name defines a unique name for the JWT provider. A name can have a variety of forms, including RFC1123 subdomains, RFC 1123 labels, or RFC 1035 labels. | -| `issuer` _string_ | Issuer is the principal that issued the JWT and takes the form of a URL or email address. For additional details, see https://tools.ietf.org/html/rfc7519#section-4.1.1 for URL format and https://rfc-editor.org/rfc/rfc5322.html for email format. If not provided, the JWT issuer is not checked. | -| `audiences` _string array_ | Audiences is a list of JWT audiences allowed access. For additional details, see https://tools.ietf.org/html/rfc7519#section-4.1.3. If not provided, JWT audiences are not checked. | -| `remoteJWKS` _[RemoteJWKS](#remotejwks)_ | RemoteJWKS defines how to fetch and cache JSON Web Key Sets (JWKS) from a remote HTTP/HTTPS endpoint. | -| `claimToHeaders` _[ClaimToHeader](#claimtoheader) array_ | ClaimToHeaders is a list of JWT claims that must be extracted into HTTP request headers For examples, following config: The claim must be of type; string, int, double, bool. Array type claims are not supported | -| `extractFrom` _[JWTExtractor](#jwtextractor)_ | ExtractFrom defines different ways to extract the JWT token from HTTP request. If empty, it defaults to extract JWT token from the Authorization HTTP request header using Bearer schema or access_token from query parameters. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `name` | _string_ | true | Name defines a unique name for the JWT provider. A name can have a variety of forms, including RFC1123 subdomains, RFC 1123 labels, or RFC 1035 labels. | +| `issuer` | _string_ | false | Issuer is the principal that issued the JWT and takes the form of a URL or email address. For additional details, see https://tools.ietf.org/html/rfc7519#section-4.1.1 for URL format and https://rfc-editor.org/rfc/rfc5322.html for email format. If not provided, the JWT issuer is not checked. | +| `audiences` | _string array_ | false | Audiences is a list of JWT audiences allowed access. For additional details, see https://tools.ietf.org/html/rfc7519#section-4.1.3. If not provided, JWT audiences are not checked. | +| `remoteJWKS` | _[RemoteJWKS](#remotejwks)_ | true | RemoteJWKS defines how to fetch and cache JSON Web Key Sets (JWKS) from a remote HTTP/HTTPS endpoint. | +| `claimToHeaders` | _[ClaimToHeader](#claimtoheader) array_ | true | ClaimToHeaders is a list of JWT claims that must be extracted into HTTP request headers For examples, following config: The claim must be of type; string, int, double, bool. Array type claims are not supported | +| `extractFrom` | _[JWTExtractor](#jwtextractor)_ | false | ExtractFrom defines different ways to extract the JWT token from HTTP request. If empty, it defaults to extract JWT token from the Authorization HTTP request header using Bearer schema or access_token from query parameters. | #### KubernetesContainerSpec @@ -1117,13 +1387,13 @@ KubernetesContainerSpec defines the desired state of the Kubernetes container re _Appears in:_ - [KubernetesDeploymentSpec](#kubernetesdeploymentspec) -| Field | Description | -| --- | --- | -| `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#envvar-v1-core) array_ | List of environment variables to set in the container. | -| `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#resourcerequirements-v1-core)_ | Resources required by this container. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ | -| `securityContext` _[SecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#securitycontext-v1-core)_ | SecurityContext defines the security options the container should be run with. If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ | -| `image` _string_ | Image specifies the EnvoyProxy container image to be used, instead of the default image. | -| `volumeMounts` _[VolumeMount](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#volumemount-v1-core) array_ | VolumeMounts are volumes to mount into the container's filesystem. Cannot be updated. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `env` | _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#envvar-v1-core) array_ | false | List of environment variables to set in the container. | +| `resources` | _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#resourcerequirements-v1-core)_ | false | Resources required by this container. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ | +| `securityContext` | _[SecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#securitycontext-v1-core)_ | false | SecurityContext defines the security options the container should be run with. If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ | +| `image` | _string_ | false | Image specifies the EnvoyProxy container image to be used, instead of the default image. | +| `volumeMounts` | _[VolumeMount](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#volumemount-v1-core) array_ | false | VolumeMounts are volumes to mount into the container's filesystem. Cannot be updated. | #### KubernetesDeployMode @@ -1147,13 +1417,13 @@ _Appears in:_ - [EnvoyGatewayKubernetesProvider](#envoygatewaykubernetesprovider) - [EnvoyProxyKubernetesProvider](#envoyproxykubernetesprovider) -| Field | Description | -| --- | --- | -| `replicas` _integer_ | Replicas is the number of desired pods. Defaults to 1. | -| `strategy` _[DeploymentStrategy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#deploymentstrategy-v1-apps)_ | The deployment strategy to use to replace existing pods with new ones. | -| `pod` _[KubernetesPodSpec](#kubernetespodspec)_ | Pod defines the desired specification of pod. | -| `container` _[KubernetesContainerSpec](#kubernetescontainerspec)_ | Container defines the desired specification of main container. | -| `initContainers` _[Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#container-v1-core) array_ | List of initialization containers belonging to the pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `replicas` | _integer_ | false | Replicas is the number of desired pods. Defaults to 1. | +| `strategy` | _[DeploymentStrategy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#deploymentstrategy-v1-apps)_ | false | The deployment strategy to use to replace existing pods with new ones. | +| `pod` | _[KubernetesPodSpec](#kubernetespodspec)_ | false | Pod defines the desired specification of pod. | +| `container` | _[KubernetesContainerSpec](#kubernetescontainerspec)_ | false | Container defines the desired specification of main container. | +| `initContainers` | _[Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#container-v1-core) array_ | false | List of initialization containers belonging to the pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ | #### KubernetesHorizontalPodAutoscalerSpec @@ -1165,12 +1435,12 @@ KubernetesHorizontalPodAutoscalerSpec defines Kubernetes Horizontal Pod Autoscal _Appears in:_ - [EnvoyProxyKubernetesProvider](#envoyproxykubernetesprovider) -| Field | Description | -| --- | --- | -| `minReplicas` _integer_ | minReplicas is the lower limit for the number of replicas to which the autoscaler can scale down. It defaults to 1 replica. | -| `maxReplicas` _integer_ | maxReplicas is the upper limit for the number of replicas to which the autoscaler can scale up. It cannot be less that minReplicas. | -| `metrics` _[MetricSpec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#metricspec-v2-autoscaling) array_ | metrics contains the specifications for which to use to calculate the desired replica count (the maximum replica count across all metrics will be used). If left empty, it defaults to being based on CPU utilization with average on 80% usage. | -| `behavior` _[HorizontalPodAutoscalerBehavior](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#horizontalpodautoscalerbehavior-v2-autoscaling)_ | behavior configures the scaling behavior of the target in both Up and Down directions (scaleUp and scaleDown fields respectively). If not set, the default HPAScalingRules for scale up and scale down are used. See k8s.io.autoscaling.v2.HorizontalPodAutoScalerBehavior. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `minReplicas` | _integer_ | false | minReplicas is the lower limit for the number of replicas to which the autoscaler can scale down. It defaults to 1 replica. | +| `maxReplicas` | _integer_ | true | maxReplicas is the upper limit for the number of replicas to which the autoscaler can scale up. It cannot be less that minReplicas. | +| `metrics` | _[MetricSpec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#metricspec-v2-autoscaling) array_ | false | metrics contains the specifications for which to use to calculate the desired replica count (the maximum replica count across all metrics will be used). If left empty, it defaults to being based on CPU utilization with average on 80% usage. | +| `behavior` | _[HorizontalPodAutoscalerBehavior](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#horizontalpodautoscalerbehavior-v2-autoscaling)_ | false | behavior configures the scaling behavior of the target in both Up and Down directions (scaleUp and scaleDown fields respectively). If not set, the default HPAScalingRules for scale up and scale down are used. See k8s.io.autoscaling.v2.HorizontalPodAutoScalerBehavior. | #### KubernetesPodSpec @@ -1182,18 +1452,18 @@ KubernetesPodSpec defines the desired state of the Kubernetes pod resource. _Appears in:_ - [KubernetesDeploymentSpec](#kubernetesdeploymentspec) -| Field | Description | -| --- | --- | -| `annotations` _object (keys:string, values:string)_ | Annotations are the annotations that should be appended to the pods. By default, no pod annotations are appended. | -| `labels` _object (keys:string, values:string)_ | Labels are the additional labels that should be tagged to the pods. By default, no additional pod labels are tagged. | -| `securityContext` _[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#podsecuritycontext-v1-core)_ | SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field. | -| `affinity` _[Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#affinity-v1-core)_ | If specified, the pod's scheduling constraints. | -| `tolerations` _[Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#toleration-v1-core) array_ | If specified, the pod's tolerations. | -| `volumes` _[Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#volume-v1-core) array_ | Volumes that can be mounted by containers belonging to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes | -| `hostNetwork` _boolean_ | HostNetwork, If this is set to true, the pod will use host's network namespace. | -| `imagePullSecrets` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#localobjectreference-v1-core) array_ | ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod | -| `nodeSelector` _object (keys:string, values:string)_ | NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node's labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ | -| `topologySpreadConstraints` _[TopologySpreadConstraint](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#topologyspreadconstraint-v1-core) array_ | TopologySpreadConstraints describes how a group of pods ought to spread across topology domains. Scheduler will schedule pods in a way which abides by the constraints. All topologySpreadConstraints are ANDed. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `annotations` | _object (keys:string, values:string)_ | false | Annotations are the annotations that should be appended to the pods. By default, no pod annotations are appended. | +| `labels` | _object (keys:string, values:string)_ | false | Labels are the additional labels that should be tagged to the pods. By default, no additional pod labels are tagged. | +| `securityContext` | _[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#podsecuritycontext-v1-core)_ | false | SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field. | +| `affinity` | _[Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#affinity-v1-core)_ | false | If specified, the pod's scheduling constraints. | +| `tolerations` | _[Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#toleration-v1-core) array_ | false | If specified, the pod's tolerations. | +| `volumes` | _[Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#volume-v1-core) array_ | false | Volumes that can be mounted by containers belonging to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes | +| `hostNetwork` | _boolean_ | false | HostNetwork, If this is set to true, the pod will use host's network namespace. | +| `imagePullSecrets` | _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#localobjectreference-v1-core) array_ | false | ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod | +| `nodeSelector` | _object (keys:string, values:string)_ | false | NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node's labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ | +| `topologySpreadConstraints` | _[TopologySpreadConstraint](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#topologyspreadconstraint-v1-core) array_ | false | TopologySpreadConstraints describes how a group of pods ought to spread across topology domains. Scheduler will schedule pods in a way which abides by the constraints. All topologySpreadConstraints are ANDed. | #### KubernetesServiceSpec @@ -1205,14 +1475,14 @@ KubernetesServiceSpec defines the desired state of the Kubernetes service resour _Appears in:_ - [EnvoyProxyKubernetesProvider](#envoyproxykubernetesprovider) -| Field | Description | -| --- | --- | -| `annotations` _object (keys:string, values:string)_ | Annotations that should be appended to the service. By default, no annotations are appended. | -| `type` _[ServiceType](#servicetype)_ | Type determines how the Service is exposed. Defaults to LoadBalancer. Valid options are ClusterIP, LoadBalancer and NodePort. "LoadBalancer" means a service will be exposed via an external load balancer (if the cloud provider supports it). "ClusterIP" means a service will only be accessible inside the cluster, via the cluster IP. "NodePort" means a service will be exposed on a static Port on all Nodes of the cluster. | -| `loadBalancerClass` _string_ | LoadBalancerClass, when specified, allows for choosing the LoadBalancer provider implementation if more than one are available or is otherwise expected to be specified | -| `allocateLoadBalancerNodePorts` _boolean_ | AllocateLoadBalancerNodePorts defines if NodePorts will be automatically allocated for services with type LoadBalancer. Default is "true". It may be set to "false" if the cluster load-balancer does not rely on NodePorts. If the caller requests specific NodePorts (by specifying a value), those requests will be respected, regardless of this field. This field may only be set for services with type LoadBalancer and will be cleared if the type is changed to any other type. | -| `loadBalancerIP` _string_ | LoadBalancerIP defines the IP Address of the underlying load balancer service. This field may be ignored if the load balancer provider does not support this feature. This field has been deprecated in Kubernetes, but it is still used for setting the IP Address in some cloud providers such as GCP. | -| `externalTrafficPolicy` _[ServiceExternalTrafficPolicy](#serviceexternaltrafficpolicy)_ | ExternalTrafficPolicy determines the externalTrafficPolicy for the Envoy Service. Valid options are Local and Cluster. Default is "Local". "Local" means traffic will only go to pods on the node receiving the traffic. "Cluster" means connections are loadbalanced to all pods in the cluster. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `annotations` | _object (keys:string, values:string)_ | false | Annotations that should be appended to the service. By default, no annotations are appended. | +| `type` | _[ServiceType](#servicetype)_ | false | Type determines how the Service is exposed. Defaults to LoadBalancer. Valid options are ClusterIP, LoadBalancer and NodePort. "LoadBalancer" means a service will be exposed via an external load balancer (if the cloud provider supports it). "ClusterIP" means a service will only be accessible inside the cluster, via the cluster IP. "NodePort" means a service will be exposed on a static Port on all Nodes of the cluster. | +| `loadBalancerClass` | _string_ | false | LoadBalancerClass, when specified, allows for choosing the LoadBalancer provider implementation if more than one are available or is otherwise expected to be specified | +| `allocateLoadBalancerNodePorts` | _boolean_ | false | AllocateLoadBalancerNodePorts defines if NodePorts will be automatically allocated for services with type LoadBalancer. Default is "true". It may be set to "false" if the cluster load-balancer does not rely on NodePorts. If the caller requests specific NodePorts (by specifying a value), those requests will be respected, regardless of this field. This field may only be set for services with type LoadBalancer and will be cleared if the type is changed to any other type. | +| `loadBalancerIP` | _string_ | false | LoadBalancerIP defines the IP Address of the underlying load balancer service. This field may be ignored if the load balancer provider does not support this feature. This field has been deprecated in Kubernetes, but it is still used for setting the IP Address in some cloud providers such as GCP. | +| `externalTrafficPolicy` | _[ServiceExternalTrafficPolicy](#serviceexternaltrafficpolicy)_ | false | ExternalTrafficPolicy determines the externalTrafficPolicy for the Envoy Service. Valid options are Local and Cluster. Default is "Local". "Local" means traffic will only go to pods on the node receiving the traffic. "Cluster" means connections are loadbalanced to all pods in the cluster. | #### KubernetesWatchMode @@ -1224,16 +1494,16 @@ KubernetesWatchMode holds the configuration for which input resources to watch a _Appears in:_ - [EnvoyGatewayKubernetesProvider](#envoygatewaykubernetesprovider) -| Field | Description | -| --- | --- | -| `type` _[KubernetesWatchModeType](#kuberneteswatchmodetype)_ | Type indicates what watch mode to use. KubernetesWatchModeTypeNamespaces and KubernetesWatchModeTypeNamespaceSelectors are currently supported By default, when this field is unset or empty, Envoy Gateway will watch for input namespaced resources from all namespaces. | -| `namespaces` _string array_ | Namespaces holds the list of namespaces that Envoy Gateway will watch for namespaced scoped resources such as Gateway, HTTPRoute and Service. Note that Envoy Gateway will continue to reconcile relevant cluster scoped resources such as GatewayClass that it is linked to. Precisely one of Namespaces and NamespaceSelectors must be set | -| `namespaceSelectors` _string array_ | NamespaceSelectors holds a list of labels that namespaces have to have in order to be watched. Note this doesn't set the informer to watch the namespaces with the given labels. Informer still watches all namespaces. But the events for objects whois namespce have no given labels will be filtered out. Precisely one of Namespaces and NamespaceSelectors must be set | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | _[KubernetesWatchModeType](#kuberneteswatchmodetype)_ | true | Type indicates what watch mode to use. KubernetesWatchModeTypeNamespaces and KubernetesWatchModeTypeNamespaceSelector are currently supported By default, when this field is unset or empty, Envoy Gateway will watch for input namespaced resources from all namespaces. | +| `namespaces` | _string array_ | true | Namespaces holds the list of namespaces that Envoy Gateway will watch for namespaced scoped resources such as Gateway, HTTPRoute and Service. Note that Envoy Gateway will continue to reconcile relevant cluster scoped resources such as GatewayClass that it is linked to. Precisely one of Namespaces and NamespaceSelector must be set. | +| `namespaceSelector` | _[LabelSelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#labelselector-v1-meta)_ | true | NamespaceSelector holds the label selector used to dynamically select namespaces. Envoy Gateway will watch for namespaces matching the specified label selector. Precisely one of Namespaces and NamespaceSelector must be set. | #### KubernetesWatchModeType -_Underlying type:_ `string` +_Underlying type:_ _string_ KubernetesWatchModeType defines the type of KubernetesWatchMode @@ -1251,9 +1521,9 @@ LiteralCustomTag adds hard-coded value to each span. _Appears in:_ - [CustomTag](#customtag) -| Field | Description | -| --- | --- | -| `value` _string_ | Value defines the hard-coded value to add to each span. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `value` | _string_ | true | Value defines the hard-coded value to add to each span. | #### LoadBalancer @@ -1265,16 +1535,16 @@ LoadBalancer defines the load balancer policy to be applied. _Appears in:_ - [BackendTrafficPolicySpec](#backendtrafficpolicyspec) -| Field | Description | -| --- | --- | -| `type` _[LoadBalancerType](#loadbalancertype)_ | Type decides the type of Load Balancer policy. Valid LoadBalancerType values are "ConsistentHash", "LeastRequest", "Random", "RoundRobin", | -| `consistentHash` _[ConsistentHash](#consistenthash)_ | ConsistentHash defines the configuration when the load balancer type is set to ConsistentHash | -| `slowStart` _[SlowStart](#slowstart)_ | SlowStart defines the configuration related to the slow start load balancer policy. If set, during slow start window, traffic sent to the newly added hosts will gradually increase. Currently this is only supported for RoundRobin and LeastRequest load balancers | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | _[LoadBalancerType](#loadbalancertype)_ | true | Type decides the type of Load Balancer policy. Valid LoadBalancerType values are "ConsistentHash", "LeastRequest", "Random", "RoundRobin", | +| `consistentHash` | _[ConsistentHash](#consistenthash)_ | false | ConsistentHash defines the configuration when the load balancer type is set to ConsistentHash | +| `slowStart` | _[SlowStart](#slowstart)_ | false | SlowStart defines the configuration related to the slow start load balancer policy. If set, during slow start window, traffic sent to the newly added hosts will gradually increase. Currently this is only supported for RoundRobin and LeastRequest load balancers | #### LoadBalancerType -_Underlying type:_ `string` +_Underlying type:_ _string_ LoadBalancerType specifies the types of LoadBalancer. @@ -1292,14 +1562,14 @@ LocalRateLimit defines local rate limit configuration. _Appears in:_ - [RateLimitSpec](#ratelimitspec) -| Field | Description | -| --- | --- | -| `rules` _[RateLimitRule](#ratelimitrule) array_ | Rules are a list of RateLimit selectors and limits. If a request matches multiple rules, the strictest limit is applied. For example, if a request matches two rules, one with 10rps and one with 20rps, the final limit will be based on the rule with 10rps. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `rules` | _[RateLimitRule](#ratelimitrule) array_ | false | Rules are a list of RateLimit selectors and limits. If a request matches multiple rules, the strictest limit is applied. For example, if a request matches two rules, one with 10rps and one with 20rps, the final limit will be based on the rule with 10rps. | #### LogLevel -_Underlying type:_ `string` +_Underlying type:_ _string_ LogLevel defines a log level for Envoy Gateway and EnvoyProxy system logs. @@ -1311,7 +1581,7 @@ _Appears in:_ #### MetricSinkType -_Underlying type:_ `string` +_Underlying type:_ _string_ @@ -1330,15 +1600,14 @@ OIDC defines the configuration for the OpenID Connect (OIDC) authentication. _Appears in:_ - [SecurityPolicySpec](#securitypolicyspec) -| Field | Description | -| --- | --- | -| `provider` _[OIDCProvider](#oidcprovider)_ | The OIDC Provider configuration. | -| `clientID` _string_ | The client ID to be used in the OIDC [Authentication Request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest). | -| `clientSecret` _[SecretObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.SecretObjectReference)_ | The Kubernetes secret which contains the OIDC client secret to be used in the [Authentication Request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest). - This is an Opaque secret. The client secret should be stored in the key "client-secret". | -| `scopes` _string array_ | The OIDC scopes to be used in the [Authentication Request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest). The "openid" scope is always added to the list of scopes if not already specified. | -| `redirectURL` _string_ | The redirect URL to be used in the OIDC [Authentication Request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest). If not specified, uses the default redirect URI "%REQ(x-forwarded-proto)%://%REQ(:authority)%/oauth2/callback" | -| `logoutPath` _string_ | The path to log a user out, clearing their credential cookies. If not specified, uses a default logout path "/logout" | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `provider` | _[OIDCProvider](#oidcprovider)_ | true | The OIDC Provider configuration. | +| `clientID` | _string_ | true | The client ID to be used in the OIDC [Authentication Request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest). | +| `clientSecret` | _[SecretObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.SecretObjectReference)_ | true | The Kubernetes secret which contains the OIDC client secret to be used in the [Authentication Request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest).

This is an Opaque secret. The client secret should be stored in the key "client-secret". | +| `scopes` | _string array_ | false | The OIDC scopes to be used in the [Authentication Request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest). The "openid" scope is always added to the list of scopes if not already specified. | +| `redirectURL` | _string_ | true | The redirect URL to be used in the OIDC [Authentication Request](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest). If not specified, uses the default redirect URI "%REQ(x-forwarded-proto)%://%REQ(:authority)%/oauth2/callback" | +| `logoutPath` | _string_ | true | The path to log a user out, clearing their credential cookies. If not specified, uses a default logout path "/logout" | #### OIDCProvider @@ -1350,11 +1619,11 @@ OIDCProvider defines the OIDC Provider configuration. _Appears in:_ - [OIDC](#oidc) -| Field | Description | -| --- | --- | -| `issuer` _string_ | The OIDC Provider's [issuer identifier](https://openid.net/specs/openid-connect-discovery-1_0.html#IssuerDiscovery). Issuer MUST be a URI RFC 3986 [RFC3986] with a scheme component that MUST be https, a host component, and optionally, port and path components and no query or fragment components. | -| `authorizationEndpoint` _string_ | The OIDC Provider's [authorization endpoint](https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint). If not provided, EG will try to discover it from the provider's [Well-Known Configuration Endpoint](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse). | -| `tokenEndpoint` _string_ | The OIDC Provider's [token endpoint](https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint). If not provided, EG will try to discover it from the provider's [Well-Known Configuration Endpoint](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse). | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `issuer` | _string_ | true | The OIDC Provider's [issuer identifier](https://openid.net/specs/openid-connect-discovery-1_0.html#IssuerDiscovery). Issuer MUST be a URI RFC 3986 [RFC3986] with a scheme component that MUST be https, a host component, and optionally, port and path components and no query or fragment components. | +| `authorizationEndpoint` | _string_ | false | The OIDC Provider's [authorization endpoint](https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint). If not provided, EG will try to discover it from the provider's [Well-Known Configuration Endpoint](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse). | +| `tokenEndpoint` | _string_ | false | The OIDC Provider's [token endpoint](https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint). If not provided, EG will try to discover it from the provider's [Well-Known Configuration Endpoint](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse). | #### OpenTelemetryEnvoyProxyAccessLog @@ -1366,16 +1635,48 @@ TODO: consider reuse ExtensionService? _Appears in:_ - [ProxyAccessLogSink](#proxyaccesslogsink) -| Field | Description | -| --- | --- | -| `host` _string_ | Host define the extension service hostname. | -| `port` _integer_ | Port defines the port the extension service is exposed on. | -| `resources` _object (keys:string, values:string)_ | Resources is a set of labels that describe the source of a log entry, including envoy node info. It's recommended to follow [semantic conventions](https://opentelemetry.io/docs/reference/specification/resource/semantic_conventions/). | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `host` | _string_ | true | Host define the extension service hostname. | +| `port` | _integer_ | false | Port defines the port the extension service is exposed on. | +| `resources` | _object (keys:string, values:string)_ | false | Resources is a set of labels that describe the source of a log entry, including envoy node info. It's recommended to follow [semantic conventions](https://opentelemetry.io/docs/reference/specification/resource/semantic_conventions/). | + + +#### Origin + +_Underlying type:_ _string_ + +Origin is defined by the scheme (protocol), hostname (domain), and port of the URL used to access it. The hostname can be "precise" which is just the domain name or "wildcard" which is a domain name prefixed with a single wildcard label such as "*.example.com". In addition to that a single wildcard (with or without scheme) can be configured to match any origin. + For example, the following are valid origins: - https://foo.example.com - https://*.example.com - http://foo.example.com:8080 - http://*.example.com:8080 - https://* + +_Appears in:_ +- [CORS](#cors) + + + +#### PassiveHealthCheck + + + +PassiveHealthCheck defines the configuration for passive health checks in the context of Envoy's Outlier Detection, see https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/outlier + +_Appears in:_ +- [HealthCheck](#healthcheck) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `splitExternalLocalOriginErrors` | _boolean_ | false | SplitExternalLocalOriginErrors enables splitting of errors between external and local origin. | +| `interval` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ | false | Interval defines the time between passive health checks. | +| `consecutiveLocalOriginFailures` | _integer_ | false | ConsecutiveLocalOriginFailures sets the number of consecutive local origin failures triggering ejection. Parameter takes effect only when split_external_local_origin_errors is set to true. | +| `consecutiveGatewayErrors` | _integer_ | false | ConsecutiveGatewayErrors sets the number of consecutive gateway errors triggering ejection. | +| `consecutive5XxErrors` | _integer_ | false | Consecutive5xxErrors sets the number of consecutive 5xx errors triggering ejection. | +| `baseEjectionTime` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ | false | BaseEjectionTime defines the base duration for which a host will be ejected on consecutive failures. | +| `maxEjectionPercent` | _integer_ | false | MaxEjectionPercent sets the maximum percentage of hosts in a cluster that can be ejected. | #### PathEscapedSlashAction -_Underlying type:_ `string` +_Underlying type:_ _string_ PathEscapedSlashAction determines the action for requests that contain %2F, %2f, %5C, or %5c sequences in the URI path. @@ -1393,15 +1694,30 @@ PathSettings provides settings that managing how the incoming path set by client _Appears in:_ - [ClientTrafficPolicySpec](#clienttrafficpolicyspec) -| Field | Description | -| --- | --- | -| `escapedSlashesAction` _[PathEscapedSlashAction](#pathescapedslashaction)_ | EscapedSlashesAction determines how %2f, %2F, %5c, or %5C sequences in the path URI should be handled. The default is UnescapeAndRedirect. | -| `disableMergeSlashes` _boolean_ | DisableMergeSlashes allows disabling the default configuration of merging adjacent slashes in the path. Note that slash merging is not part of the HTTP spec and is provided for convenience. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `escapedSlashesAction` | _[PathEscapedSlashAction](#pathescapedslashaction)_ | false | EscapedSlashesAction determines how %2f, %2F, %5c, or %5C sequences in the path URI should be handled. The default is UnescapeAndRedirect. | +| `disableMergeSlashes` | _boolean_ | false | DisableMergeSlashes allows disabling the default configuration of merging adjacent slashes in the path. Note that slash merging is not part of the HTTP spec and is provided for convenience. | + + +#### PerRetryPolicy + + + + + +_Appears in:_ +- [Retry](#retry) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `timeout` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ | false | Timeout is the timeout per retry attempt. | +| `backOff` | _[BackOffPolicy](#backoffpolicy)_ | false | Backoff is the backoff policy to be applied per retry attempt. gateway uses a fully jittered exponential back-off algorithm for retries. For additional details, see https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/router_filter#config-http-filters-router-x-envoy-max-retries | #### ProviderType -_Underlying type:_ `string` +_Underlying type:_ _string_ ProviderType defines the types of providers supported by Envoy Gateway. @@ -1420,10 +1736,10 @@ _Appears in:_ _Appears in:_ - [ProxyTelemetry](#proxytelemetry) -| Field | Description | -| --- | --- | -| `disable` _boolean_ | Disable disables access logging for managed proxies if set to true. | -| `settings` _[ProxyAccessLogSetting](#proxyaccesslogsetting) array_ | Settings defines accesslog settings for managed proxies. If unspecified, will send default format to stdout. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `disable` | _boolean_ | true | Disable disables access logging for managed proxies if set to true. | +| `settings` | _[ProxyAccessLogSetting](#proxyaccesslogsetting) array_ | false | Settings defines accesslog settings for managed proxies. If unspecified, will send default format to stdout. | #### ProxyAccessLogFormat @@ -1435,16 +1751,16 @@ ProxyAccessLogFormat defines the format of accesslog. By default accesslogs are _Appears in:_ - [ProxyAccessLogSetting](#proxyaccesslogsetting) -| Field | Description | -| --- | --- | -| `type` _[ProxyAccessLogFormatType](#proxyaccesslogformattype)_ | Type defines the type of accesslog format. | -| `text` _string_ | Text defines the text accesslog format, following Envoy accesslog formatting, It's required when the format type is "Text". Envoy [command operators](https://www.envoyproxy.io/docs/envoy/latest/configuration/observability/access_log/usage#command-operators) may be used in the format. The [format string documentation](https://www.envoyproxy.io/docs/envoy/latest/configuration/observability/access_log/usage#config-access-log-format-strings) provides more information. | -| `json` _object (keys:string, values:string)_ | JSON is additional attributes that describe the specific event occurrence. Structured format for the envoy access logs. Envoy [command operators](https://www.envoyproxy.io/docs/envoy/latest/configuration/observability/access_log/usage#command-operators) can be used as values for fields within the Struct. It's required when the format type is "JSON". | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | _[ProxyAccessLogFormatType](#proxyaccesslogformattype)_ | true | Type defines the type of accesslog format. | +| `text` | _string_ | false | Text defines the text accesslog format, following Envoy accesslog formatting, It's required when the format type is "Text". Envoy [command operators](https://www.envoyproxy.io/docs/envoy/latest/configuration/observability/access_log/usage#command-operators) may be used in the format. The [format string documentation](https://www.envoyproxy.io/docs/envoy/latest/configuration/observability/access_log/usage#config-access-log-format-strings) provides more information. | +| `json` | _object (keys:string, values:string)_ | false | JSON is additional attributes that describe the specific event occurrence. Structured format for the envoy access logs. Envoy [command operators](https://www.envoyproxy.io/docs/envoy/latest/configuration/observability/access_log/usage#command-operators) can be used as values for fields within the Struct. It's required when the format type is "JSON". | #### ProxyAccessLogFormatType -_Underlying type:_ `string` +_Underlying type:_ _string_ @@ -1462,10 +1778,10 @@ _Appears in:_ _Appears in:_ - [ProxyAccessLog](#proxyaccesslog) -| Field | Description | -| --- | --- | -| `format` _[ProxyAccessLogFormat](#proxyaccesslogformat)_ | Format defines the format of accesslog. | -| `sinks` _[ProxyAccessLogSink](#proxyaccesslogsink) array_ | Sinks defines the sinks of accesslog. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `format` | _[ProxyAccessLogFormat](#proxyaccesslogformat)_ | true | Format defines the format of accesslog. | +| `sinks` | _[ProxyAccessLogSink](#proxyaccesslogsink) array_ | true | Sinks defines the sinks of accesslog. | #### ProxyAccessLogSink @@ -1477,16 +1793,16 @@ ProxyAccessLogSink defines the sink of accesslog. _Appears in:_ - [ProxyAccessLogSetting](#proxyaccesslogsetting) -| Field | Description | -| --- | --- | -| `type` _[ProxyAccessLogSinkType](#proxyaccesslogsinktype)_ | Type defines the type of accesslog sink. | -| `file` _[FileEnvoyProxyAccessLog](#fileenvoyproxyaccesslog)_ | File defines the file accesslog sink. | -| `openTelemetry` _[OpenTelemetryEnvoyProxyAccessLog](#opentelemetryenvoyproxyaccesslog)_ | OpenTelemetry defines the OpenTelemetry accesslog sink. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | _[ProxyAccessLogSinkType](#proxyaccesslogsinktype)_ | true | Type defines the type of accesslog sink. | +| `file` | _[FileEnvoyProxyAccessLog](#fileenvoyproxyaccesslog)_ | false | File defines the file accesslog sink. | +| `openTelemetry` | _[OpenTelemetryEnvoyProxyAccessLog](#opentelemetryenvoyproxyaccesslog)_ | false | OpenTelemetry defines the OpenTelemetry accesslog sink. | #### ProxyAccessLogSinkType -_Underlying type:_ `string` +_Underlying type:_ _string_ @@ -1504,15 +1820,15 @@ ProxyBootstrap defines Envoy Bootstrap configuration. _Appears in:_ - [EnvoyProxySpec](#envoyproxyspec) -| Field | Description | -| --- | --- | -| `type` _[BootstrapType](#bootstraptype)_ | Type is the type of the bootstrap configuration, it should be either Replace or Merge. If unspecified, it defaults to Replace. | -| `value` _string_ | Value is a YAML string of the bootstrap. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | _[BootstrapType](#bootstraptype)_ | false | Type is the type of the bootstrap configuration, it should be either Replace or Merge. If unspecified, it defaults to Replace. | +| `value` | _string_ | true | Value is a YAML string of the bootstrap. | #### ProxyLogComponent -_Underlying type:_ `string` +_Underlying type:_ _string_ ProxyLogComponent defines a component that supports a configured logging level. @@ -1530,9 +1846,9 @@ ProxyLogging defines logging parameters for managed proxies. _Appears in:_ - [EnvoyProxySpec](#envoyproxyspec) -| Field | Description | -| --- | --- | -| `level` _object (keys:[ProxyLogComponent](#proxylogcomponent), values:[LogLevel](#loglevel))_ | Level is a map of logging level per component, where the component is the key and the log level is the value. If unspecified, defaults to "default: warn". | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `level` | _object (keys:[ProxyLogComponent](#proxylogcomponent), values:[LogLevel](#loglevel))_ | true | Level is a map of logging level per component, where the component is the key and the log level is the value. If unspecified, defaults to "default: warn". | #### ProxyMetricSink @@ -1544,10 +1860,10 @@ ProxyMetricSink defines the sink of metrics. Default metrics sink is OpenTelemet _Appears in:_ - [ProxyMetrics](#proxymetrics) -| Field | Description | -| --- | --- | -| `type` _[MetricSinkType](#metricsinktype)_ | Type defines the metric sink type. EG currently only supports OpenTelemetry. | -| `openTelemetry` _[ProxyOpenTelemetrySink](#proxyopentelemetrysink)_ | OpenTelemetry defines the configuration for OpenTelemetry sink. It's required if the sink type is OpenTelemetry. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | _[MetricSinkType](#metricsinktype)_ | true | Type defines the metric sink type. EG currently only supports OpenTelemetry. | +| `openTelemetry` | _[ProxyOpenTelemetrySink](#proxyopentelemetrysink)_ | false | OpenTelemetry defines the configuration for OpenTelemetry sink. It's required if the sink type is OpenTelemetry. | #### ProxyMetrics @@ -1559,12 +1875,12 @@ _Appears in:_ _Appears in:_ - [ProxyTelemetry](#proxytelemetry) -| Field | Description | -| --- | --- | -| `prometheus` _[ProxyPrometheusProvider](#proxyprometheusprovider)_ | Prometheus defines the configuration for Admin endpoint `/stats/prometheus`. | -| `sinks` _[ProxyMetricSink](#proxymetricsink) array_ | Sinks defines the metric sinks where metrics are sent to. | -| `matches` _[StringMatch](#stringmatch) array_ | Matches defines configuration for selecting specific metrics instead of generating all metrics stats that are enabled by default. This helps reduce CPU and memory overhead in Envoy, but eliminating some stats may after critical functionality. Here are the stats that we strongly recommend not disabling: `cluster_manager.warming_clusters`, `cluster..membership_total`,`cluster..membership_healthy`, `cluster..membership_degraded`,reference https://github.com/envoyproxy/envoy/issues/9856, https://github.com/envoyproxy/envoy/issues/14610 | -| `enableVirtualHostStats` _boolean_ | EnableVirtualHostStats enables envoy stat metrics for virtual hosts. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `prometheus` | _[ProxyPrometheusProvider](#proxyprometheusprovider)_ | true | Prometheus defines the configuration for Admin endpoint `/stats/prometheus`. | +| `sinks` | _[ProxyMetricSink](#proxymetricsink) array_ | true | Sinks defines the metric sinks where metrics are sent to. | +| `matches` | _[StringMatch](#stringmatch) array_ | true | Matches defines configuration for selecting specific metrics instead of generating all metrics stats that are enabled by default. This helps reduce CPU and memory overhead in Envoy, but eliminating some stats may after critical functionality. Here are the stats that we strongly recommend not disabling: `cluster_manager.warming_clusters`, `cluster..membership_total`,`cluster..membership_healthy`, `cluster..membership_degraded`,reference https://github.com/envoyproxy/envoy/issues/9856, https://github.com/envoyproxy/envoy/issues/14610 | +| `enableVirtualHostStats` | _boolean_ | true | EnableVirtualHostStats enables envoy stat metrics for virtual hosts. | #### ProxyOpenTelemetrySink @@ -1576,10 +1892,10 @@ _Appears in:_ _Appears in:_ - [ProxyMetricSink](#proxymetricsink) -| Field | Description | -| --- | --- | -| `host` _string_ | Host define the service hostname. | -| `port` _integer_ | Port defines the port the service is exposed on. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `host` | _string_ | true | Host define the service hostname. | +| `port` | _integer_ | false | Port defines the port the service is exposed on. | #### ProxyPrometheusProvider @@ -1591,9 +1907,9 @@ _Appears in:_ _Appears in:_ - [ProxyMetrics](#proxymetrics) -| Field | Description | -| --- | --- | -| `disable` _boolean_ | Disable the Prometheus endpoint. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `disable` | _boolean_ | true | Disable the Prometheus endpoint. | #### ProxyProtocol @@ -1605,14 +1921,14 @@ ProxyProtocol defines the configuration related to the proxy protocol when commu _Appears in:_ - [BackendTrafficPolicySpec](#backendtrafficpolicyspec) -| Field | Description | -| --- | --- | -| `version` _[ProxyProtocolVersion](#proxyprotocolversion)_ | Version of ProxyProtol Valid ProxyProtocolVersion values are "V1" "V2" | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `version` | _[ProxyProtocolVersion](#proxyprotocolversion)_ | true | Version of ProxyProtol Valid ProxyProtocolVersion values are "V1" "V2" | #### ProxyProtocolVersion -_Underlying type:_ `string` +_Underlying type:_ _string_ ProxyProtocolVersion defines the version of the Proxy Protocol to use. @@ -1630,11 +1946,11 @@ _Appears in:_ _Appears in:_ - [EnvoyProxySpec](#envoyproxyspec) -| Field | Description | -| --- | --- | -| `accessLog` _[ProxyAccessLog](#proxyaccesslog)_ | AccessLogs defines accesslog parameters for managed proxies. If unspecified, will send default format to stdout. | -| `tracing` _[ProxyTracing](#proxytracing)_ | Tracing defines tracing configuration for managed proxies. If unspecified, will not send tracing data. | -| `metrics` _[ProxyMetrics](#proxymetrics)_ | Metrics defines metrics configuration for managed proxies. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `accessLog` | _[ProxyAccessLog](#proxyaccesslog)_ | false | AccessLogs defines accesslog parameters for managed proxies. If unspecified, will send default format to stdout. | +| `tracing` | _[ProxyTracing](#proxytracing)_ | false | Tracing defines tracing configuration for managed proxies. If unspecified, will not send tracing data. | +| `metrics` | _[ProxyMetrics](#proxymetrics)_ | true | Metrics defines metrics configuration for managed proxies. | #### ProxyTracing @@ -1646,11 +1962,11 @@ _Appears in:_ _Appears in:_ - [ProxyTelemetry](#proxytelemetry) -| Field | Description | -| --- | --- | -| `samplingRate` _integer_ | SamplingRate controls the rate at which traffic will be selected for tracing if no prior sampling decision has been made. Defaults to 100, valid values [0-100]. 100 indicates 100% sampling. | -| `customTags` _object (keys:string, values:[CustomTag](#customtag))_ | CustomTags defines the custom tags to add to each span. If provider is kubernetes, pod name and namespace are added by default. | -| `provider` _[TracingProvider](#tracingprovider)_ | Provider defines the tracing provider. Only OpenTelemetry is supported currently. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `samplingRate` | _integer_ | false | SamplingRate controls the rate at which traffic will be selected for tracing if no prior sampling decision has been made. Defaults to 100, valid values [0-100]. 100 indicates 100% sampling. | +| `customTags` | _object (keys:string, values:[CustomTag](#customtag))_ | true | CustomTags defines the custom tags to add to each span. If provider is kubernetes, pod name and namespace are added by default. | +| `provider` | _[TracingProvider](#tracingprovider)_ | true | Provider defines the tracing provider. Only OpenTelemetry is supported currently. | #### RateLimit @@ -1663,11 +1979,11 @@ _Appears in:_ - [EnvoyGateway](#envoygateway) - [EnvoyGatewaySpec](#envoygatewayspec) -| Field | Description | -| --- | --- | -| `backend` _[RateLimitDatabaseBackend](#ratelimitdatabasebackend)_ | Backend holds the configuration associated with the database backend used by the rate limit service to store state associated with global ratelimiting. | -| `timeout` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ | Timeout specifies the timeout period for the proxy to access the ratelimit server If not set, timeout is 20ms. | -| `failClosed` _boolean_ | FailClosed is a switch used to control the flow of traffic when the response from the ratelimit server cannot be obtained. If FailClosed is false, let the traffic pass, otherwise, don't let the traffic pass and return 500. If not set, FailClosed is False. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `backend` | _[RateLimitDatabaseBackend](#ratelimitdatabasebackend)_ | true | Backend holds the configuration associated with the database backend used by the rate limit service to store state associated with global ratelimiting. | +| `timeout` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ | false | Timeout specifies the timeout period for the proxy to access the ratelimit server If not set, timeout is 20ms. | +| `failClosed` | _boolean_ | true | FailClosed is a switch used to control the flow of traffic when the response from the ratelimit server cannot be obtained. If FailClosed is false, let the traffic pass, otherwise, don't let the traffic pass and return 500. If not set, FailClosed is False. | #### RateLimitDatabaseBackend @@ -1679,15 +1995,15 @@ RateLimitDatabaseBackend defines the configuration associated with the database _Appears in:_ - [RateLimit](#ratelimit) -| Field | Description | -| --- | --- | -| `type` _[RateLimitDatabaseBackendType](#ratelimitdatabasebackendtype)_ | Type is the type of database backend to use. Supported types are: * Redis: Connects to a Redis database. | -| `redis` _[RateLimitRedisSettings](#ratelimitredissettings)_ | Redis defines the settings needed to connect to a Redis database. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | _[RateLimitDatabaseBackendType](#ratelimitdatabasebackendtype)_ | true | Type is the type of database backend to use. Supported types are: * Redis: Connects to a Redis database. | +| `redis` | _[RateLimitRedisSettings](#ratelimitredissettings)_ | false | Redis defines the settings needed to connect to a Redis database. | #### RateLimitDatabaseBackendType -_Underlying type:_ `string` +_Underlying type:_ _string_ RateLimitDatabaseBackendType specifies the types of database backend to be used by the rate limit service. @@ -1705,10 +2021,10 @@ RateLimitRedisSettings defines the configuration for connecting to redis databas _Appears in:_ - [RateLimitDatabaseBackend](#ratelimitdatabasebackend) -| Field | Description | -| --- | --- | -| `url` _string_ | URL of the Redis Database. | -| `tls` _[RedisTLSSettings](#redistlssettings)_ | TLS defines TLS configuration for connecting to redis database. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `url` | _string_ | true | URL of the Redis Database. | +| `tls` | _[RedisTLSSettings](#redistlssettings)_ | false | TLS defines TLS configuration for connecting to redis database. | #### RateLimitRule @@ -1721,12 +2037,10 @@ _Appears in:_ - [GlobalRateLimit](#globalratelimit) - [LocalRateLimit](#localratelimit) -| Field | Description | -| --- | --- | -| `clientSelectors` _[RateLimitSelectCondition](#ratelimitselectcondition) array_ | ClientSelectors holds the list of select conditions to select specific clients using attributes from the traffic flow. All individual select conditions must hold True for this rule and its limit to be applied. - If no client selectors are specified, the rule applies to all traffic of the targeted Route. - If the policy targets a Gateway, the rule applies to each Route of the Gateway. Please note that each Route has its own rate limit counters. For example, if a Gateway has two Routes, and the policy has a rule with limit 10rps, each Route will have its own 10rps limit. | -| `limit` _[RateLimitValue](#ratelimitvalue)_ | Limit holds the rate limit values. This limit is applied for traffic flows when the selectors compute to True, causing the request to be counted towards the limit. The limit is enforced and the request is ratelimited, i.e. a response with 429 HTTP status code is sent back to the client when the selected requests have reached the limit. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `clientSelectors` | _[RateLimitSelectCondition](#ratelimitselectcondition) array_ | false | ClientSelectors holds the list of select conditions to select specific clients using attributes from the traffic flow. All individual select conditions must hold True for this rule and its limit to be applied.

If no client selectors are specified, the rule applies to all traffic of the targeted Route.

If the policy targets a Gateway, the rule applies to each Route of the Gateway. Please note that each Route has its own rate limit counters. For example, if a Gateway has two Routes, and the policy has a rule with limit 10rps, each Route will have its own 10rps limit. | +| `limit` | _[RateLimitValue](#ratelimitvalue)_ | true | Limit holds the rate limit values. This limit is applied for traffic flows when the selectors compute to True, causing the request to be counted towards the limit. The limit is enforced and the request is ratelimited, i.e. a response with 429 HTTP status code is sent back to the client when the selected requests have reached the limit. | #### RateLimitSelectCondition @@ -1738,10 +2052,10 @@ RateLimitSelectCondition specifies the attributes within the traffic flow that c _Appears in:_ - [RateLimitRule](#ratelimitrule) -| Field | Description | -| --- | --- | -| `headers` _[HeaderMatch](#headermatch) array_ | Headers is a list of request headers to match. Multiple header values are ANDed together, meaning, a request MUST match all the specified headers. At least one of headers or sourceCIDR condition must be specified. | -| `sourceCIDR` _[SourceMatch](#sourcematch)_ | SourceCIDR is the client IP Address range to match on. At least one of headers or sourceCIDR condition must be specified. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `headers` | _[HeaderMatch](#headermatch) array_ | false | Headers is a list of request headers to match. Multiple header values are ANDed together, meaning, a request MUST match all the specified headers. At least one of headers or sourceCIDR condition must be specified. | +| `sourceCIDR` | _[SourceMatch](#sourcematch)_ | false | SourceCIDR is the client IP Address range to match on. At least one of headers or sourceCIDR condition must be specified. | #### RateLimitSpec @@ -1753,16 +2067,16 @@ RateLimitSpec defines the desired state of RateLimitSpec. _Appears in:_ - [BackendTrafficPolicySpec](#backendtrafficpolicyspec) -| Field | Description | -| --- | --- | -| `type` _[RateLimitType](#ratelimittype)_ | Type decides the scope for the RateLimits. Valid RateLimitType values are "Global" or "Local". | -| `global` _[GlobalRateLimit](#globalratelimit)_ | Global defines global rate limit configuration. | -| `local` _[LocalRateLimit](#localratelimit)_ | Local defines local rate limit configuration. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | _[RateLimitType](#ratelimittype)_ | true | Type decides the scope for the RateLimits. Valid RateLimitType values are "Global" or "Local". | +| `global` | _[GlobalRateLimit](#globalratelimit)_ | false | Global defines global rate limit configuration. | +| `local` | _[LocalRateLimit](#localratelimit)_ | false | Local defines local rate limit configuration. | #### RateLimitType -_Underlying type:_ `string` +_Underlying type:_ _string_ RateLimitType specifies the types of RateLimiting. @@ -1773,7 +2087,7 @@ _Appears in:_ #### RateLimitUnit -_Underlying type:_ `string` +_Underlying type:_ _string_ RateLimitUnit specifies the intervals for setting rate limits. Valid RateLimitUnit values are "Second", "Minute", "Hour", and "Day". @@ -1791,10 +2105,10 @@ RateLimitValue defines the limits for rate limiting. _Appears in:_ - [RateLimitRule](#ratelimitrule) -| Field | Description | -| --- | --- | -| `requests` _integer_ | | -| `unit` _[RateLimitUnit](#ratelimitunit)_ | | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `requests` | _integer_ | true | | +| `unit` | _[RateLimitUnit](#ratelimitunit)_ | true | | #### RedisTLSSettings @@ -1806,9 +2120,9 @@ RedisTLSSettings defines the TLS configuration for connecting to redis database. _Appears in:_ - [RateLimitRedisSettings](#ratelimitredissettings) -| Field | Description | -| --- | --- | -| `certificateRef` _[SecretObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.SecretObjectReference)_ | CertificateRef defines the client certificate reference for TLS connections. Currently only a Kubernetes Secret of type TLS is supported. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `certificateRef` | _[SecretObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.SecretObjectReference)_ | false | CertificateRef defines the client certificate reference for TLS connections. Currently only a Kubernetes Secret of type TLS is supported. | #### RemoteJWKS @@ -1820,9 +2134,9 @@ RemoteJWKS defines how to fetch and cache JSON Web Key Sets (JWKS) from a remote _Appears in:_ - [JWTProvider](#jwtprovider) -| Field | Description | -| --- | --- | -| `uri` _string_ | URI is the HTTPS URI to fetch the JWKS. Envoy's system trust bundle is used to validate the server certificate. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `uri` | _string_ | true | URI is the HTTPS URI to fetch the JWKS. Envoy's system trust bundle is used to validate the server certificate. | #### RequestHeaderCustomTag @@ -1834,15 +2148,15 @@ RequestHeaderCustomTag adds value from request header to each span. _Appears in:_ - [CustomTag](#customtag) -| Field | Description | -| --- | --- | -| `name` _string_ | Name defines the name of the request header which to extract the value from. | -| `defaultValue` _string_ | DefaultValue defines the default value to use if the request header is not set. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `name` | _string_ | true | Name defines the name of the request header which to extract the value from. | +| `defaultValue` | _string_ | false | DefaultValue defines the default value to use if the request header is not set. | #### ResourceProviderType -_Underlying type:_ `string` +_Underlying type:_ _string_ ResourceProviderType defines the types of custom resource providers supported by Envoy Gateway. @@ -1851,6 +2165,37 @@ _Appears in:_ +#### Retry + + + +Retry defines the retry strategy to be applied. + +_Appears in:_ +- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `numRetries` | _integer_ | false | NumRetries is the number of retries to be attempted. Defaults to 2. | +| `retryOn` | _[RetryOn](#retryon)_ | false | RetryOn specifies the retry trigger condition.

If not specified, the default is to retry on connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes(503). | +| `perRetry` | _[PerRetryPolicy](#perretrypolicy)_ | false | PerRetry is the retry policy to be applied per retry attempt. | + + +#### RetryOn + + + + + +_Appears in:_ +- [Retry](#retry) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `triggers` | _[TriggerEnum](#triggerenum) array_ | false | Triggers specifies the retry trigger condition(Http/Grpc). | +| `httpStatusCodes` | _[HTTPStatus](#httpstatus) array_ | false | HttpStatusCodes specifies the http status codes to be retried. | + + #### SecurityPolicy @@ -1860,12 +2205,12 @@ SecurityPolicy allows the user to configure various security settings for a Gate _Appears in:_ - [SecurityPolicyList](#securitypolicylist) -| Field | Description | -| --- | --- | -| `apiVersion` _string_ | `gateway.envoyproxy.io/v1alpha1` -| `kind` _string_ | `SecurityPolicy` -| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | -| `spec` _[SecurityPolicySpec](#securitypolicyspec)_ | Spec defines the desired state of SecurityPolicy. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1` +| `kind` | _string_ | |`SecurityPolicy` +| `metadata` | _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#objectmeta-v1-meta)_ | true | Refer to Kubernetes API documentation for fields of `metadata`. | +| `spec` | _[SecurityPolicySpec](#securitypolicyspec)_ | true | Spec defines the desired state of SecurityPolicy. | #### SecurityPolicyList @@ -1876,12 +2221,12 @@ SecurityPolicyList contains a list of SecurityPolicy resources. -| Field | Description | -| --- | --- | -| `apiVersion` _string_ | `gateway.envoyproxy.io/v1alpha1` -| `kind` _string_ | `SecurityPolicyList` -| `metadata` _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#listmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | -| `items` _[SecurityPolicy](#securitypolicy) array_ | | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `apiVersion` | _string_ | |`gateway.envoyproxy.io/v1alpha1` +| `kind` | _string_ | |`SecurityPolicyList` +| `metadata` | _[ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#listmeta-v1-meta)_ | true | Refer to Kubernetes API documentation for fields of `metadata`. | +| `items` | _[SecurityPolicy](#securitypolicy) array_ | true | | #### SecurityPolicySpec @@ -1893,20 +2238,21 @@ SecurityPolicySpec defines the desired state of SecurityPolicy. _Appears in:_ - [SecurityPolicy](#securitypolicy) -| Field | Description | -| --- | --- | -| `targetRef` _[PolicyTargetReferenceWithSectionName](#policytargetreferencewithsectionname)_ | TargetRef is the name of the Gateway resource this policy is being attached to. This Policy and the TargetRef MUST be in the same namespace for this Policy to have effect and be applied to the Gateway. TargetRef | -| `cors` _[CORS](#cors)_ | CORS defines the configuration for Cross-Origin Resource Sharing (CORS). | -| `basicAuth` _[BasicAuth](#basicauth)_ | BasicAuth defines the configuration for the HTTP Basic Authentication. | -| `jwt` _[JWT](#jwt)_ | JWT defines the configuration for JSON Web Token (JWT) authentication. | -| `oidc` _[OIDC](#oidc)_ | OIDC defines the configuration for the OpenID Connect (OIDC) authentication. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `targetRef` | _[PolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.PolicyTargetReferenceWithSectionName)_ | true | TargetRef is the name of the Gateway resource this policy is being attached to. This Policy and the TargetRef MUST be in the same namespace for this Policy to have effect and be applied to the Gateway. | +| `cors` | _[CORS](#cors)_ | false | CORS defines the configuration for Cross-Origin Resource Sharing (CORS). | +| `basicAuth` | _[BasicAuth](#basicauth)_ | false | BasicAuth defines the configuration for the HTTP Basic Authentication. | +| `jwt` | _[JWT](#jwt)_ | false | JWT defines the configuration for JSON Web Token (JWT) authentication. | +| `oidc` | _[OIDC](#oidc)_ | false | OIDC defines the configuration for the OpenID Connect (OIDC) authentication. | +| `extAuth` | _[ExtAuth](#extauth)_ | false | ExtAuth defines the configuration for External Authorization. | #### ServiceExternalTrafficPolicy -_Underlying type:_ `string` +_Underlying type:_ _string_ ServiceExternalTrafficPolicy describes how nodes distribute service traffic they receive on one of the Service's "externally-facing" addresses (NodePorts, ExternalIPs, and LoadBalancer IPs. @@ -1917,7 +2263,7 @@ _Appears in:_ #### ServiceType -_Underlying type:_ `string` +_Underlying type:_ _string_ ServiceType string describes ingress methods for a service @@ -1935,19 +2281,21 @@ SlowStart defines the configuration related to the slow start load balancer poli _Appears in:_ - [LoadBalancer](#loadbalancer) -| Field | Description | -| --- | --- | -| `window` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ | Window defines the duration of the warm up period for newly added host. During slow start window, traffic sent to the newly added hosts will gradually increase. Currently only supports linear growth of traffic. For additional details, see https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto#config-cluster-v3-cluster-slowstartconfig | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `window` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ | true | Window defines the duration of the warm up period for newly added host. During slow start window, traffic sent to the newly added hosts will gradually increase. Currently only supports linear growth of traffic. For additional details, see https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto#config-cluster-v3-cluster-slowstartconfig | -#### SourceMatch +#### SourceMatchType + +_Underlying type:_ _string_ _Appears in:_ -- [RateLimitSelectCondition](#ratelimitselectcondition) +- [SourceMatch](#sourcematch) @@ -1960,15 +2308,15 @@ StringMatch defines how to match any strings. This is a general purpose match co _Appears in:_ - [ProxyMetrics](#proxymetrics) -| Field | Description | -| --- | --- | -| `type` _[StringMatchType](#stringmatchtype)_ | Type specifies how to match against a string. | -| `value` _string_ | Value specifies the string value that the match must have. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | _[StringMatchType](#stringmatchtype)_ | false | Type specifies how to match against a string. | +| `value` | _string_ | true | Value specifies the string value that the match must have. | #### StringMatchType -_Underlying type:_ `string` +_Underlying type:_ _string_ StringMatchType specifies the semantics of how a string value should be compared. Valid MatchType values are "Exact", "Prefix", "Suffix", "RegularExpression". @@ -1977,19 +2325,19 @@ _Appears in:_ -#### TCPHealthChecker +#### TCPActiveHealthChecker -TCPHealthChecker defines the settings of tcp health check. +TCPActiveHealthChecker defines the settings of tcp health check. _Appears in:_ -- [HealthCheck](#healthcheck) +- [ActiveHealthCheck](#activehealthcheck) -| Field | Description | -| --- | --- | -| `send` _[HealthCheckPayload](#healthcheckpayload)_ | Send defines the request payload. | -| `receive` _[HealthCheckPayload](#healthcheckpayload)_ | Receive defines the expected response payload. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `send` | _[ActiveHealthCheckPayload](#activehealthcheckpayload)_ | false | Send defines the request payload. | +| `receive` | _[ActiveHealthCheckPayload](#activehealthcheckpayload)_ | false | Receive defines the expected response payload. | #### TCPKeepalive @@ -2002,11 +2350,25 @@ _Appears in:_ - [BackendTrafficPolicySpec](#backendtrafficpolicyspec) - [ClientTrafficPolicySpec](#clienttrafficpolicyspec) -| Field | Description | -| --- | --- | -| `probes` _integer_ | The total number of unacknowledged probes to send before deciding the connection is dead. Defaults to 9. | -| `idleTime` _Duration_ | The duration a connection needs to be idle before keep-alive probes start being sent. The duration format is Defaults to `7200s`. | -| `interval` _Duration_ | The duration between keep-alive probes. Defaults to `75s`. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `probes` | _integer_ | false | The total number of unacknowledged probes to send before deciding the connection is dead. Defaults to 9. | +| `idleTime` | _[Duration](#duration)_ | false | The duration a connection needs to be idle before keep-alive probes start being sent. The duration format is Defaults to `7200s`. | +| `interval` | _[Duration](#duration)_ | false | The duration between keep-alive probes. Defaults to `75s`. | + + +#### TCPTimeout + + + + + +_Appears in:_ +- [Timeout](#timeout) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `connectTimeout` | _[Duration](#duration)_ | false | The timeout for network connection establishment, including TCP and TLS handshakes. Default: 10 seconds. | #### TLSSettings @@ -2018,19 +2380,20 @@ _Appears in:_ _Appears in:_ - [ClientTrafficPolicySpec](#clienttrafficpolicyspec) -| Field | Description | -| --- | --- | -| `minVersion` _[TLSVersion](#tlsversion)_ | Min specifies the minimal TLS protocol version to allow. The default is TLS 1.2 if this is not specified. | -| `maxVersion` _[TLSVersion](#tlsversion)_ | Max specifies the maximal TLS protocol version to allow The default is TLS 1.3 if this is not specified. | -| `ciphers` _string array_ | Ciphers specifies the set of cipher suites supported when negotiating TLS 1.0 - 1.2. This setting has no effect for TLS 1.3. In non-FIPS Envoy Proxy builds the default cipher list is: - [ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305] - [ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305] - ECDHE-ECDSA-AES256-GCM-SHA384 - ECDHE-RSA-AES256-GCM-SHA384 In builds using BoringSSL FIPS the default cipher list is: - ECDHE-ECDSA-AES128-GCM-SHA256 - ECDHE-RSA-AES128-GCM-SHA256 - ECDHE-ECDSA-AES256-GCM-SHA384 - ECDHE-RSA-AES256-GCM-SHA384 | -| `ecdhCurves` _string array_ | ECDHCurves specifies the set of supported ECDH curves. In non-FIPS Envoy Proxy builds the default curves are: - X25519 - P-256 In builds using BoringSSL FIPS the default curve is: - P-256 | -| `signatureAlgorithms` _string array_ | SignatureAlgorithms specifies which signature algorithms the listener should support. | -| `alpnProtocols` _[ALPNProtocol](#alpnprotocol) array_ | ALPNProtocols supplies the list of ALPN protocols that should be exposed by the listener. By default h2 and http/1.1 are enabled. Supported values are: - http/1.0 - http/1.1 - h2 | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `minVersion` | _[TLSVersion](#tlsversion)_ | false | Min specifies the minimal TLS protocol version to allow. The default is TLS 1.2 if this is not specified. | +| `maxVersion` | _[TLSVersion](#tlsversion)_ | false | Max specifies the maximal TLS protocol version to allow The default is TLS 1.3 if this is not specified. | +| `ciphers` | _string array_ | false | Ciphers specifies the set of cipher suites supported when negotiating TLS 1.0 - 1.2. This setting has no effect for TLS 1.3. In non-FIPS Envoy Proxy builds the default cipher list is: - [ECDHE-ECDSA-AES128-GCM-SHA256\|ECDHE-ECDSA-CHACHA20-POLY1305] - [ECDHE-RSA-AES128-GCM-SHA256\|ECDHE-RSA-CHACHA20-POLY1305] - ECDHE-ECDSA-AES256-GCM-SHA384 - ECDHE-RSA-AES256-GCM-SHA384 In builds using BoringSSL FIPS the default cipher list is: - ECDHE-ECDSA-AES128-GCM-SHA256 - ECDHE-RSA-AES128-GCM-SHA256 - ECDHE-ECDSA-AES256-GCM-SHA384 - ECDHE-RSA-AES256-GCM-SHA384 | +| `ecdhCurves` | _string array_ | false | ECDHCurves specifies the set of supported ECDH curves. In non-FIPS Envoy Proxy builds the default curves are: - X25519 - P-256 In builds using BoringSSL FIPS the default curve is: - P-256 | +| `signatureAlgorithms` | _string array_ | false | SignatureAlgorithms specifies which signature algorithms the listener should support. | +| `alpnProtocols` | _[ALPNProtocol](#alpnprotocol) array_ | false | ALPNProtocols supplies the list of ALPN protocols that should be exposed by the listener. By default h2 and http/1.1 are enabled. Supported values are: - http/1.0 - http/1.1 - h2 | +| `clientValidation` | _[ClientValidationContext](#clientvalidationcontext)_ | false | ClientValidation specifies the configuration to validate the client initiating the TLS connection to the Gateway listener. | #### TLSVersion -_Underlying type:_ `string` +_Underlying type:_ _string_ TLSVersion specifies the TLS version @@ -2039,6 +2402,21 @@ _Appears in:_ +#### Timeout + + + +Timeout defines configuration for timeouts related to connections. + +_Appears in:_ +- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `tcp` | _[TCPTimeout](#tcptimeout)_ | false | Timeout settings for TCP. | +| `http` | _[HTTPTimeout](#httptimeout)_ | false | Timeout settings for HTTP. | + + #### TracingProvider @@ -2048,16 +2426,16 @@ _Appears in:_ _Appears in:_ - [ProxyTracing](#proxytracing) -| Field | Description | -| --- | --- | -| `type` _[TracingProviderType](#tracingprovidertype)_ | Type defines the tracing provider type. EG currently only supports OpenTelemetry. | -| `host` _string_ | Host define the provider service hostname. | -| `port` _integer_ | Port defines the port the provider service is exposed on. | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | _[TracingProviderType](#tracingprovidertype)_ | true | Type defines the tracing provider type. EG currently only supports OpenTelemetry. | +| `host` | _string_ | true | Host define the provider service hostname. | +| `port` | _integer_ | false | Port defines the port the provider service is exposed on. | #### TracingProviderType -_Underlying type:_ `string` +_Underlying type:_ _string_ @@ -2066,9 +2444,20 @@ _Appears in:_ +#### TriggerEnum + +_Underlying type:_ _string_ + +TriggerEnum specifies the conditions that trigger retries. + +_Appears in:_ +- [RetryOn](#retryon) + + + #### XDSTranslatorHook -_Underlying type:_ `string` +_Underlying type:_ _string_ XDSTranslatorHook defines the types of hooks that an Envoy Gateway extension may support for the xds-translator @@ -2086,9 +2475,23 @@ XDSTranslatorHooks contains all the pre and post hooks for the xds-translator ru _Appears in:_ - [ExtensionHooks](#extensionhooks) -| Field | Description | -| --- | --- | -| `pre` _[XDSTranslatorHook](#xdstranslatorhook) array_ | | -| `post` _[XDSTranslatorHook](#xdstranslatorhook) array_ | | +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `pre` | _[XDSTranslatorHook](#xdstranslatorhook) array_ | true | | +| `post` | _[XDSTranslatorHook](#xdstranslatorhook) array_ | true | | + + +#### XForwardedForSettings + + + +XForwardedForSettings provides configuration for using X-Forwarded-For headers for determining the client IP address. + +_Appears in:_ +- [ClientIPDetectionSettings](#clientipdetectionsettings) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `numTrustedHops` | _integer_ | false | NumTrustedHops controls the number of additional ingress proxy hops from the right side of XFF HTTP headers to trust when determining the origin client's IP address. Refer to https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers#x-forwarded-for for more details. | diff --git a/site/content/en/latest/install/api.md b/site/content/en/latest/install/api.md index c293a42ab68..e007fdba69c 100644 --- a/site/content/en/latest/install/api.md +++ b/site/content/en/latest/install/api.md @@ -25,6 +25,7 @@ The Helm chart for Envoy Gateway | Key | Type | Default | Description | |-----|------|---------|-------------| | certgen.job.annotations | object | `{}` | | +| certgen.job.resources | object | `{}` | | | certgen.job.ttlSecondsAfterFinished | int | `0` | | | certgen.rbac.annotations | object | `{}` | | | certgen.rbac.labels | object | `{}` | | diff --git a/site/content/en/latest/user/client-traffic-policy.md b/site/content/en/latest/user/client-traffic-policy.md index 9d89a0eb816..b155eaf4869 100644 --- a/site/content/en/latest/user/client-traffic-policy.md +++ b/site/content/en/latest/user/client-traffic-policy.md @@ -285,5 +285,130 @@ You should now expect 200 response status and also see that source IP was preser } ``` +### Configure Client IP Detection + +This example configures the number of additional ingress proxy hops from the right side of XFF HTTP headers to trust when determining the origin client's IP address and determines whether or not `x-forwarded-proto` headers will be trusted. Refer to https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers#x-forwarded-for for details. + +```shell +cat < GET /get HTTP/1.1 +> Host: www.example.com +> User-Agent: curl/8.4.0 +> Accept: */* +> X-Forwarded-Proto: https +> X-Forwarded-For: 1.1.1.1,2.2.2.2 +> +Handling connection for 8888 +< HTTP/1.1 200 OK +< content-type: application/json +< x-content-type-options: nosniff +< date: Tue, 30 Jan 2024 15:19:22 GMT +< content-length: 535 +< x-envoy-upstream-service-time: 0 +< server: envoy +< +{ + "path": "/get", + "host": "www.example.com", + "method": "GET", + "proto": "HTTP/1.1", + "headers": { + "Accept": [ + "*/*" + ], + "User-Agent": [ + "curl/8.4.0" + ], + "X-Envoy-Expected-Rq-Timeout-Ms": [ + "15000" + ], + "X-Envoy-External-Address": [ + "1.1.1.1" + ], + "X-Forwarded-For": [ + "1.1.1.1,2.2.2.2,10.244.0.9" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-Request-Id": [ + "53ccfad7-1899-40fa-9322-ddb833aa1ac3" + ] + }, + "namespace": "default", + "ingress": "", + "service": "", + "pod": "backend-58d58f745-8psnc" +* Connection #0 to host localhost left intact +} +``` + [ClientTrafficPolicy]: ../../api/extension_types#clienttrafficpolicy [BackendTrafficPolicy]: ../../api/extension_types#backendtrafficpolicy diff --git a/site/content/en/latest/user/cors.md b/site/content/en/latest/user/cors.md index 5f24c626d9b..886d795a66a 100644 --- a/site/content/en/latest/user/cors.md +++ b/site/content/en/latest/user/cors.md @@ -16,7 +16,11 @@ Before proceeding, you should be able to query the example backend using HTTP. ## Configuration -The below example defines a SecurityPolicy that allows CORS requests from `www.foo.com`. +When configuring CORS either an origin with a precise hostname can be configured or an hostname containing a wildcard prefix, +allowing all subdomains of the specified hostname. +In addition to that the entire origin (with or without specifying a scheme) can be a wildcard to allow all origins. + +The below example defines a SecurityPolicy that allows CORS for all HTTP requests originating from `www.foo.com`. ```shell cat < /dev/null ``` -Note: CORS specification requires that the browsers to send a preflight request to the server to ask if it's allowed +Note: +* CORS specification requires that the browsers to send a preflight request to the server to ask if it's allowed to access the limited resource in another domains. The browsers are supposed to follow the response from the server to determine whether to send the actual request or not. The CORS filter only response to the preflight requests according to its configuration. It won't deny any requests. The browsers are responsible for enforcing the CORS policy. +* The targeted HTTPRoute or the HTTPRoutes that the targeted Gateway routes to must allow the OPTIONS method for the CORS +filter to work. Otherwise, the OPTIONS request won't match the routes and the CORS filter won't be invoked. ## Clean-Up diff --git a/site/content/en/latest/user/customize-envoyproxy.md b/site/content/en/latest/user/customize-envoyproxy.md index 6565d08b0dc..3bc0c0c96d6 100644 --- a/site/content/en/latest/user/customize-envoyproxy.md +++ b/site/content/en/latest/user/customize-envoyproxy.md @@ -349,6 +349,24 @@ EOF After applying the config, the EnvoyProxy HPA (Horizontal Pod Autoscaler) is generated. However, upon activating the EnvoyProxy's HPA, the Envoy Gateway will no longer reference the `replicas` field specified in the `envoyDeployment`, as outlined [here](#customize-envoyproxy-deployment-replicas). +## Customize EnvoyProxy Command line options + +You can customize the EnvoyProxy Command line options via `spec.extraArgs` in EnvoyProxy Config. +For example, the following configuration will add `--disable-extensions` arg in order to disable `envoy.access_loggers/envoy.access_loggers.wasm` extension: + +```shell +cat < GET /get HTTP/1.1 @@ -203,8 +208,13 @@ Handling connection for 8888 * Lets deploy Envoy Gateway in the `product` namespace and also watch resources only in this namespace. -``` -helm install --set config.envoyGateway.gateway.controllerName=gateway.envoyproxy.io/product-gatewayclass-controller --set config.envoyGateway.provider.kubernetes.watch.namespaces={product} eg-product oci://docker.io/envoyproxy/gateway-helm --version v0.0.0-latest -n product --create-namespace +```shell +helm install \ +--set config.envoyGateway.gateway.controllerName=gateway.envoyproxy.io/product-gatewayclass-controller \ +--set config.envoyGateway.provider.kubernetes.watch.type=Namespaces \ +--set config.envoyGateway.provider.kubernetes.watch.namespaces={product} \ +eg-product oci://docker.io/envoyproxy/gateway-helm \ +--version v0.0.0-latest -n product --create-namespace ``` Lets create a `GatewayClass` linked to the product team's Envoy Gateway controller, and as well other resources linked to it, so the `backend` application operated by this team can be exposed to external clients. @@ -381,7 +391,7 @@ and the product team's data plane. curl --verbose --header "Host: www.marketing.example.com" http://localhost:8889/get ``` -``` +```console * Trying 127.0.0.1:8889... * Connected to localhost (127.0.0.1) port 8889 (#0) > GET /get HTTP/1.1 @@ -400,5 +410,6 @@ Handling connection for 8889 ``` [GatewayClass]: https://gateway-api.sigs.k8s.io/api-types/gatewayclass/ +[Namespaced deployment mode]: ../../api/extension_types#kuberneteswatchmode [issue1231]: https://github.com/envoyproxy/gateway/issues/1231 [issue1117]: https://github.com/envoyproxy/gateway/issues/1117 diff --git a/site/content/en/latest/user/egctl.md b/site/content/en/latest/user/egctl.md index 739a137d131..3c612274046 100644 --- a/site/content/en/latest/user/egctl.md +++ b/site/content/en/latest/user/egctl.md @@ -741,4 +741,87 @@ xds: '@type': type.googleapis.com/envoy.admin.v3.RoutesConfigDump ``` +## egctl experimental status + +This subcommand allows users to show the summary of the status of specific or all resource types, in order to quickly find +out the status of any resources. + +By default, `egctl x status` display all the conditions for one resource type. You can either add `--quiet` to only +display the latest condition, or add `--verbose` to display more details about current status. + +{{% alert title="Note" color="primary" %}} + +Currently, this subcommand only supports: `GatewayClass`, `Gateway`, `HTTPRoute`, `GRPCRoute`, +`TLSRoute`, `TCPRoute`, `UDPRoute`, `BackendTLSPolicy`, +`BackendTrafficPolicy`, `ClientTrafficPolicy`, `EnvoyPatchPolicy`, `SecurityPolicy` resource types and `all`. + +{{% /alert %}} + +Some examples of this command after installing [Multi-tenancy][] example manifest: + +- Show the summary of GatewayClass. + +```console +~ egctl x status gatewayclass + +NAME TYPE STATUS REASON +eg-marketing Accepted True Accepted +eg-product Accepted True Accepted +``` + +- Show the summary of all resource types under all namespaces, the resource type with empty status will be ignored. + +```console +~ egctl x status all -A + +NAME TYPE STATUS REASON +gatewayclass/eg-marketing Accepted True Accepted +gatewayclass/eg-product Accepted True Accepted + +NAMESPACE NAME TYPE STATUS REASON +marketing gateway/eg Programmed True Programmed + Accepted True Accepted +product gateway/eg Programmed True Programmed + Accepted True Accepted + +NAMESPACE NAME TYPE STATUS REASON +marketing httproute/backend ResolvedRefs True ResolvedRefs + Accepted True Accepted +product httproute/backend ResolvedRefs True ResolvedRefs + Accepted True Accepted +``` + +- Show the summary of all the Gateways with details under all namespaces. + +```console +~ egctl x status gateway --verbose --all-namespaces + +NAMESPACE NAME TYPE STATUS REASON MESSAGE OBSERVED GENERATION LAST TRANSITION TIME +marketing eg Programmed True Programmed Address assigned to the Gateway, 1/1 envoy Deployment replicas available 1 2024-02-02 18:17:14 +0800 CST + Accepted True Accepted The Gateway has been scheduled by Envoy Gateway 1 2024-02-01 17:50:39 +0800 CST +product eg Programmed True Programmed Address assigned to the Gateway, 1/1 envoy Deployment replicas available 1 2024-02-02 18:17:14 +0800 CST + Accepted True Accepted The Gateway has been scheduled by Envoy Gateway 1 2024-02-01 17:52:42 +0800 CST +``` + +- Show the summary of latest Gateways condition under `product` namespace. + +```console +~ egctl x status gateway --quiet -n product + +NAME TYPE STATUS REASON +eg Programmed True Programmed +``` + +- Show the summary of latest HTTPRoutes condition under all namespaces. + +```console +~ egctl x status httproute --quiet --all-namespaces + +NAMESPACE NAME TYPE STATUS REASON +marketing backend ResolvedRefs True ResolvedRefs +product backend ResolvedRefs True ResolvedRefs +``` + + +[Multi-tenancy]: ../deployment-mode#multi-tenancy [EnvoyProxy]: ../../api/extension_types#envoyproxy diff --git a/site/content/en/latest/user/gateway-address.md b/site/content/en/latest/user/gateway-address.md index 95aeb3aa4a3..b87b19ec805 100644 --- a/site/content/en/latest/user/gateway-address.md +++ b/site/content/en/latest/user/gateway-address.md @@ -2,35 +2,23 @@ title: "Gateway Address" --- -The Gateway API provides an optional [Addresses][] field through which Envoy Gateway can set addresses for Envoy Proxy Service. The currently supported addresses are: +The Gateway API provides an optional [Addresses][] field through which Envoy Gateway can set addresses for Envoy Proxy Service. +Depending on the Service Type, the addresses of gateway can be used as: -- [External IPs](#External-IPs) +- [External IPs](#external-ips) +- [Cluster IP](#cluster-ip) -## Installation +## Prerequisites -Install Envoy Gateway: - -```shell -helm install eg oci://docker.io/envoyproxy/gateway-helm --version v0.0.0-latest -n envoy-gateway-system --create-namespace -``` - -Wait for Envoy Gateway to become available: - -```shell -kubectl wait --timeout=5m -n envoy-gateway-system deployment/envoy-gateway --for=condition=Available -``` +Follow the steps from the [Quickstart](../quickstart) to install Envoy Gateway and the example manifest. ## External IPs -Using the addresses in `Gateway.Spec.Addresses` as the [External IPs][] of Envoy Proxy Service, this will __require__ the address to be of type `IPAddress`. +Using the addresses in `Gateway.Spec.Addresses` as the [External IPs][] of Envoy Proxy Service, +this will __require__ the address to be of type `IPAddress` and the [ServiceType][] to be of `LoadBalancer` or `NodePort`. -Install the GatewayClass, Gateway from quickstart: - -```shell -kubectl apply -f https://github.com/envoyproxy/gateway/releases/download/latest/quickstart.yaml -n default -``` - -Set the address of the Gateway, the address settings here are for reference only: +The Envoy Gateway deploys Envoy Proxy Service as `LoadBalancer` by default, +so you can set the address of the Gateway directly (the address settings here are for reference only): ```shell kubectl patch gateway eg --type=json --patch '[{ @@ -65,5 +53,13 @@ envoy-gateway-metrics-service ClusterIP 10.96.124.73 844 __Note:__ If the `Gateway.Spec.Addresses` is explicitly set, it will be the only addresses that populates the Gateway status. +## Cluster IP + +Using the addresses in `Gateway.Spec.Addresses` as the [Cluster IP][] of Envoy Proxy Service, +this will __require__ the address to be of type `IPAddress` and the [ServiceType][] to be of `ClusterIP`. + + [Addresses]: https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.GatewayAddress [External IPs]: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips +[Cluster IP]: https://kubernetes.io/docs/concepts/services-networking/service/#type-clusterip +[ServiceType]: ../../api/extension_types#servicetype diff --git a/site/content/en/latest/user/oidc.md b/site/content/en/latest/user/oidc.md index 39928ed7fba..6d4deba8efd 100644 --- a/site/content/en/latest/user/oidc.md +++ b/site/content/en/latest/user/oidc.md @@ -3,12 +3,12 @@ title: "OIDC Authentication" --- This guide provides instructions for configuring [OpenID Connect (OIDC)][oidc] authentication. -OpenID Connect (OIDC) is an authentication standard built on top of OAuth 2.0. -It enables client applications to rely on authentication that is performed by an OpenID Connect Provider (OP) +OpenID Connect (OIDC) is an authentication standard built on top of OAuth 2.0. +It enables client applications to rely on authentication that is performed by an OpenID Connect Provider (OP) to verify the identity of a user. -Envoy Gateway introduces a new CRD called [SecurityPolicy][SecurityPolicy] that allows the user to configure OIDC -authentication. +Envoy Gateway introduces a new CRD called [SecurityPolicy][SecurityPolicy] that allows the user to configure OIDC +authentication. This instantiated resource can be linked to a [Gateway][Gateway] and [HTTPRoute][HTTPRoute] resource. ## Prerequisites @@ -17,7 +17,7 @@ Follow the steps from the [Quickstart](../quickstart) guide to install Envoy Gat Before proceeding, you should be able to query the example backend using HTTP. OIDC authentication requires the redirect URL to be HTTPS. Follow the [Secure Gateways](../secure-gateways) guide - to generate the TLS certificates and update the Gateway configuration to add an HTTPS listener. +to generate the TLS certificates and update the Gateway configuration to add an HTTPS listener. Verify the Gateway status: @@ -34,7 +34,11 @@ providers, including Auth0, Azure AD, Keycloak, Okta, OneLogin, Salesforce, UAA, Follow the steps in the [Google OIDC documentation][google-oidc] to register an OIDC application. Please make sure the redirect URL is set to the one you configured in the SecurityPolicy that you will create in the step below. If you don't -specify a redirect URL in the SecurityPolicy, the default redirect URL is `https:///oauth2/callback`. +specify a redirect URL in the SecurityPolicy, the default redirect URL is `https://${GATEWAY_HOST}/oauth2/callback`. +Please notice that the `redirectURL` and `logoutPath` must be caught by the target HTTPRoute. For example, if the +HTTPRoute is configured to match the host `www.example.com` and the path `/foo`, the `redirectURL` must +be prefixed with `https://www.example.com/foo`, and `logoutPath` must be prefixed with`/foo`, for example, +`https://www.example.com/foo/oauth2/callback` and `/foo/logout`, otherwise the OIDC authentication will fail. After registering the application, you should have the following information: * Client ID: The client ID of the OIDC application. @@ -73,6 +77,8 @@ spec: clientID: "${CLIENT_ID}.apps.googleusercontent.com" clientSecret: name: "my-app-client-secret" + redirectURI: "https://www.example.com/oauth2/callback" + logoutPath: "/logout" EOF ``` @@ -92,7 +98,7 @@ export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gatewa sudo kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 443:443 ``` -Put www.exampe.com in the /etc/hosts file in your test machine, so we can use this host name to access the demo from a browser: +Put www.example.com in the /etc/hosts file in your test machine, so we can use this host name to access the demo from a browser: ```shell ... diff --git a/test/cel-validation/backendtrafficpolicy_test.go b/test/cel-validation/backendtrafficpolicy_test.go index ba7d077107e..947b88b970c 100644 --- a/test/cel-validation/backendtrafficpolicy_test.go +++ b/test/cel-validation/backendtrafficpolicy_test.go @@ -18,6 +18,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/pointer" "k8s.io/utils/ptr" + + gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" @@ -467,13 +469,15 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, CircuitBreaker: &egv1a1.CircuitBreaker{ - MaxConnections: valOverMax, - MaxPendingRequests: valUnderMin, - MaxParallelRequests: valOverMax, + MaxConnections: valOverMax, + MaxPendingRequests: valUnderMin, + MaxParallelRequests: valOverMax, + MaxRequestsPerConnection: valUnderMin, }, } }, wantErrors: []string{ + "spec.circuitBreaker.maxRequestsPerConnection: Invalid value: -1: spec.circuitBreaker.maxRequestsPerConnection in body should be greater than or equal to 0", "spec.circuitBreaker.maxParallelRequests: Invalid value: 4294967296: spec.circuitBreaker.maxParallelRequests in body should be less than or equal to 4294967295", "spec.circuitBreaker.maxPendingRequests: Invalid value: -1: spec.circuitBreaker.maxPendingRequests in body should be greater than or equal to 0", "spec.circuitBreaker.maxConnections: Invalid value: 4294967296: spec.circuitBreaker.maxConnections in body should be less than or equal to 4294967295", @@ -491,15 +495,17 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, HealthCheck: &egv1a1.HealthCheck{ - Type: egv1a1.HealthCheckerTypeHTTP, - HTTP: &egv1a1.HTTPHealthChecker{ - Path: "", + Active: &egv1a1.ActiveHealthCheck{ + Type: egv1a1.ActiveHealthCheckerTypeHTTP, + HTTP: &egv1a1.HTTPActiveHealthChecker{ + Path: "", + }, }, }, } }, wantErrors: []string{ - `spec.healthCheck.http.path: Invalid value: "": spec.healthCheck.http.path in body should be at least 1 chars long`, + `spec.HealthCheck.active.http.path: Invalid value: "": spec.HealthCheck.active.http.path in body should be at least 1 chars long`, }, }, { @@ -514,16 +520,18 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, HealthCheck: &egv1a1.HealthCheck{ - UnhealthyThreshold: ptr.To[uint32](0), - Type: egv1a1.HealthCheckerTypeHTTP, - HTTP: &egv1a1.HTTPHealthChecker{ - Path: "/healthz", + Active: &egv1a1.ActiveHealthCheck{ + UnhealthyThreshold: ptr.To[uint32](0), + Type: egv1a1.ActiveHealthCheckerTypeHTTP, + HTTP: &egv1a1.HTTPActiveHealthChecker{ + Path: "/healthz", + }, }, }, } }, wantErrors: []string{ - `spec.healthCheck.unhealthyThreshold: Invalid value: 0: spec.healthCheck.unhealthyThreshold in body should be greater than or equal to 1`, + `spec.HealthCheck.active.unhealthyThreshold: Invalid value: 0: spec.HealthCheck.active.unhealthyThreshold in body should be greater than or equal to 1`, }, }, { @@ -538,16 +546,18 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, HealthCheck: &egv1a1.HealthCheck{ - HealthyThreshold: ptr.To[uint32](0), - Type: egv1a1.HealthCheckerTypeHTTP, - HTTP: &egv1a1.HTTPHealthChecker{ - Path: "/healthz", + Active: &egv1a1.ActiveHealthCheck{ + HealthyThreshold: ptr.To[uint32](0), + Type: egv1a1.ActiveHealthCheckerTypeHTTP, + HTTP: &egv1a1.HTTPActiveHealthChecker{ + Path: "/healthz", + }, }, }, } }, wantErrors: []string{ - `spec.healthCheck.healthyThreshold: Invalid value: 0: spec.healthCheck.healthyThreshold in body should be greater than or equal to 1`, + `spec.HealthCheck.active.healthyThreshold: Invalid value: 0: spec.HealthCheck.active.healthyThreshold in body should be greater than or equal to 1`, }, }, { @@ -562,13 +572,15 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, HealthCheck: &egv1a1.HealthCheck{ - Type: egv1a1.HealthCheckerTypeHTTP, - TCP: &egv1a1.TCPHealthChecker{}, + Active: &egv1a1.ActiveHealthCheck{ + Type: egv1a1.ActiveHealthCheckerTypeHTTP, + TCP: &egv1a1.TCPActiveHealthChecker{}, + }, }, } }, wantErrors: []string{ - `spec.healthCheck: Invalid value: "object": If Health Checker type is HTTP, http field needs to be set., spec.healthCheck: Invalid value: "object": If Health Checker type is TCP, tcp field needs to be set`, + `spec.HealthCheck.active: Invalid value: "object": If Health Checker type is HTTP, http field needs to be set., spec.HealthCheck.active: Invalid value: "object": If Health Checker type is TCP, tcp field needs to be set`, }, }, { @@ -583,16 +595,18 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, HealthCheck: &egv1a1.HealthCheck{ - Type: egv1a1.HealthCheckerTypeHTTP, - HTTP: &egv1a1.HTTPHealthChecker{ - Path: "/healthz", - ExpectedStatuses: []egv1a1.HTTPStatus{99, 200}, + Active: &egv1a1.ActiveHealthCheck{ + Type: egv1a1.ActiveHealthCheckerTypeHTTP, + HTTP: &egv1a1.HTTPActiveHealthChecker{ + Path: "/healthz", + ExpectedStatuses: []egv1a1.HTTPStatus{99, 200}, + }, }, }, } }, wantErrors: []string{ - `spec.healthCheck.http.expectedStatuses[0]: Invalid value: 99: spec.healthCheck.http.expectedStatuses[0] in body should be greater than or equal to 100`, + `spec.HealthCheck.active.http.expectedStatuses[0]: Invalid value: 99: spec.HealthCheck.active.http.expectedStatuses[0] in body should be greater than or equal to 100`, }, }, { @@ -607,10 +621,12 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, HealthCheck: &egv1a1.HealthCheck{ - Type: egv1a1.HealthCheckerTypeHTTP, - HTTP: &egv1a1.HTTPHealthChecker{ - Path: "/healthz", - ExpectedStatuses: []egv1a1.HTTPStatus{100, 200, 201}, + Active: &egv1a1.ActiveHealthCheck{ + Type: egv1a1.ActiveHealthCheckerTypeHTTP, + HTTP: &egv1a1.HTTPActiveHealthChecker{ + Path: "/healthz", + ExpectedStatuses: []egv1a1.HTTPStatus{100, 200, 201}, + }, }, }, } @@ -629,16 +645,18 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, HealthCheck: &egv1a1.HealthCheck{ - Type: egv1a1.HealthCheckerTypeHTTP, - HTTP: &egv1a1.HTTPHealthChecker{ - Path: "/healthz", - ExpectedStatuses: []egv1a1.HTTPStatus{200, 300, 601}, + Active: &egv1a1.ActiveHealthCheck{ + Type: egv1a1.ActiveHealthCheckerTypeHTTP, + HTTP: &egv1a1.HTTPActiveHealthChecker{ + Path: "/healthz", + ExpectedStatuses: []egv1a1.HTTPStatus{200, 300, 601}, + }, }, }, } }, wantErrors: []string{ - `spec.healthCheck.http.expectedStatuses[2]: Invalid value: 601: spec.healthCheck.http.expectedStatuses[2] in body should be less than 600`, + `spec.HealthCheck.active.http.expectedStatuses[2]: Invalid value: 601: spec.HealthCheck.active.http.expectedStatuses[2] in body should be less than 600`, }, }, { @@ -653,19 +671,21 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, HealthCheck: &egv1a1.HealthCheck{ - Type: egv1a1.HealthCheckerTypeHTTP, - HTTP: &egv1a1.HTTPHealthChecker{ - Path: "/healthz", - ExpectedResponse: &egv1a1.HealthCheckPayload{ - Type: egv1a1.HealthCheckPayloadTypeText, - Binary: []byte{'f', 'o', 'o'}, + Active: &egv1a1.ActiveHealthCheck{ + Type: egv1a1.ActiveHealthCheckerTypeHTTP, + HTTP: &egv1a1.HTTPActiveHealthChecker{ + Path: "/healthz", + ExpectedResponse: &egv1a1.ActiveHealthCheckPayload{ + Type: egv1a1.ActiveHealthCheckPayloadTypeText, + Binary: []byte{'f', 'o', 'o'}, + }, }, }, }, } }, wantErrors: []string{ - `[spec.healthCheck.http.expectedResponse: Invalid value: "object": If payload type is Text, text field needs to be set., spec.healthCheck.http.expectedResponse: Invalid value: "object": If payload type is Binary, binary field needs to be set.]`, + `[spec.HealthCheck.active.http.expectedResponse: Invalid value: "object": If payload type is Text, text field needs to be set., spec.HealthCheck.active.http.expectedResponse: Invalid value: "object": If payload type is Binary, binary field needs to be set.]`, }, }, { @@ -680,19 +700,21 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, HealthCheck: &egv1a1.HealthCheck{ - Type: egv1a1.HealthCheckerTypeHTTP, - HTTP: &egv1a1.HTTPHealthChecker{ - Path: "/healthz", - ExpectedResponse: &egv1a1.HealthCheckPayload{ - Type: egv1a1.HealthCheckPayloadTypeBinary, - Text: ptr.To("foo"), + Active: &egv1a1.ActiveHealthCheck{ + Type: egv1a1.ActiveHealthCheckerTypeHTTP, + HTTP: &egv1a1.HTTPActiveHealthChecker{ + Path: "/healthz", + ExpectedResponse: &egv1a1.ActiveHealthCheckPayload{ + Type: egv1a1.ActiveHealthCheckPayloadTypeBinary, + Text: ptr.To("foo"), + }, }, }, }, } }, wantErrors: []string{ - `[spec.healthCheck.http.expectedResponse: Invalid value: "object": If payload type is Text, text field needs to be set., spec.healthCheck.http.expectedResponse: Invalid value: "object": If payload type is Binary, binary field needs to be set.]`, + `[spec.HealthCheck.active.http.expectedResponse: Invalid value: "object": If payload type is Text, text field needs to be set., spec.HealthCheck.active.http.expectedResponse: Invalid value: "object": If payload type is Binary, binary field needs to be set.]`, }, }, { @@ -707,22 +729,24 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, HealthCheck: &egv1a1.HealthCheck{ - Type: egv1a1.HealthCheckerTypeTCP, - TCP: &egv1a1.TCPHealthChecker{ - Send: &egv1a1.HealthCheckPayload{ - Type: egv1a1.HealthCheckPayloadTypeText, - Binary: []byte{'f', 'o', 'o'}, - }, - Receive: &egv1a1.HealthCheckPayload{ - Type: egv1a1.HealthCheckPayloadTypeText, - Text: ptr.To("foo"), + Active: &egv1a1.ActiveHealthCheck{ + Type: egv1a1.ActiveHealthCheckerTypeTCP, + TCP: &egv1a1.TCPActiveHealthChecker{ + Send: &egv1a1.ActiveHealthCheckPayload{ + Type: egv1a1.ActiveHealthCheckPayloadTypeText, + Binary: []byte{'f', 'o', 'o'}, + }, + Receive: &egv1a1.ActiveHealthCheckPayload{ + Type: egv1a1.ActiveHealthCheckPayloadTypeText, + Text: ptr.To("foo"), + }, }, }, }, } }, wantErrors: []string{ - `spec.healthCheck.tcp.send: Invalid value: "object": If payload type is Text, text field needs to be set., spec.healthCheck.tcp.send: Invalid value: "object": If payload type is Binary, binary field needs to be set.`, + `spec.HealthCheck.active.tcp.send: Invalid value: "object": If payload type is Text, text field needs to be set., spec.HealthCheck.active.tcp.send: Invalid value: "object": If payload type is Binary, binary field needs to be set.`, }, }, { @@ -737,24 +761,51 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, HealthCheck: &egv1a1.HealthCheck{ - Type: egv1a1.HealthCheckerTypeTCP, - TCP: &egv1a1.TCPHealthChecker{ - Send: &egv1a1.HealthCheckPayload{ - Type: egv1a1.HealthCheckPayloadTypeText, - Text: ptr.To("foo"), - }, - Receive: &egv1a1.HealthCheckPayload{ - Type: egv1a1.HealthCheckPayloadTypeText, - Binary: []byte{'f', 'o', 'o'}, + Active: &egv1a1.ActiveHealthCheck{ + Type: egv1a1.ActiveHealthCheckerTypeTCP, + TCP: &egv1a1.TCPActiveHealthChecker{ + Send: &egv1a1.ActiveHealthCheckPayload{ + Type: egv1a1.ActiveHealthCheckPayloadTypeText, + Text: ptr.To("foo"), + }, + Receive: &egv1a1.ActiveHealthCheckPayload{ + Type: egv1a1.ActiveHealthCheckPayloadTypeText, + Binary: []byte{'f', 'o', 'o'}, + }, }, }, }, } }, wantErrors: []string{ - `[spec.healthCheck.tcp.receive: Invalid value: "object": If payload type is Text, text field needs to be set., spec.healthCheck.tcp.receive: Invalid value: "object": If payload type is Binary, binary field needs to be set.]`, + `[spec.HealthCheck.active.tcp.receive: Invalid value: "object": If payload type is Text, text field needs to be set., spec.HealthCheck.active.tcp.receive: Invalid value: "object": If payload type is Binary, binary field needs to be set.]`, }, }, + { + desc: " valid timeout", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + d := gwapiv1.Duration("3s") + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + Timeout: &egv1a1.Timeout{ + TCP: &egv1a1.TCPTimeout{ + ConnectTimeout: &d, + }, + HTTP: &egv1a1.HTTPTimeout{ + ConnectionIdleTimeout: &d, + MaxConnectionDuration: &d, + }, + }, + } + }, + wantErrors: []string{}, + }, } for _, tc := range cases { diff --git a/test/cel-validation/clienttrafficpolicy_test.go b/test/cel-validation/clienttrafficpolicy_test.go index e1bcc39aab7..31f04da8f3b 100644 --- a/test/cel-validation/clienttrafficpolicy_test.go +++ b/test/cel-validation/clienttrafficpolicy_test.go @@ -15,12 +15,11 @@ import ( "testing" "time" + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" - + gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - - egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" ) func TestClientTrafficPolicyTarget(t *testing.T) { @@ -178,6 +177,31 @@ func TestClientTrafficPolicyTarget(t *testing.T) { "spec.tls: Invalid value: \"object\": minVersion must be smaller or equal to maxVersion", }, }, + { + desc: "clientIPDetection xForwardedFor and customHeader set", + mutate: func(ctp *egv1a1.ClientTrafficPolicy) { + ctp.Spec = egv1a1.ClientTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + ClientIPDetection: &egv1a1.ClientIPDetectionSettings{ + XForwardedFor: &egv1a1.XForwardedForSettings{ + NumTrustedHops: ptr.To(uint32(1)), + }, + CustomHeader: &egv1a1.CustomHeaderExtensionSettings{ + Name: "x-client-ip-address", + }, + }, + } + }, + wantErrors: []string{ + "spec.clientIPDetection: Invalid value: \"object\": customHeader cannot be used in conjunction with xForwardedFor", + }, + }, { desc: "http3 enabled and ALPN protocols set", mutate: func(ctp *egv1a1.ClientTrafficPolicy) { @@ -258,6 +282,27 @@ func TestClientTrafficPolicyTarget(t *testing.T) { "spec.tls: Invalid value: \"object\": setting ciphers has no effect if the minimum possible TLS version is 1.3", }, }, + { + desc: "valid timeout", + mutate: func(ctp *egv1a1.ClientTrafficPolicy) { + d := gwapiv1.Duration("300s") + ctp.Spec = egv1a1.ClientTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + Timeout: &egv1a1.ClientTimeout{ + HTTP: &egv1a1.HTTPClientTimeout{ + RequestReceivedTimeout: &d, + }, + }, + } + }, + wantErrors: []string{}, + }, } for _, tc := range cases { diff --git a/test/cel-validation/envoyproxy_test.go b/test/cel-validation/envoyproxy_test.go index 9f029534b12..cc414e314b6 100644 --- a/test/cel-validation/envoyproxy_test.go +++ b/test/cel-validation/envoyproxy_test.go @@ -152,6 +152,23 @@ func TestEnvoyProxyProvider(t *testing.T) { }, wantErrors: []string{}, }, + { + desc: "ServiceTypeLoadBalancer-with-invalid-IP", + mutate: func(envoy *egv1a1.EnvoyProxy) { + envoy.Spec = egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + EnvoyService: &egv1a1.KubernetesServiceSpec{ + Type: ptr.To(egv1a1.ServiceTypeLoadBalancer), + LoadBalancerIP: ptr.To("1.2.3.4."), + }, + }, + }, + } + }, + wantErrors: []string{"loadBalancerIP must be a valid IPv4 address"}, + }, { desc: "ServiceTypeLoadBalancer-with-invalid-IP", mutate: func(envoy *egv1a1.EnvoyProxy) { diff --git a/test/cel-validation/securitypolicy_test.go b/test/cel-validation/securitypolicy_test.go index 8f6937fc1ce..a6107e6531b 100644 --- a/test/cel-validation/securitypolicy_test.go +++ b/test/cel-validation/securitypolicy_test.go @@ -16,6 +16,8 @@ import ( "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" + gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" @@ -220,7 +222,67 @@ func TestSecurityPolicyTarget(t *testing.T) { wantErrors: []string{}, }, { - desc: "cors alloworigin invalid with wildcard in the middle", + desc: "cors alloworigin valid with scheme and wildcard", + mutate: func(sp *egv1a1.SecurityPolicy) { + sp.Spec = egv1a1.SecurityPolicySpec{ + CORS: &egv1a1.CORS{ + AllowOrigins: []egv1a1.Origin{ + "http://*", // valid + }, + }, + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + } + }, + wantErrors: []string{}, + }, + { + desc: "cors alloworigin valid with wildcard only", + mutate: func(sp *egv1a1.SecurityPolicy) { + sp.Spec = egv1a1.SecurityPolicySpec{ + CORS: &egv1a1.CORS{ + AllowOrigins: []egv1a1.Origin{ + "*", // valid + }, + }, + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + } + }, + wantErrors: []string{}, + }, + { + desc: "cors alloworigin valid with simple hostname without tld", + mutate: func(sp *egv1a1.SecurityPolicy) { + sp.Spec = egv1a1.SecurityPolicySpec{ + CORS: &egv1a1.CORS{ + AllowOrigins: []egv1a1.Origin{ + "http://localhost", // valid + }, + }, + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + } + }, + wantErrors: []string{}, + }, + { + desc: "cors alloworigin with wildcard in the middle", mutate: func(sp *egv1a1.SecurityPolicy) { sp.Spec = egv1a1.SecurityPolicySpec{ CORS: &egv1a1.CORS{ @@ -238,7 +300,7 @@ func TestSecurityPolicyTarget(t *testing.T) { } }, wantErrors: []string{ - "spec.cors.allowOrigins[0]: Invalid value: \"https://foo.*.com\": spec.cors.allowOrigins[0] in body should match '^https?:\\/\\/(\\*\\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*(:[0-9]+)?$'", + "spec.cors.allowOrigins[0]: Invalid value: \"https://foo.*.com\": spec.cors.allowOrigins[0] in body should match '^(\\*|https?:\\/\\/(\\*|(\\*\\.)?(([\\w-]+\\.?)+)?[\\w-]+)(:\\d{1,5})?)$'", }, }, { @@ -260,7 +322,7 @@ func TestSecurityPolicyTarget(t *testing.T) { } }, wantErrors: []string{ - "spec.cors.allowOrigins[0]: Invalid value: \"foo.bar.com\": spec.cors.allowOrigins[0] in body should match '^https?:\\/\\/(\\*\\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*(:[0-9]+)?$'", + "spec.cors.allowOrigins[0]: Invalid value: \"foo.bar.com\": spec.cors.allowOrigins[0] in body should match '^(\\*|https?:\\/\\/(\\*|(\\*\\.)?(([\\w-]+\\.?)+)?[\\w-]+)(:\\d{1,5})?)$'", }, }, { @@ -282,7 +344,208 @@ func TestSecurityPolicyTarget(t *testing.T) { } }, wantErrors: []string{ - "spec.cors.allowOrigins[0]: Invalid value: \"grpc://foo.bar.com\": spec.cors.allowOrigins[0] in body should match '^https?:\\/\\/(\\*\\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*(:[0-9]+)?$'", + "spec.cors.allowOrigins[0]: Invalid value: \"grpc://foo.bar.com\": spec.cors.allowOrigins[0] in body should match '^(\\*|https?:\\/\\/(\\*|(\\*\\.)?(([\\w-]+\\.?)+)?[\\w-]+)(:\\d{1,5})?)$'", + }, + }, + + // ExtAuth + { + desc: "GRPC external auth service", + mutate: func(sp *egv1a1.SecurityPolicy) { + sp.Spec = egv1a1.SecurityPolicySpec{ + ExtAuth: &egv1a1.ExtAuth{ + GRPC: &egv1a1.GRPCExtAuthService{ + BackendRef: gwapiv1.BackendObjectReference{ + Name: "grpc-auth-service", + Port: ptr.To(gwapiv1.PortNumber(80)), + }, + }, + }, + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: "gateway.networking.k8s.io", + Kind: "Gateway", + Name: "eg", + }, + }, + } + }, + wantErrors: []string{}, + }, + { + desc: "HTTP external auth service", + mutate: func(sp *egv1a1.SecurityPolicy) { + sp.Spec = egv1a1.SecurityPolicySpec{ + ExtAuth: &egv1a1.ExtAuth{ + HTTP: &egv1a1.HTTPExtAuthService{ + BackendRef: gwapiv1.BackendObjectReference{ + Name: "http-auth-service", + Port: ptr.To(gwapiv1.PortNumber(15001)), + }, + }, + }, + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: "gateway.networking.k8s.io", + Kind: "Gateway", + Name: "eg", + }, + }, + } + }, + wantErrors: []string{}, + }, + { + desc: "no extAuth", + mutate: func(sp *egv1a1.SecurityPolicy) { + sp.Spec = egv1a1.SecurityPolicySpec{ + ExtAuth: &egv1a1.ExtAuth{}, + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: "gateway.networking.k8s.io", + Kind: "Gateway", + Name: "eg", + }, + }, + } + }, + wantErrors: []string{ + "spec.extAuth: Invalid value: \"object\": one of grpc or http must be specified", + }, + }, + { + desc: "with both extAuth services", + mutate: func(sp *egv1a1.SecurityPolicy) { + sp.Spec = egv1a1.SecurityPolicySpec{ + ExtAuth: &egv1a1.ExtAuth{ + GRPC: &egv1a1.GRPCExtAuthService{ + BackendRef: gwapiv1.BackendObjectReference{ + Name: "grpc-auth-service", + Port: ptr.To(gwapiv1.PortNumber(80)), + }, + }, + HTTP: &egv1a1.HTTPExtAuthService{ + BackendRef: gwapiv1.BackendObjectReference{ + Name: "http-auth-service", + Port: ptr.To(gwapiv1.PortNumber(15001)), + }, + }, + }, + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: "gateway.networking.k8s.io", + Kind: "Gateway", + Name: "eg", + }, + }, + } + }, + wantErrors: []string{ + "spec.extAuth: Invalid value: \"object\": only one of grpc or http can be specified", + }, + }, + { + desc: "http extAuth service invalid Group", + mutate: func(sp *egv1a1.SecurityPolicy) { + sp.Spec = egv1a1.SecurityPolicySpec{ + ExtAuth: &egv1a1.ExtAuth{ + HTTP: &egv1a1.HTTPExtAuthService{ + BackendRef: gwapiv1.BackendObjectReference{ + Group: ptr.To(gwapiv1.Group("unsupported")), + Name: "http-auth-service", + Port: ptr.To(gwapiv1.PortNumber(15001)), + }, + }, + }, + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: "gateway.networking.k8s.io", + Kind: "Gateway", + Name: "eg", + }, + }, + } + }, + wantErrors: []string{ + "spec.extAuth: Invalid value: \"object\": group is invalid, only the core API group (specified by omitting the group field or setting it to an empty string) is supported", + }, + }, + { + desc: "http extAuth service invalid Kind", + mutate: func(sp *egv1a1.SecurityPolicy) { + sp.Spec = egv1a1.SecurityPolicySpec{ + ExtAuth: &egv1a1.ExtAuth{ + HTTP: &egv1a1.HTTPExtAuthService{ + BackendRef: gwapiv1.BackendObjectReference{ + Kind: ptr.To(gwapiv1.Kind("unsupported")), + Name: "http-auth-service", + Port: ptr.To(gwapiv1.PortNumber(15001)), + }, + }, + }, + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: "gateway.networking.k8s.io", + Kind: "Gateway", + Name: "eg", + }, + }, + } + }, + wantErrors: []string{ + "spec.extAuth: Invalid value: \"object\": kind is invalid, only Service (specified by omitting the kind field or setting it to 'Service') is supported", + }, + }, + { + desc: "grpc extAuth service invalid Group", + mutate: func(sp *egv1a1.SecurityPolicy) { + sp.Spec = egv1a1.SecurityPolicySpec{ + ExtAuth: &egv1a1.ExtAuth{ + GRPC: &egv1a1.GRPCExtAuthService{ + BackendRef: gwapiv1.BackendObjectReference{ + Group: ptr.To(gwapiv1.Group("unsupported")), + Name: "http-auth-service", + Port: ptr.To(gwapiv1.PortNumber(15001)), + }, + }, + }, + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: "gateway.networking.k8s.io", + Kind: "Gateway", + Name: "eg", + }, + }, + } + }, + wantErrors: []string{ + "spec.extAuth: Invalid value: \"object\": group is invalid, only the core API group (specified by omitting the group field or setting it to an empty string) is supported", + }, + }, + { + desc: "grpc extAuth service invalid Kind", + mutate: func(sp *egv1a1.SecurityPolicy) { + sp.Spec = egv1a1.SecurityPolicySpec{ + ExtAuth: &egv1a1.ExtAuth{ + GRPC: &egv1a1.GRPCExtAuthService{ + BackendRef: gwapiv1.BackendObjectReference{ + Kind: ptr.To(gwapiv1.Kind("unsupported")), + Name: "http-auth-service", + Port: ptr.To(gwapiv1.PortNumber(15001)), + }, + }, + }, + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: "gateway.networking.k8s.io", + Kind: "Gateway", + Name: "eg", + }, + }, + } + }, + wantErrors: []string{ + "spec.extAuth: Invalid value: \"object\": kind is invalid, only Service (specified by omitting the kind field or setting it to 'Service') is supported", }, }, } diff --git a/test/conformance/experimental_conformance_test.go b/test/conformance/experimental_conformance_test.go index 348f44a3a4d..b6d6b19e953 100644 --- a/test/conformance/experimental_conformance_test.go +++ b/test/conformance/experimental_conformance_test.go @@ -12,7 +12,7 @@ import ( "os" "testing" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" @@ -53,11 +53,11 @@ func TestExperimentalConformance(t *testing.T) { } err = v1alpha2.AddToScheme(mgrClient.Scheme()) - assert.NoError(t, err) + require.NoError(t, err) err = v1beta1.AddToScheme(mgrClient.Scheme()) - assert.NoError(t, err) + require.NoError(t, err) err = v1.AddToScheme(mgrClient.Scheme()) - assert.NoError(t, err) + require.NoError(t, err) // experimental conformance flags conformanceProfiles = sets.New( @@ -119,7 +119,7 @@ func experimentalConformance(t *testing.T) { } err = experimentalConformanceReport(t.Logf, *report, *flags.ReportOutput) - assert.NoError(t, err) + require.NoError(t, err) } func experimentalConformanceReport(logf func(string, ...any), report confv1a1.ConformanceReport, output string) error { diff --git a/test/e2e/base/manifests.yaml b/test/e2e/base/manifests.yaml index 54450ce73bf..73131cd9913 100644 --- a/test/e2e/base/manifests.yaml +++ b/test/e2e/base/manifests.yaml @@ -521,3 +521,110 @@ spec: allowedRoutes: kinds: - kind: UDPRoute +--- +apiVersion: v1 +kind: Namespace +metadata: + name: gateway-preserve-case-backend +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: go-server + namespace: gateway-preserve-case-backend +data: + go.mod: | + module srvr + go 1.21.3 + require ( + github.com/andybalholm/brotli v1.0.5 // indirect + github.com/klauspost/compress v1.17.0 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.51.0 // indirect + ) + go.sum: | + github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= + github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= + github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= + github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= + github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= + github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= + github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA= + github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g= + main.go: | + package main + import ( + "encoding/json" + "fmt" + "log" + "github.com/valyala/fasthttp" + ) + func HandleFastHTTP(ctx *fasthttp.RequestCtx) { + ctx.QueryArgs().VisitAll(func(key, value []byte) { + if string(key) == "headers" { + ctx.Response.Header.Add(string(value), "PrEsEnT") + } + }) + headers := map[string][]string{} + ctx.Request.Header.VisitAll(func(key, value []byte) { + headers[string(key)] = append(headers[string(key)], string(value)) + }) + if d, err := json.MarshalIndent(headers, "", " "); err != nil { + ctx.Error(fmt.Sprintf("%s", err), fasthttp.StatusBadRequest) + } else { + fmt.Fprintf(ctx, string(d)+"\n") + } + } + func main() { + s := fasthttp.Server{ + Handler: HandleFastHTTP, + DisableHeaderNamesNormalizing: true, + } + log.Printf("Starting on port 8000") + log.Fatal(s.ListenAndServe(":8000")) + } +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: golang-app-deployment + namespace: gateway-preserve-case-backend +spec: + replicas: 1 + selector: + matchLabels: + app: golang-app + template: + metadata: + labels: + app: golang-app + spec: + containers: + - name: golang-app-container + command: + - sh + - "-c" + - "cp -a /app /app-live && cd /app-live && go run . " + image: golang:1.21.3-alpine + ports: + - containerPort: 8000 + volumeMounts: + - name: go-server + mountPath: /app + volumes: + - name: go-server + configMap: + name: go-server +--- +apiVersion: v1 +kind: Service +metadata: + name: fasthttp-backend + namespace: gateway-preserve-case-backend +spec: + selector: + app: golang-app + ports: + - protocol: TCP + port: 8000 + targetPort: 8000 diff --git a/test/e2e/testdata/preserve-case.yaml b/test/e2e/testdata/preserve-case.yaml new file mode 100644 index 00000000000..53d521d7ea8 --- /dev/null +++ b/test/e2e/testdata/preserve-case.yaml @@ -0,0 +1,45 @@ +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: ReferenceGrant +metadata: + name: allow-preserve-case + namespace: gateway-preserve-case-backend +spec: + from: + - group: gateway.networking.k8s.io + kind: HTTPRoute + namespace: gateway-conformance-infra + to: + - group: "" + kind: Service +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: ClientTrafficPolicy +metadata: + name: preserve-case + namespace: gateway-conformance-infra +spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: same-namespace + namespace: gateway-conformance-infra + http1: + preserveHeaderCase: true +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: preserve-case + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - matches: + - path: + type: PathPrefix + value: /preserve + backendRefs: + - name: fasthttp-backend + namespace: gateway-preserve-case-backend + port: 8000 diff --git a/test/e2e/testdata/ratelimit-block-all-ips.yaml b/test/e2e/testdata/ratelimit-cidr-match.yaml similarity index 94% rename from test/e2e/testdata/ratelimit-block-all-ips.yaml rename to test/e2e/testdata/ratelimit-cidr-match.yaml index 9741ad17a8a..4ee92d26fcd 100644 --- a/test/e2e/testdata/ratelimit-block-all-ips.yaml +++ b/test/e2e/testdata/ratelimit-cidr-match.yaml @@ -7,7 +7,7 @@ spec: targetRef: group: gateway.networking.k8s.io kind: HTTPRoute - name: http-ratelimit + name: cidr-ratelimit namespace: gateway-conformance-infra rateLimit: type: Global @@ -24,7 +24,7 @@ spec: apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: - name: http-ratelimit + name: cidr-ratelimit namespace: gateway-conformance-infra spec: parentRefs: diff --git a/test/e2e/testdata/ratelimit-header-match.yaml b/test/e2e/testdata/ratelimit-header-match.yaml new file mode 100644 index 00000000000..d38d66a5a79 --- /dev/null +++ b/test/e2e/testdata/ratelimit-header-match.yaml @@ -0,0 +1,43 @@ +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: BackendTrafficPolicy +metadata: + name: ratelimit-anded-headers + namespace: gateway-conformance-infra +spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: header-ratelimit + namespace: gateway-conformance-infra + rateLimit: + type: Global + global: + rules: + - clientSelectors: + - headers: + - name: x-user-id + type: Exact + value: one + - name: x-user-org + type: Exact + value: acme + limit: + requests: 3 + unit: Hour +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: header-ratelimit + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - matches: + - path: + type: PathPrefix + value: /get + backendRefs: + - name: infra-backend-v1 + port: 8080 diff --git a/test/e2e/tests/basic-auth.go b/test/e2e/tests/basic-auth.go index cecac930216..e5b16e6c307 100644 --- a/test/e2e/tests/basic-auth.go +++ b/test/e2e/tests/basic-auth.go @@ -156,6 +156,35 @@ var BasicAuthTest = suite.ConformanceTest{ t.Errorf("failed to compare request and response: %v", err) } }) + + // https://github.com/envoyproxy/gateway/issues/2507 + t.Run("request without matching routes ", func(t *testing.T) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "http-with-basic-auth-1", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + SecurityPolicyMustBeAccepted(t, suite.Client, types.NamespacedName{Name: "basic-auth-1", Namespace: ns}) + // TODO: We should wait for the `programmed` condition to be true before sending traffic. + expectedResponse := http.ExpectedResponse{ + Request: http.Request{ + Path: "/not-matching-route", + }, + Response: http.Response{ + StatusCode: 404, + }, + Namespace: ns, + } + + req := http.MakeRequest(t, &expectedResponse, gwAddr, "HTTP", "http") + cReq, cResp, err := suite.RoundTripper.CaptureRoundTrip(req) + if err != nil { + t.Errorf("failed to get expected response: %v", err) + } + + if err := http.CompareRequest(t, &req, cReq, cResp, expectedResponse); err != nil { + t.Errorf("failed to compare request and response: %v", err) + } + }) }, } diff --git a/test/e2e/tests/preservecase.go b/test/e2e/tests/preservecase.go new file mode 100644 index 00000000000..59d54c2f84e --- /dev/null +++ b/test/e2e/tests/preservecase.go @@ -0,0 +1,140 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +//go:build e2e +// +build e2e + +package tests + +import ( + "context" + "encoding/json" + "fmt" + "io" + nethttp "net/http" + "net/http/httputil" + "regexp" + "testing" + + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/roundtripper" + "sigs.k8s.io/gateway-api/conformance/utils/suite" +) + +func init() { + ConformanceTests = append(ConformanceTests, PreserveCaseTest) +} + +// Copied from the conformance suite because it's needed in casePreservingRoundTrip +var startLineRegex = regexp.MustCompile(`(?m)^`) + +func formatDump(data []byte, prefix string) string { + data = startLineRegex.ReplaceAllLiteral(data, []byte(prefix)) + return string(data) +} + +// Copied from the conformance suite and modified to not normalize headers before sending them +// to the remote side. +// The default HTTP client implementation in Golang also automatically normalizes received +// headers as they are parsed , so it's not possible to verify that returned headers were not normalized +func casePreservingRoundTrip(request roundtripper.Request, transport nethttp.RoundTripper, suite *suite.ConformanceTestSuite) (map[string]any, error) { + client := &nethttp.Client{} + client.Transport = transport + + method := "GET" + ctx, cancel := context.WithTimeout(context.Background(), suite.TimeoutConfig.RequestTimeout) + defer cancel() + req, err := nethttp.NewRequestWithContext(ctx, method, request.URL.String(), nil) + if err != nil { + return nil, err + } + if request.Host != "" { + req.Host = request.Host + } + if request.Headers != nil { + for name, value := range request.Headers { + req.Header[name] = value + } + } + if suite.Debug { + var dump []byte + dump, err = httputil.DumpRequestOut(req, true) + if err != nil { + return nil, err + } + + fmt.Printf("Sending Request:\n%s\n\n", formatDump(dump, "< ")) + } + + resp, err := client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if suite.Debug { + var dump []byte + dump, err = httputil.DumpResponse(resp, true) + if err != nil { + return nil, err + } + + fmt.Printf("Received Response:\n%s\n\n", formatDump(dump, "< ")) + } + + cReq := map[string]any{} + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + err = json.Unmarshal(body, &cReq) + if err != nil { + return nil, fmt.Errorf("unexpected error reading response: %w", err) + } + + return cReq, nil +} + +var PreserveCaseTest = suite.ConformanceTest{ + ShortName: "Preserve Case", + Description: "Preserve header cases", + Manifests: []string{"testdata/preserve-case.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + t.Run("should preserve header cases in both directions", func(t *testing.T) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "preserve-case", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + + // Can't use the standard method for checking the response, since the remote side isn't the + // conformance echo server and it returns a differently formatted response. + expectedResponse := http.ExpectedResponse{ + Request: http.Request{ + Path: "/preserve?headers=ReSpOnSeHeAdEr", + Headers: map[string]string{ + "SpEcIaL": "Header", + }, + }, + Namespace: ns, + } + + var rt nethttp.RoundTripper + req := http.MakeRequest(t, &expectedResponse, gwAddr, "HTTP", "http") + respBody, err := casePreservingRoundTrip(req, rt, suite) + if err != nil { + t.Errorf("failed to get expected response: %v", err) + } + + if _, found := respBody["SpEcIaL"]; !found { + t.Errorf("case was not preserved for test header: %+v", respBody) + } + }) + + }, +} diff --git a/test/e2e/tests/ratelimit.go b/test/e2e/tests/ratelimit.go index eb48f955f3c..4bfed9506d8 100644 --- a/test/e2e/tests/ratelimit.go +++ b/test/e2e/tests/ratelimit.go @@ -19,18 +19,19 @@ import ( ) func init() { - ConformanceTests = append(ConformanceTests, RateLimitTest) + ConformanceTests = append(ConformanceTests, RateLimitCIDRMatchTest) + ConformanceTests = append(ConformanceTests, RateLimitHeaderMatchTest) ConformanceTests = append(ConformanceTests, RateLimitBasedJwtClaimsTest) } -var RateLimitTest = suite.ConformanceTest{ - ShortName: "RateLimit", - Description: "Limit all requests", - Manifests: []string{"testdata/ratelimit-block-all-ips.yaml"}, +var RateLimitCIDRMatchTest = suite.ConformanceTest{ + ShortName: "RateLimitCIDRMatch", + Description: "Limit all requests that match CIDR", + Manifests: []string{"testdata/ratelimit-cidr-match.yaml"}, Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { t.Run("block all ips", func(t *testing.T) { ns := "gateway-conformance-infra" - routeNN := types.NamespacedName{Name: "http-ratelimit", Namespace: ns} + routeNN := types.NamespacedName{Name: "cidr-ratelimit", Namespace: ns} gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) ratelimitHeader := make(map[string]string) @@ -63,12 +64,100 @@ var RateLimitTest = suite.ConformanceTest{ // keep sending requests till get 200 first, that will cost one 200 http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectOkResp) - // fire the rest request + // fire the rest of requests if err := GotExactExpectedResponse(t, 2, suite.RoundTripper, expectOkReq, expectOkResp); err != nil { - t.Errorf("fail to get expected response at first three request: %v", err) + t.Errorf("failed to get expected response for the first three requests: %v", err) } if err := GotExactExpectedResponse(t, 1, suite.RoundTripper, expectLimitReq, expectLimitResp); err != nil { - t.Errorf("fail to get expected response at last fourth request: %v", err) + t.Errorf("failed to get expected response for the last (fourth) request: %v", err) + } + }) + }, +} + +var RateLimitHeaderMatchTest = suite.ConformanceTest{ + ShortName: "RateLimitHeaderMatch", + Description: "Limit all requests that match headers", + Manifests: []string{"testdata/ratelimit-header-match.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "header-ratelimit", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + + t.Run("all matched headers can got limited", func(t *testing.T) { + requestHeaders := map[string]string{ + "x-user-id": "one", + "x-user-org": "acme", + } + + ratelimitHeader := make(map[string]string) + expectOkResp := http.ExpectedResponse{ + Request: http.Request{ + Path: "/get", + Headers: requestHeaders, + }, + Response: http.Response{ + StatusCode: 200, + Headers: ratelimitHeader, + }, + Namespace: ns, + } + expectOkResp.Response.Headers["X-Ratelimit-Limit"] = "3, 3;w=3600" + expectOkReq := http.MakeRequest(t, &expectOkResp, gwAddr, "HTTP", "http") + + expectLimitResp := http.ExpectedResponse{ + Request: http.Request{ + Path: "/get", + Headers: requestHeaders, + }, + Response: http.Response{ + StatusCode: 429, + }, + Namespace: ns, + } + expectLimitReq := http.MakeRequest(t, &expectLimitResp, gwAddr, "HTTP", "http") + + // should just send exactly 4 requests, and expect 429 + + // keep sending requests till get 200 first, that will cost one 200 + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectOkResp) + + // fire the rest of the requests + if err := GotExactExpectedResponse(t, 2, suite.RoundTripper, expectOkReq, expectOkResp); err != nil { + t.Errorf("failed to get expected response for the first three requests: %v", err) + } + if err := GotExactExpectedResponse(t, 1, suite.RoundTripper, expectLimitReq, expectLimitResp); err != nil { + t.Errorf("failed to get expected response for the last (fourth) request: %v", err) + } + }) + + t.Run("only one matched header cannot got limited", func(t *testing.T) { + requestHeaders := map[string]string{ + "x-user-id": "one", + } + + // it does not require any rate limit header, since this request never be rate limited. + expectOkResp := http.ExpectedResponse{ + Request: http.Request{ + Path: "/get", + Headers: requestHeaders, + }, + Response: http.Response{ + StatusCode: 200, + }, + Namespace: ns, + } + expectOkReq := http.MakeRequest(t, &expectOkResp, gwAddr, "HTTP", "http") + + // send exactly 4 requests, and still expect 200 + + // keep sending requests till get 200 first, that will cost one 200 + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectOkResp) + + // fire the rest of the requests + if err := GotExactExpectedResponse(t, 3, suite.RoundTripper, expectOkReq, expectOkResp); err != nil { + t.Errorf("failed to get expected responses for the request: %v", err) } }) }, @@ -164,7 +253,7 @@ var RateLimitBasedJwtClaimsTest = suite.ConformanceTest{ // keep sending requests till get 200 first, that will cost one 200 http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, JwtOkResp) - // fire the rest request + // fire the rest of requests if err := GotExactExpectedResponse(t, 2, suite.RoundTripper, JwtReq, JwtOkResp); err != nil { t.Errorf("failed to get expected response at third request: %v", err) } diff --git a/tools/crd-ref-docs/config.yaml b/tools/crd-ref-docs/config.yaml index cd95e3d8d4a..18e84746d4c 100644 --- a/tools/crd-ref-docs/config.yaml +++ b/tools/crd-ref-docs/config.yaml @@ -14,3 +14,6 @@ render: - name: SecretObjectReference package: sigs.k8s.io/gateway-api/apis/v1 link: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.SecretObjectReference + - name: PolicyTargetReferenceWithSectionName + package: sigs.k8s.io/gateway-api/apis/v1alpha2 + link: https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.PolicyTargetReferenceWithSectionName diff --git a/tools/crd-ref-docs/templates/README b/tools/crd-ref-docs/templates/README new file mode 100644 index 00000000000..49754fb7ef8 --- /dev/null +++ b/tools/crd-ref-docs/templates/README @@ -0,0 +1 @@ +Original from https://github.com/elastic/crd-ref-docs/tree/9a3105b6ca763ea03393fa6f396046ad7b5d4e38/templates/markdown diff --git a/tools/crd-ref-docs/templates/gv_details.tpl b/tools/crd-ref-docs/templates/gv_details.tpl new file mode 100644 index 00000000000..30ad0d75184 --- /dev/null +++ b/tools/crd-ref-docs/templates/gv_details.tpl @@ -0,0 +1,19 @@ +{{- define "gvDetails" -}} +{{- $gv := . -}} + +## {{ $gv.GroupVersionString }} + +{{ $gv.Doc }} + +{{- if $gv.Kinds }} +### Resource Types +{{- range $gv.SortedKinds }} +- {{ $gv.TypeForKind . | markdownRenderTypeLink }} +{{- end }} +{{ end }} + +{{ range $gv.SortedTypes }} +{{ template "type" . }} +{{ end }} + +{{- end -}} diff --git a/tools/crd-ref-docs/templates/gv_list.tpl b/tools/crd-ref-docs/templates/gv_list.tpl new file mode 100644 index 00000000000..a4d3dadf18c --- /dev/null +++ b/tools/crd-ref-docs/templates/gv_list.tpl @@ -0,0 +1,15 @@ +{{- define "gvList" -}} +{{- $groupVersions := . -}} + +# API Reference + +## Packages +{{- range $groupVersions }} +- {{ markdownRenderGVLink . }} +{{- end }} + +{{ range $groupVersions }} +{{ template "gvDetails" . }} +{{ end }} + +{{- end -}} diff --git a/tools/crd-ref-docs/templates/type.tpl b/tools/crd-ref-docs/templates/type.tpl new file mode 100644 index 00000000000..581cd8fcd9a --- /dev/null +++ b/tools/crd-ref-docs/templates/type.tpl @@ -0,0 +1,33 @@ +{{- define "type" -}} +{{- $type := . -}} +{{- if markdownShouldRenderType $type -}} + +#### {{ $type.Name }} + +{{ if $type.IsAlias }}_Underlying type:_ _{{ markdownRenderTypeLink $type.UnderlyingType }}_{{ end }} + +{{ $type.Doc }} + +{{ if $type.References -}} +_Appears in:_ +{{- range $type.SortedReferences }} +- {{ markdownRenderTypeLink . }} +{{- end }} +{{- end }} + +{{ if $type.Members -}} +| Field | Type | Required | Description | +| --- | --- | --- | --- | +{{ if $type.GVK -}} +| `apiVersion` | _string_ | |`{{ $type.GVK.Group }}/{{ $type.GVK.Version }}` +| `kind` | _string_ | |`{{ $type.GVK.Kind }}` +{{ end -}} + +{{ range $type.Members -}} +| `{{ .Name }}` | _{{ markdownRenderType .Type }}_ | {{ with .Markers.optional }} {{ "false" }} {{ else }} {{ "true" }} {{end}} | {{ template "type_members" . }} | +{{ end -}} + +{{ end -}} + +{{- end -}} +{{- end -}} diff --git a/tools/crd-ref-docs/templates/type_members.tpl b/tools/crd-ref-docs/templates/type_members.tpl new file mode 100644 index 00000000000..041758a8725 --- /dev/null +++ b/tools/crd-ref-docs/templates/type_members.tpl @@ -0,0 +1,8 @@ +{{- define "type_members" -}} +{{- $field := . -}} +{{- if eq $field.Name "metadata" -}} +Refer to Kubernetes API documentation for fields of `metadata`. +{{- else -}} +{{ markdownRenderFieldDoc $field.Doc }} +{{- end -}} +{{- end -}} diff --git a/tools/docker/envoy-gateway/Dockerfile b/tools/docker/envoy-gateway/Dockerfile index 08b05307f9f..7063e5bf15f 100644 --- a/tools/docker/envoy-gateway/Dockerfile +++ b/tools/docker/envoy-gateway/Dockerfile @@ -1,6 +1,6 @@ # Use distroless as minimal base image to package the manager binary # Refer to https://github.com/GoogleContainerTools/distroless for more details -FROM gcr.io/distroless/static:nonroot@sha256:112a87f19e83c83711cc81ce8ed0b4d79acd65789682a6a272df57c4a0858534 +FROM gcr.io/distroless/static:nonroot@sha256:6a3500b086c2856fbc189f5d11351bdbcf7c4dc5673c2b6070aac9d607da90d7 ARG TARGETPLATFORM COPY $TARGETPLATFORM/envoy-gateway /usr/local/bin/ diff --git a/tools/linter/golangci-lint/.golangci.yml b/tools/linter/golangci-lint/.golangci.yml index ca5ffcc63e3..825e9c8bae1 100644 --- a/tools/linter/golangci-lint/.golangci.yml +++ b/tools/linter/golangci-lint/.golangci.yml @@ -15,6 +15,7 @@ linters: - misspell - revive - stylecheck + - testifylint - unconvert - unparam @@ -31,6 +32,8 @@ linters-settings: desc: "use sigs.k8s.io/yaml instead" - pkg: k8s.io/utils/pointer desc: "use k8s.io/utils/ptr instead" + - pkg: github.com/tetratelabs/multierror + desc: "use errors instead" gci: sections: # Captures all standard packages if they do not match another section. @@ -39,19 +42,8 @@ linters-settings: - default # Groups all imports with the specified Prefix. - prefix(github.com/envoyproxy/gateway) - goimports: - # put imports beginning with prefix after 3rd-party packages; - # it's a comma-separated list of prefixes - local-prefixes: github.com/envoyproxy/gateway/ gofmt: simplify: true - unparam: - check-exported: false - revive: - rules: - # TODO: enable if-return check - - name: if-return - disabled: true goheader: # Note that because the format is different (this needs no comment markers), # updating this text means also updating /tools/boilerplate.txt so that @@ -61,6 +53,32 @@ linters-settings: SPDX-License-Identifier: Apache-2.0 The full text of the Apache license is available in the LICENSE file at the root of the repo. + goimports: + # put imports beginning with prefix after 3rd-party packages; + # it's a comma-separated list of prefixes + local-prefixes: github.com/envoyproxy/gateway/ + revive: + rules: + # TODO: enable if-return check + - name: if-return + disabled: true + testifylint: + disable: + - float-compare + - go-require + enable: + - bool-compare + - compares + - empty + - error-is-as + - error-nil + - expected-actual + - len + - require-error + - suite-dont-use-pkg + - suite-extra-assert-call + unparam: + check-exported: false issues: exclude-rules: diff --git a/tools/make/docs.mk b/tools/make/docs.mk index fc61912f86a..26cabc9e7a2 100644 --- a/tools/make/docs.mk +++ b/tools/make/docs.mk @@ -46,6 +46,7 @@ docs-api-gen: $(tools/crd-ref-docs) $(tools/crd-ref-docs) \ --source-path=api/v1alpha1 \ --config=tools/crd-ref-docs/config.yaml \ + --templates-dir=tools/crd-ref-docs/templates \ --output-path=site/content/en/latest/api/extension_types.md \ --max-depth 10 \ --renderer=markdown diff --git a/tools/make/kube.mk b/tools/make/kube.mk index 00811b01506..1384c9340e0 100644 --- a/tools/make/kube.mk +++ b/tools/make/kube.mk @@ -29,6 +29,7 @@ CONTROLLERGEN_OBJECT_FLAGS := object:headerFile="$(ROOT_DIR)/tools/boilerplate/ .PHONY: manifests manifests: $(tools/controller-gen) generate-gwapi-manifests ## Generate WebhookConfiguration and CustomResourceDefinition objects. + @$(LOG_TARGET) $(tools/controller-gen) crd:allowDangerousTypes=true paths="./..." output:crd:artifacts:config=charts/gateway-helm/crds/generated .PHONY: generate-gwapi-manifests diff --git a/tools/make/tools.mk b/tools/make/tools.mk index dda0fa26a41..2edfbcee22a 100644 --- a/tools/make/tools.mk +++ b/tools/make/tools.mk @@ -17,7 +17,7 @@ tools/golangci-lint = $(tools.bindir)/golangci-lint tools/kustomize = $(tools.bindir)/kustomize tools/kind = $(tools.bindir)/kind tools/setup-envtest = $(tools.bindir)/setup-envtest -tools/crd-ref-docs = $(tools.bindir)/crd-ref-docs +tools/crd-ref-docs = $(tools.bindir)/crd-ref-docs tools/buf = $(tools.bindir)/buf tools/protoc-gen-go = $(tools.bindir)/protoc-gen-go tools/protoc-gen-go-grpc = $(tools.bindir)/protoc-gen-go-grpc diff --git a/tools/src/buf/go.mod b/tools/src/buf/go.mod index 758489607ba..df182f14780 100644 --- a/tools/src/buf/go.mod +++ b/tools/src/buf/go.mod @@ -2,74 +2,81 @@ module local go 1.19 -require github.com/bufbuild/buf v1.28.1 +require github.com/bufbuild/buf v1.29.0 require ( - buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.31.0-20231106192134-1baebb0a1518.2 // indirect - buf.build/gen/go/bufbuild/registry/protocolbuffers/go v1.31.0-20231111212044-1119bf4b707e.2 // indirect - connectrpc.com/connect v1.12.0 // indirect - connectrpc.com/otelconnect v0.6.0 // indirect + buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.32.0-20231115204500-e097f827e652.1 // indirect + connectrpc.com/connect v1.14.0 // indirect + connectrpc.com/otelconnect v0.7.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/antlr4-go/antlr/v4 v4.13.0 // indirect - github.com/bufbuild/protocompile v0.6.1-0.20231108163138-146b831231f7 // indirect - github.com/bufbuild/protovalidate-go v0.4.1 // indirect + github.com/bufbuild/protocompile v0.8.0 // indirect + github.com/bufbuild/protovalidate-go v0.5.0 // indirect + github.com/bufbuild/protoyaml-go v0.1.7 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect github.com/distribution/reference v0.5.0 // indirect github.com/docker/cli v24.0.7+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect - github.com/docker/docker v24.0.7+incompatible // indirect - github.com/docker/docker-credential-helpers v0.8.0 // indirect - github.com/docker/go-connections v0.4.0 // indirect + github.com/docker/docker v25.0.0+incompatible // indirect + github.com/docker/docker-credential-helpers v0.8.1 // indirect + github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/fgprof v0.9.3 // indirect - github.com/go-chi/chi/v5 v5.0.10 // indirect - github.com/go-logr/logr v1.3.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-chi/chi/v5 v5.0.11 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/gofrs/uuid/v5 v5.0.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/google/cel-go v0.18.2 // indirect - github.com/google/go-containerregistry v0.16.1 // indirect - github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect + github.com/google/cel-go v0.19.0 // indirect + github.com/google/go-containerregistry v0.18.0 // indirect + github.com/google/pprof v0.0.0-20240117000934-35fc243c5815 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jdx/go-netrc v1.0.0 // indirect - github.com/klauspost/compress v1.17.2 // indirect + github.com/klauspost/compress v1.17.4 // indirect github.com/klauspost/pgzip v1.2.6 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/moby/term v0.5.0 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0-rc5 // indirect - github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pkg/profile v1.7.0 // indirect + github.com/rogpeppe/go-internal v1.10.0 // indirect github.com/rs/cors v1.10.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/spf13/cobra v1.8.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect - github.com/tetratelabs/wazero v1.5.0 // indirect + github.com/tetratelabs/wazero v1.6.0 // indirect github.com/vbatts/tar-split v0.11.5 // indirect - go.opentelemetry.io/otel v1.20.0 // indirect - go.opentelemetry.io/otel/metric v1.20.0 // indirect - go.opentelemetry.io/otel/sdk v1.20.0 // indirect - go.opentelemetry.io/otel/trace v1.20.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect + go.opentelemetry.io/otel v1.22.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 // indirect + go.opentelemetry.io/otel/metric v1.22.0 // indirect + go.opentelemetry.io/otel/sdk v1.22.0 // indirect + go.opentelemetry.io/otel/trace v1.22.0 // indirect + go.opentelemetry.io/proto/otlp v1.1.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.26.0 // indirect - golang.org/x/crypto v0.15.0 // indirect - golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect + golang.org/x/crypto v0.18.0 // indirect + golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect golang.org/x/mod v0.14.0 // indirect - golang.org/x/net v0.18.0 // indirect - golang.org/x/sync v0.5.0 // indirect - golang.org/x/sys v0.14.0 // indirect - golang.org/x/term v0.14.0 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/sync v0.6.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/term v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.15.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 // indirect - google.golang.org/protobuf v1.31.1-0.20231027082548-f4a6c1f6e5c1 // indirect + golang.org/x/tools v0.17.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240116215550-a9fa1716bcac // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/tools/src/buf/go.sum b/tools/src/buf/go.sum index 96169e9a7ba..4a06be3fa59 100644 --- a/tools/src/buf/go.sum +++ b/tools/src/buf/go.sum @@ -1,31 +1,34 @@ -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.31.0-20230914171853-63dfe56cc2c4.2/go.mod h1:xafc+XIsTxTy76GJQ1TKgvJWsSugFBqMaN27WhUblew= -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.31.0-20231106192134-1baebb0a1518.2 h1:iRWpWLm1nrsCHBVhibqPJQB3iIf3FRsAXioJVU8m6w0= -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.31.0-20231106192134-1baebb0a1518.2/go.mod h1:xafc+XIsTxTy76GJQ1TKgvJWsSugFBqMaN27WhUblew= -buf.build/gen/go/bufbuild/registry/protocolbuffers/go v1.31.0-20231111212044-1119bf4b707e.2 h1:tgXOEZtPifMR5kaQ6GB4t7pk0G3dai/OS3JFD9Zt+eE= -buf.build/gen/go/bufbuild/registry/protocolbuffers/go v1.31.0-20231111212044-1119bf4b707e.2/go.mod h1:3Ion4eJWjUDfJyrUXSgtB3zO5ZweZtyvNuEc+fyMBCk= -connectrpc.com/connect v1.12.0 h1:HwKdOY0lGhhoHdsza+hW55aqHEC64pYpObRNoAgn70g= -connectrpc.com/connect v1.12.0/go.mod h1:3AGaO6RRGMx5IKFfqbe3hvK1NqLosFNP2BxDYTPmNPo= -connectrpc.com/otelconnect v0.6.0 h1:VJAdQL9+sgdUw9+7+J+jq8pQo/h1S7tSFv2+vDcR7bU= -connectrpc.com/otelconnect v0.6.0/go.mod h1:jdcs0uiwXQVmSMgTJ2dAaWR5VbpNd7QKNkuoH7n86RA= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.32.0-20231115204500-e097f827e652.1 h1:u0olL4yf2p7Tl5jfsAK5keaFi+JFJuv1CDHrbiXkxkk= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.32.0-20231115204500-e097f827e652.1/go.mod h1:tiTMKD8j6Pd/D2WzREoweufjzaJKHZg35f/VGcZ2v3I= +connectrpc.com/connect v1.14.0 h1:PDS+J7uoz5Oui2VEOMcfz6Qft7opQM9hPiKvtGC01pA= +connectrpc.com/connect v1.14.0/go.mod h1:uoAq5bmhhn43TwhaKdGKN/bZcGtzPW1v+ngDTn5u+8s= +connectrpc.com/otelconnect v0.7.0 h1:ZH55ZZtcJOTKWWLy3qmL4Pam4RzRWBJFOqTPyAqCXkY= +connectrpc.com/otelconnect v0.7.0/go.mod h1:Bt2ivBymHZHqxvo4HkJ0EwHuUzQN6k2l0oH+mp/8nwc= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= -github.com/bufbuild/buf v1.28.1 h1:JG+PjhaVz4bprGV1u//ZBDSxWwFnjrzjse2pmm4zBlI= -github.com/bufbuild/buf v1.28.1/go.mod h1:X/HDGbWUM2QiR5XvvsBfElUPblETOf96zq5H7FOUiP4= -github.com/bufbuild/protocompile v0.6.1-0.20231108163138-146b831231f7 h1:1pUks8VaLdprN9wrxAgshb06b08IzdYp0B7JgoDeUfw= -github.com/bufbuild/protocompile v0.6.1-0.20231108163138-146b831231f7/go.mod h1:9N39DyRmxAF5+5AjqXQKV6hyWDI0EeoX4TRMix2ZnPE= -github.com/bufbuild/protovalidate-go v0.4.1 h1:ye/8S72WbEklCeltPkSEeT8Eu1A7P/gmMsmapkwqTFk= -github.com/bufbuild/protovalidate-go v0.4.1/go.mod h1:+p5FXfOjSEgLz5WBDTOMPMdQPXqALEERbJZU7huDCtA= +github.com/bufbuild/buf v1.29.0 h1:llP6HqOcCaSGBxOfnrp/mwvcY1O/dciEOl1QaMEOB3M= +github.com/bufbuild/buf v1.29.0/go.mod h1:UTjvPXTObvKQiGqxod32wt9zRz70TJsMpaigpbIZGuc= +github.com/bufbuild/protocompile v0.8.0 h1:9Kp1q6OkS9L4nM3FYbr8vlJnEwtbpDPQlQOVXfR+78s= +github.com/bufbuild/protocompile v0.8.0/go.mod h1:+Etjg4guZoAqzVk2czwEQP12yaxLJ8DxuqCJ9qHdH94= +github.com/bufbuild/protovalidate-go v0.5.0 h1:xFery2RlLh07FQTvB7hlasKqPrDK2ug+uw6DUiuadjo= +github.com/bufbuild/protovalidate-go v0.5.0/go.mod h1:3XAwFeJ2x9sXyPLgkxufH9sts1tQRk8fdt1AW93NiUU= +github.com/bufbuild/protoyaml-go v0.1.7 h1:3uKIoNb/l5zrZ93u+Xzsg6cdAO06lveZE/K7UUbUQLw= +github.com/bufbuild/protoyaml-go v0.1.7/go.mod h1:R8vE2+l49bSiIExP4VJpxOXleHE+FDzZ6HVxr3cYunw= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/stargz-snapshotter/estargz v0.15.1 h1:eXJjw9RbkLFgioVaTG+G/ZW/0kEe2oEKCdS/ZxIyoCU= github.com/containerd/stargz-snapshotter/estargz v0.15.1/go.mod h1:gr2RNwukQ/S9Nv33Lt6UC7xEx58C+LHRdoqbEKjz1Kk= github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -36,22 +39,24 @@ github.com/docker/cli v24.0.7+incompatible h1:wa/nIwYFW7BVTGa7SWPVyyXU9lgORqUb1x github.com/docker/cli v24.0.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= -github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8= -github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/docker v25.0.0+incompatible h1:g9b6wZTblhMgzOT2tspESstfw6ySZ9kdm94BLDKaZac= +github.com/docker/docker v25.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqYyMHOp5vfsD1807oKo= +github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= -github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk= -github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/go-chi/chi/v5 v5.0.11 h1:BnpYbFZ3T3S1WMpD79r7R5ThWX40TaFB7L31Y8xqSwA= +github.com/go-chi/chi/v5 v5.0.11/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= @@ -61,29 +66,32 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/google/cel-go v0.18.2 h1:L0B6sNBSVmt0OyECi8v6VOS74KOc9W/tLiWKfZABvf4= -github.com/google/cel-go v0.18.2/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg= +github.com/google/cel-go v0.19.0 h1:vVgaZoHPBDd1lXCYGQOh5A06L4EtuIfmqQ/qnSXSKiU= +github.com/google/cel-go v0.19.0/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-containerregistry v0.16.1 h1:rUEt426sR6nyrL3gt+18ibRcvYpKYdpsa5ZW7MA08dQ= -github.com/google/go-containerregistry v0.16.1/go.mod h1:u0qB2l7mvtWVR5kNcbFIhFY1hLbf8eeGapA+vbFDCtQ= +github.com/google/go-containerregistry v0.18.0 h1:ShE7erKNPqRh5ue6Z9DUOlk04WsnFWPO6YGr3OxnfoQ= +github.com/google/go-containerregistry v0.18.0/go.mod h1:u0qB2l7mvtWVR5kNcbFIhFY1hLbf8eeGapA+vbFDCtQ= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= -github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk= -github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= +github.com/google/pprof v0.0.0-20240117000934-35fc243c5815 h1:WzfWbQz/Ze8v6l++GGbGNFZnUShVpP/0xffCPLL+ax8= +github.com/google/pprof v0.0.0-20240117000934-35fc243c5815/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jdx/go-netrc v1.0.0 h1:QbLMLyCZGj0NA8glAhxUpf1zDg6cxnWgMBbjq40W0gQ= github.com/jdx/go-netrc v1.0.0/go.mod h1:Gh9eFQJnoTNIRHXl2j5bJXA1u84hQWJWgGh569zF3v8= -github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= +github.com/jhump/protoreflect v1.15.4 h1:mrwJhfQGGljwvR/jPEocli8KA6G9afbQpH8NY2wORcI= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= -github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= @@ -94,14 +102,18 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -122,21 +134,28 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/tetratelabs/wazero v1.5.0 h1:Yz3fZHivfDiZFUXnWMPUoiW7s8tC1sjdBtlJn08qYa0= -github.com/tetratelabs/wazero v1.5.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A= +github.com/tetratelabs/wazero v1.6.0 h1:z0H1iikCdP8t+q341xqepY4EWvHEw8Es7tlqiVzlP3g= +github.com/tetratelabs/wazero v1.6.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A= github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v1.20.0 h1:vsb/ggIY+hUjD/zCAQHpzTmndPqv/ml2ArbsbfBYTAc= -go.opentelemetry.io/otel v1.20.0/go.mod h1:oUIGj3D77RwJdM6PPZImDpSZGDvkD9fhesHny69JFrs= -go.opentelemetry.io/otel/metric v1.20.0 h1:ZlrO8Hu9+GAhnepmRGhSU7/VkpjrNowxRN9GyKR4wzA= -go.opentelemetry.io/otel/metric v1.20.0/go.mod h1:90DRw3nfK4D7Sm/75yQ00gTJxtkBxX+wu6YaNymbpVM= -go.opentelemetry.io/otel/sdk v1.20.0 h1:5Jf6imeFZlZtKv9Qbo6qt2ZkmWtdWx/wzcCbNUlAWGM= -go.opentelemetry.io/otel/sdk v1.20.0/go.mod h1:rmkSx1cZCm/tn16iWDn1GQbLtsW/LvsdEEFzCSRM6V0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 h1:sv9kVfal0MK0wBMCOGr+HeJm9v803BkJxGrk2au7j08= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw= +go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= +go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 h1:FyjCyI9jVEfqhUh2MoSkmolPjfh5fp2hnV0b0irxH4Q= +go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= +go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= +go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= +go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= go.opentelemetry.io/otel/sdk/metric v1.19.0 h1:EJoTO5qysMsYCa+w4UghwFV/ptQgqSL/8Ni+hx+8i1k= -go.opentelemetry.io/otel/trace v1.20.0 h1:+yxVAPZPbQhbC3OfAkeIVTky6iTFpcr4SiY9om7mXSQ= -go.opentelemetry.io/otel/trace v1.20.0/go.mod h1:HJSK7F/hA5RlzpZ0zKDCHCDHm556LCDtKaAo6JmBFUU= +go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= +go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= +go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= +go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= @@ -147,10 +166,10 @@ go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= -golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o= +golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= @@ -159,24 +178,24 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= -golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= -golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= -golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= @@ -186,20 +205,20 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= -golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= +golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= +golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo= -google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 h1:Jyp0Hsi0bmHXG6k9eATXoYtjd6e2UzZ1SCn/wIupY14= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:oQ5rr10WTTMvP4A36n8JpR1OrO1BEiV4f78CneXZxkA= +google.golang.org/genproto/googleapis/api v0.0.0-20240116215550-a9fa1716bcac h1:OZkkudMUu9LVQMCoRUbI/1p5VCo9BOrlvkqMvWtqa6s= +google.golang.org/genproto/googleapis/api v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:B5xPO//w8qmBDjGReYLpR6UJPnkldGkCSMoH/2vxJeg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac h1:nUQEQmH/csSvFECKYRv6HWEyypysidKl2I6Qpsglq/0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA= +google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.1-0.20231027082548-f4a6c1f6e5c1 h1:fk72uXZyuZiTtW5tgd63jyVK6582lF61nRC/kGv6vCA= -google.golang.org/protobuf v1.31.1-0.20231027082548-f4a6c1f6e5c1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/tools/src/controller-gen/go.mod b/tools/src/controller-gen/go.mod index ebafb3d2757..3140d861c8b 100644 --- a/tools/src/controller-gen/go.mod +++ b/tools/src/controller-gen/go.mod @@ -19,9 +19,9 @@ require ( github.com/spf13/cobra v1.7.0 // indirect github.com/spf13/pflag v1.0.5 // indirect golang.org/x/mod v0.12.0 // indirect - golang.org/x/net v0.14.0 // indirect - golang.org/x/sys v0.11.0 // indirect - golang.org/x/text v0.12.0 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/tools/src/controller-gen/go.sum b/tools/src/controller-gen/go.sum index 0160f5185bf..3443dfb00e1 100644 --- a/tools/src/controller-gen/go.sum +++ b/tools/src/controller-gen/go.sum @@ -5,6 +5,7 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -13,6 +14,7 @@ github.com/gobuffalo/flect v1.0.2/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnD github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -23,7 +25,9 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -35,11 +39,15 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= @@ -53,6 +61,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -66,22 +75,23 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= -golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -94,9 +104,11 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/tools/src/crd-ref-docs/go.mod b/tools/src/crd-ref-docs/go.mod index 6a27606ad34..e2bd19cd67a 100644 --- a/tools/src/crd-ref-docs/go.mod +++ b/tools/src/crd-ref-docs/go.mod @@ -2,15 +2,15 @@ module local go 1.21 -require github.com/elastic/crd-ref-docs v0.0.9 +require github.com/elastic/crd-ref-docs v0.0.10 require ( github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver v1.5.0 // indirect github.com/Masterminds/sprig v2.22.0+incompatible // indirect - github.com/fatih/color v1.14.1 // indirect - github.com/go-logr/logr v1.2.3 // indirect - github.com/gobuffalo/flect v1.0.0 // indirect + github.com/fatih/color v1.15.0 // indirect + github.com/go-logr/logr v1.2.4 // indirect + github.com/gobuffalo/flect v1.0.2 // indirect github.com/goccy/go-yaml v1.11.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/gofuzz v1.2.0 // indirect @@ -28,22 +28,22 @@ require ( github.com/spf13/cobra v1.7.0 // indirect github.com/spf13/pflag v1.0.5 // indirect go.uber.org/atomic v1.10.0 // indirect - go.uber.org/multierr v1.9.0 // indirect + go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.24.0 // indirect - golang.org/x/crypto v0.7.0 // indirect - golang.org/x/mod v0.10.0 // indirect - golang.org/x/net v0.9.0 // indirect - golang.org/x/sys v0.7.0 // indirect - golang.org/x/text v0.9.0 // indirect - golang.org/x/tools v0.8.0 // indirect + golang.org/x/crypto v0.18.0 // indirect + golang.org/x/mod v0.12.0 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/tools v0.12.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/apiextensions-apiserver v0.26.1 // indirect - k8s.io/apimachinery v0.27.1 // indirect - k8s.io/klog/v2 v2.90.1 // indirect - k8s.io/utils v0.0.0-20230209194617-a36077c30491 // indirect - sigs.k8s.io/controller-tools v0.11.4 // indirect + k8s.io/apiextensions-apiserver v0.28.0 // indirect + k8s.io/apimachinery v0.28.0 // indirect + k8s.io/klog/v2 v2.100.1 // indirect + k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect + sigs.k8s.io/controller-tools v0.13.0 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect ) diff --git a/tools/src/crd-ref-docs/go.sum b/tools/src/crd-ref-docs/go.sum index aed658de89f..f42d190d039 100644 --- a/tools/src/crd-ref-docs/go.sum +++ b/tools/src/crd-ref-docs/go.sum @@ -5,28 +5,34 @@ github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF0 github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/elastic/crd-ref-docs v0.0.9 h1:fkkjFPQMIH2U75Ma5AxQkW7NIydxx2tY2uo/A4+xPO0= -github.com/elastic/crd-ref-docs v0.0.9/go.mod h1:k7DCVDJCqaEozDFcnfhTQd/Foxd8Ip18qKNPAgMpzyo= -github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= -github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/elastic/crd-ref-docs v0.0.10 h1:FAc9oCxxY4+rMCLSLtTGrEaPyuxmp3LNlQ+dZfG9Ujc= +github.com/elastic/crd-ref-docs v0.0.10/go.mod h1:zha4djxzWirfx+c4fl/Kmk9Rc7Fv7XBoOi9CL9kne+M= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= -github.com/gobuffalo/flect v1.0.0 h1:eBFmskjXZgAOagiTXJH25Nt5sdFwNRcb8DKZsIsAUQI= -github.com/gobuffalo/flect v1.0.0/go.mod h1:l9V6xSb4BlXwsxEMj3FVEub2nkdQjWhPvD8XTTlHPQc= +github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= +github.com/gobuffalo/flect v1.0.2 h1:eqjPGSo2WmjgY2XlpGwo2NXgL3RucAKo4k4qQMNA5sA= +github.com/gobuffalo/flect v1.0.2/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= github.com/goccy/go-yaml v1.11.0 h1:n7Z+zx8S9f9KgzG6KtQKf+kwqXZlLNR2F6018Dgau54= github.com/goccy/go-yaml v1.11.0/go.mod h1:H+mJrWtjPTJAHvRbV09MCK9xYwODM+wRTVFFTWckfng= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -43,6 +49,7 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -58,9 +65,13 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/gomega v1.27.4 h1:Z2AnStgsdSayCMDiCU42qIz+HLqEPcgiOCXjAU/w+8E= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -74,52 +85,55 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= -go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= -go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= -golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y= -golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= +golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss= +golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -131,6 +145,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= @@ -138,18 +153,19 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI= -k8s.io/apiextensions-apiserver v0.26.1/go.mod h1:AptjOSXDGuE0JICx/Em15PaoO7buLwTs0dGleIHixSM= -k8s.io/apimachinery v0.27.1 h1:EGuZiLI95UQQcClhanryclaQE6xjg1Bts6/L3cD7zyc= -k8s.io/apimachinery v0.27.1/go.mod h1:5ikh59fK3AJ287GUvpUsryoMFtH9zj/ARfWCo3AyXTM= -k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= -k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/utils v0.0.0-20230209194617-a36077c30491 h1:r0BAOLElQnnFhE/ApUsg3iHdVYYPBjNSSOMowRZxxsY= -k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-tools v0.11.4 h1:jqXJ/Xb6yBgbgcBbw1YoC3rC+Bt1XZWiLjj0ZHv/GrU= -sigs.k8s.io/controller-tools v0.11.4/go.mod h1:qcfX7jfcfYD/b7lAhvqAyTbt/px4GpvN88WKLFFv7p8= +k8s.io/apiextensions-apiserver v0.28.0 h1:CszgmBL8CizEnj4sj7/PtLGey6Na3YgWyGCPONv7E9E= +k8s.io/apiextensions-apiserver v0.28.0/go.mod h1:uRdYiwIuu0SyqJKriKmqEN2jThIJPhVmOWETm8ud1VE= +k8s.io/apimachinery v0.28.0 h1:ScHS2AG16UlYWk63r46oU3D5y54T53cVI5mMJwwqFNA= +k8s.io/apimachinery v0.28.0/go.mod h1:X0xh/chESs2hP9koe+SdIAcXWcQ+RM5hy0ZynB+yEvw= +k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= +k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk= +k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/controller-tools v0.13.0 h1:NfrvuZ4bxyolhDBt/rCZhDnx3M2hzlhgo5n3Iv2RykI= +sigs.k8s.io/controller-tools v0.13.0/go.mod h1:5vw3En2NazbejQGCeWKRrE7q4P+CW8/klfVqP8QZkgA= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/tools/src/golangci-lint/go.mod b/tools/src/golangci-lint/go.mod index dfd11cf4b25..2c4f2dd0844 100644 --- a/tools/src/golangci-lint/go.mod +++ b/tools/src/golangci-lint/go.mod @@ -2,7 +2,7 @@ module local go 1.21 -require github.com/golangci/golangci-lint v1.55.2 +require github.com/golangci/golangci-lint v1.56.2 require ( 4d63.com/gocheckcompilerdirectives v1.2.1 // indirect @@ -11,13 +11,13 @@ require ( github.com/Abirdcfly/dupword v0.0.13 // indirect github.com/Antonboom/errname v0.1.12 // indirect github.com/Antonboom/nilnil v0.1.7 // indirect - github.com/Antonboom/testifylint v0.2.3 // indirect + github.com/Antonboom/testifylint v1.1.2 // indirect github.com/BurntSushi/toml v1.3.2 // indirect github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect - github.com/GaijinEntertainment/go-exhaustruct/v3 v3.1.0 // indirect + github.com/GaijinEntertainment/go-exhaustruct/v3 v3.2.0 // indirect github.com/Masterminds/semver v1.5.0 // indirect - github.com/OpenPeeDeeP/depguard/v2 v2.1.0 // indirect - github.com/alecthomas/go-check-sumtype v0.1.3 // indirect + github.com/OpenPeeDeeP/depguard/v2 v2.2.0 // indirect + github.com/alecthomas/go-check-sumtype v0.1.4 // indirect github.com/alexkohler/nakedret/v2 v2.0.2 // indirect github.com/alexkohler/prealloc v1.0.0 // indirect github.com/alingse/asasalint v0.0.11 // indirect @@ -26,40 +26,41 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/bkielbasa/cyclop v1.2.1 // indirect github.com/blizzy78/varnamelen v0.8.0 // indirect - github.com/bombsimon/wsl/v3 v3.4.0 // indirect + github.com/bombsimon/wsl/v4 v4.2.1 // indirect github.com/breml/bidichk v0.2.7 // indirect github.com/breml/errchkjson v0.3.6 // indirect - github.com/butuzov/ireturn v0.2.2 // indirect + github.com/butuzov/ireturn v0.3.0 // indirect github.com/butuzov/mirror v1.1.0 // indirect - github.com/catenacyber/perfsprint v0.2.0 // indirect - github.com/ccojocar/zxcvbn-go v1.0.1 // indirect + github.com/catenacyber/perfsprint v0.6.0 // indirect + github.com/ccojocar/zxcvbn-go v1.0.2 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/charithe/durationcheck v0.0.10 // indirect github.com/chavacava/garif v0.1.0 // indirect github.com/curioswitch/go-reassign v0.2.0 // indirect - github.com/daixiang0/gci v0.11.2 // indirect + github.com/daixiang0/gci v0.12.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/denis-tingaikin/go-header v0.4.3 // indirect github.com/esimonov/ifshort v1.0.4 // indirect - github.com/ettle/strcase v0.1.1 // indirect - github.com/fatih/color v1.15.0 // indirect + github.com/ettle/strcase v0.2.0 // indirect + github.com/fatih/color v1.16.0 // indirect github.com/fatih/structtag v1.2.0 // indirect github.com/firefart/nonamedreturns v1.0.4 // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/ghostiam/protogetter v0.2.3 // indirect - github.com/go-critic/go-critic v0.9.0 // indirect + github.com/ghostiam/protogetter v0.3.4 // indirect + github.com/go-critic/go-critic v0.11.1 // indirect github.com/go-toolsmith/astcast v1.1.0 // indirect github.com/go-toolsmith/astcopy v1.1.0 // indirect - github.com/go-toolsmith/astequal v1.1.0 // indirect + github.com/go-toolsmith/astequal v1.2.0 // indirect github.com/go-toolsmith/astfmt v1.1.0 // indirect github.com/go-toolsmith/astp v1.1.0 // indirect github.com/go-toolsmith/strparse v1.1.0 // indirect github.com/go-toolsmith/typep v1.1.0 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/go-xmlfmt/xmlfmt v1.1.2 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gofrs/flock v0.8.1 // indirect - github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 // indirect github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe // indirect @@ -70,54 +71,54 @@ require ( github.com/golangci/revgrep v0.5.2 // indirect github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 // indirect github.com/google/go-cmp v0.6.0 // indirect - github.com/gordonklaus/ineffassign v0.0.0-20230610083614-0e73809eb601 // indirect + github.com/gordonklaus/ineffassign v0.1.0 // indirect github.com/gostaticanalysis/analysisutil v0.7.1 // indirect github.com/gostaticanalysis/comment v1.4.2 // indirect github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect github.com/gostaticanalysis/nilerr v0.1.1 // indirect - github.com/hashicorp/errwrap v1.0.0 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-version v1.6.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/jgautheron/goconst v1.6.0 // indirect + github.com/jgautheron/goconst v1.7.0 // indirect github.com/jingyugao/rowserrcheck v1.1.1 // indirect github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af // indirect + github.com/jjti/go-spancheck v0.5.2 // indirect github.com/julz/importas v0.1.0 // indirect - github.com/kisielk/errcheck v1.6.3 // indirect + github.com/kisielk/errcheck v1.7.0 // indirect github.com/kisielk/gotool v1.0.0 // indirect github.com/kkHAIKE/contextcheck v1.1.4 // indirect github.com/kulti/thelper v0.6.3 // indirect - github.com/kunwardeep/paralleltest v1.0.8 // indirect + github.com/kunwardeep/paralleltest v1.0.9 // indirect github.com/kyoh86/exportloopref v0.1.11 // indirect github.com/ldez/gomoddirectives v0.2.3 // indirect github.com/ldez/tagliatelle v0.5.0 // indirect github.com/leonklingele/grouper v1.1.1 // indirect github.com/lufeee/execinquery v1.2.1 // indirect - github.com/macabu/inamedparam v0.1.2 // indirect + github.com/macabu/inamedparam v0.1.3 // indirect github.com/magiconair/properties v1.8.6 // indirect github.com/maratori/testableexamples v1.0.0 // indirect github.com/maratori/testpackage v1.1.1 // indirect github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/mbilski/exhaustivestruct v1.2.0 // indirect - github.com/mgechev/revive v1.3.4 // indirect + github.com/mgechev/revive v1.3.7 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/moricho/tparallel v0.3.1 // indirect github.com/nakabonne/nestif v0.3.1 // indirect - github.com/nishanths/exhaustive v0.11.0 // indirect + github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect + github.com/nishanths/exhaustive v0.12.0 // indirect github.com/nishanths/predeclared v0.2.2 // indirect - github.com/nunnatsa/ginkgolinter v0.14.1 // indirect + github.com/nunnatsa/ginkgolinter v0.15.2 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/polyfloyd/go-errorlint v1.4.5 // indirect + github.com/polyfloyd/go-errorlint v1.4.8 // indirect github.com/prometheus/client_golang v1.12.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect @@ -130,8 +131,8 @@ require ( github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect github.com/sanposhiho/wastedassign/v2 v2.0.7 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect - github.com/sashamelentyev/usestdlibvars v1.24.0 // indirect - github.com/securego/gosec/v2 v2.18.2 // indirect + github.com/sashamelentyev/usestdlibvars v1.25.0 // indirect + github.com/securego/gosec/v2 v2.19.0 // indirect github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sivchari/containedctx v1.0.3 // indirect @@ -139,7 +140,7 @@ require ( github.com/sivchari/tenv v1.7.1 // indirect github.com/sonatard/noctx v0.0.2 // indirect github.com/sourcegraph/go-diff v0.7.0 // indirect - github.com/spf13/afero v1.8.2 // indirect + github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.5.0 // indirect github.com/spf13/cobra v1.7.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect @@ -152,38 +153,39 @@ require ( github.com/subosito/gotenv v1.4.1 // indirect github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c // indirect github.com/tdakkota/asciicheck v0.2.0 // indirect - github.com/tetafro/godot v1.4.15 // indirect + github.com/tetafro/godot v1.4.16 // indirect github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 // indirect github.com/timonwong/loggercheck v0.9.4 // indirect github.com/tomarrell/wrapcheck/v2 v2.8.1 // indirect github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect github.com/ultraware/funlen v0.1.0 // indirect - github.com/ultraware/whitespace v0.0.5 // indirect + github.com/ultraware/whitespace v0.1.0 // indirect github.com/uudashr/gocognit v1.1.2 // indirect github.com/xen0n/gosmopolitan v1.2.2 // indirect github.com/yagipy/maintidx v1.0.0 // indirect github.com/yeya24/promlinter v0.2.0 // indirect - github.com/ykadowak/zerologlint v0.1.3 // indirect + github.com/ykadowak/zerologlint v0.1.5 // indirect gitlab.com/bosi/decorder v0.4.1 // indirect - go-simpler.org/sloglint v0.1.2 // indirect - go.tmz.dev/musttag v0.7.2 // indirect + go-simpler.org/musttag v0.8.0 // indirect + go-simpler.org/sloglint v0.4.0 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.24.0 // indirect - golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea // indirect - golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833 // indirect - golang.org/x/mod v0.13.0 // indirect - golang.org/x/sync v0.4.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect - golang.org/x/tools v0.14.0 // indirect - google.golang.org/protobuf v1.28.0 // indirect + golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc // indirect + golang.org/x/exp/typeparams v0.0.0-20231219180239-dc181d75b848 // indirect + golang.org/x/mod v0.15.0 // indirect + golang.org/x/sync v0.6.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/tools v0.18.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect + gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect honnef.co/go/tools v0.4.6 // indirect - mvdan.cc/gofumpt v0.5.0 // indirect + mvdan.cc/gofumpt v0.6.0 // indirect mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect - mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d // indirect + mvdan.cc/unparam v0.0.0-20240104100049-c549a3470d14 // indirect ) diff --git a/tools/src/golangci-lint/go.sum b/tools/src/golangci-lint/go.sum index 8c0d284fc64..d73330ba3aa 100644 --- a/tools/src/golangci-lint/go.sum +++ b/tools/src/golangci-lint/go.sum @@ -7,7 +7,6 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= @@ -18,9 +17,6 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -38,7 +34,6 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/4meepo/tagalign v1.3.3 h1:ZsOxcwGD/jP4U/aw7qeWu58i7dwYemfy5Y+IF1ACoNw= github.com/4meepo/tagalign v1.3.3/go.mod h1:Q9c1rYMZJc9dPRkbQPpcBNCLEmY2njbAsXhQOZFE2dE= @@ -48,24 +43,24 @@ github.com/Antonboom/errname v0.1.12 h1:oh9ak2zUtsLp5oaEd/erjB4GPu9w19NyoIskZClD github.com/Antonboom/errname v0.1.12/go.mod h1:bK7todrzvlaZoQagP1orKzWXv59X/x0W0Io2XT1Ssro= github.com/Antonboom/nilnil v0.1.7 h1:ofgL+BA7vlA1K2wNQOsHzLJ2Pw5B5DpWRLdDAVvvTow= github.com/Antonboom/nilnil v0.1.7/go.mod h1:TP+ScQWVEq0eSIxqU8CbdT5DFWoHp0MbP+KMUO1BKYQ= -github.com/Antonboom/testifylint v0.2.3 h1:MFq9zyL+rIVpsvLX4vDPLojgN7qODzWsrnftNX2Qh60= -github.com/Antonboom/testifylint v0.2.3/go.mod h1:IYaXaOX9NbfAyO+Y04nfjGI8wDemC1rUyM/cYolz018= +github.com/Antonboom/testifylint v1.1.2 h1:IdLRermiLRogxY5AumBL4sP0A+qKHQM/AP1Xd7XOTKc= +github.com/Antonboom/testifylint v1.1.2/go.mod h1:9PFi+vWa8zzl4/B/kqmFJcw85ZUv8ReyBzuQCd30+WI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/GaijinEntertainment/go-exhaustruct/v3 v3.1.0 h1:3ZBs7LAezy8gh0uECsA6CGU43FF3zsx5f4eah5FxTMA= -github.com/GaijinEntertainment/go-exhaustruct/v3 v3.1.0/go.mod h1:rZLTje5A9kFBe0pzhpe2TdhRniBF++PRHQuRpR8esVc= +github.com/GaijinEntertainment/go-exhaustruct/v3 v3.2.0 h1:sATXp1x6/axKxz2Gjxv8MALP0bXaNRfQinEwyfMcx8c= +github.com/GaijinEntertainment/go-exhaustruct/v3 v3.2.0/go.mod h1:Nl76DrGNJTA1KJ0LePKBw/vznBX1EHbAZX8mwjR82nI= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/OpenPeeDeeP/depguard/v2 v2.1.0 h1:aQl70G173h/GZYhWf36aE5H0KaujXfVMnn/f1kSDVYY= -github.com/OpenPeeDeeP/depguard/v2 v2.1.0/go.mod h1:PUBgk35fX4i7JDmwzlJwJ+GMe6NfO1723wmJMgPThNQ= +github.com/OpenPeeDeeP/depguard/v2 v2.2.0 h1:vDfG60vDtIuf0MEOhmLlLLSzqaRM8EMcgJPdp74zmpA= +github.com/OpenPeeDeeP/depguard/v2 v2.2.0/go.mod h1:CIzddKRvLBC4Au5aYP/i3nyaWQ+ClszLIuVocRiCYFQ= github.com/alecthomas/assert/v2 v2.2.2 h1:Z/iVC0xZfWTaFNE6bA3z07T86hd45Xe2eLt6WVy2bbk= github.com/alecthomas/assert/v2 v2.2.2/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= -github.com/alecthomas/go-check-sumtype v0.1.3 h1:M+tqMxB68hcgccRXBMVCPI4UJ+QUfdSx0xdbypKCqA8= -github.com/alecthomas/go-check-sumtype v0.1.3/go.mod h1:WyYPfhfkdhyrdaligV6svFopZV8Lqdzn5pyVBaV6jhQ= +github.com/alecthomas/go-check-sumtype v0.1.4 h1:WCvlB3l5Vq5dZQTFmodqL2g68uHiSwwlWcT5a2FGK0c= +github.com/alecthomas/go-check-sumtype v0.1.4/go.mod h1:WyYPfhfkdhyrdaligV6svFopZV8Lqdzn5pyVBaV6jhQ= github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk= github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -93,20 +88,20 @@ github.com/bkielbasa/cyclop v1.2.1 h1:AeF71HZDob1P2/pRm1so9cd1alZnrpyc4q2uP2l0gJ github.com/bkielbasa/cyclop v1.2.1/go.mod h1:K/dT/M0FPAiYjBgQGau7tz+3TMh4FWAEqlMhzFWCrgM= github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= -github.com/bombsimon/wsl/v3 v3.4.0 h1:RkSxjT3tmlptwfgEgTgU+KYKLI35p/tviNXNXiL2aNU= -github.com/bombsimon/wsl/v3 v3.4.0/go.mod h1:KkIB+TXkqy6MvK9BDZVbZxKNYsE1/oLRJbIFtf14qqo= +github.com/bombsimon/wsl/v4 v4.2.1 h1:Cxg6u+XDWff75SIFFmNsqnIOgob+Q9hG6y/ioKbRFiM= +github.com/bombsimon/wsl/v4 v4.2.1/go.mod h1:Xu/kDxGZTofQcDGCtQe9KCzhHphIe0fDuyWTxER9Feo= github.com/breml/bidichk v0.2.7 h1:dAkKQPLl/Qrk7hnP6P+E0xOodrq8Us7+U0o4UBOAlQY= github.com/breml/bidichk v0.2.7/go.mod h1:YodjipAGI9fGcYM7II6wFvGhdMYsC5pHDlGzqvEW3tQ= github.com/breml/errchkjson v0.3.6 h1:VLhVkqSBH96AvXEyclMR37rZslRrY2kcyq+31HCsVrA= github.com/breml/errchkjson v0.3.6/go.mod h1:jhSDoFheAF2RSDOlCfhHO9KqhZgAYLyvHe7bRCX8f/U= -github.com/butuzov/ireturn v0.2.2 h1:jWI36dxXwVrI+RnXDwux2IZOewpmfv930OuIRfaBUJ0= -github.com/butuzov/ireturn v0.2.2/go.mod h1:RfGHUvvAuFFxoHKf4Z8Yxuh6OjlCw1KvR2zM1NFHeBk= +github.com/butuzov/ireturn v0.3.0 h1:hTjMqWw3y5JC3kpnC5vXmFJAWI/m31jaCYQqzkS6PL0= +github.com/butuzov/ireturn v0.3.0/go.mod h1:A09nIiwiqzN/IoVo9ogpa0Hzi9fex1kd9PSD6edP5ZA= github.com/butuzov/mirror v1.1.0 h1:ZqX54gBVMXu78QLoiqdwpl2mgmoOJTk7s4p4o+0avZI= github.com/butuzov/mirror v1.1.0/go.mod h1:8Q0BdQU6rC6WILDiBM60DBfvV78OLJmMmixe7GF45AE= -github.com/catenacyber/perfsprint v0.2.0 h1:azOocHLscPjqXVJ7Mf14Zjlkn4uNua0+Hcg1wTR6vUo= -github.com/catenacyber/perfsprint v0.2.0/go.mod h1:/wclWYompEyjUD2FuIIDVKNkqz7IgBIWXIH3V0Zol50= -github.com/ccojocar/zxcvbn-go v1.0.1 h1:+sxrANSCj6CdadkcMnvde/GWU1vZiiXRbqYSCalV4/4= -github.com/ccojocar/zxcvbn-go v1.0.1/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= +github.com/catenacyber/perfsprint v0.6.0 h1:VSv95RRkk5+BxrU/YTPcnxuMEWar1iMK5Vyh3fWcBfs= +github.com/catenacyber/perfsprint v0.6.0/go.mod h1:/wclWYompEyjUD2FuIIDVKNkqz7IgBIWXIH3V0Zol50= +github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg= +github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= @@ -120,13 +115,11 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/curioswitch/go-reassign v0.2.0 h1:G9UZyOcpk/d7Gd6mqYgd8XYWFMw/znxwGDUstnC9DIo= github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc= -github.com/daixiang0/gci v0.11.2 h1:Oji+oPsp3bQ6bNNgX30NBAVT18P4uBH4sRZnlOlTj7Y= -github.com/daixiang0/gci v0.11.2/go.mod h1:xtHP9N7AHdNvtRNfcx9gwTDfw7FRJx4bZUsiEfiNNAI= +github.com/daixiang0/gci v0.12.1 h1:ugsG+KRYny1VK4oqrX4Vtj70bo4akYKa0tgT1DXMYiY= +github.com/daixiang0/gci v0.12.1/go.mod h1:xtHP9N7AHdNvtRNfcx9gwTDfw7FRJx4bZUsiEfiNNAI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -135,29 +128,27 @@ github.com/denis-tingaikin/go-header v0.4.3/go.mod h1:0wOCWuN71D5qIgE2nz9KrKmuYB github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/esimonov/ifshort v1.0.4 h1:6SID4yGWfRae/M7hkVDVVyppy8q/v9OuxNdmjLQStBA= github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcHcfgNWTk0= -github.com/ettle/strcase v0.1.1 h1:htFueZyVeE1XNnMEfbqp5r67qAN/4r6ya1ysq8Q+Zcw= -github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= -github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= -github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/ettle/strcase v0.2.0 h1:fGNiVF21fHXpX1niBgk0aROov1LagYsOwV/xqKDKR/Q= +github.com/ettle/strcase v0.2.0/go.mod h1:DajmHElDSaX76ITe3/VHVyMin4LWSJN5Z909Wp+ED1A= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/firefart/nonamedreturns v1.0.4 h1:abzI1p7mAEPYuR4A+VLKn4eNDOycjYo2phmY9sfv40Y= github.com/firefart/nonamedreturns v1.0.4/go.mod h1:TDhe/tjI1BXo48CmYbUduTV7BdIga8MAO/xbKdcVsGI= -github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= -github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= -github.com/ghostiam/protogetter v0.2.3 h1:qdv2pzo3BpLqezwqfGDLZ+nHEYmc5bUpIdsMbBVwMjw= -github.com/ghostiam/protogetter v0.2.3/go.mod h1:KmNLOsy1v04hKbvZs8EfGI1fk39AgTdRDxWNYPfXVc4= -github.com/go-critic/go-critic v0.9.0 h1:Pmys9qvU3pSML/3GEQ2Xd9RZ/ip+aXHKILuxczKGV/U= -github.com/go-critic/go-critic v0.9.0/go.mod h1:5P8tdXL7m/6qnyG6oRAlYLORvoXH0WDypYgAEmagT40= +github.com/ghostiam/protogetter v0.3.4 h1:5SZ+lZSNmNkSbGVSF9hUHhv/b7ELF9Rwchoq7btYo6c= +github.com/ghostiam/protogetter v0.3.4/go.mod h1:A0JgIhs0fgVnotGinjQiKaFVG3waItLJNwPmcMzDnvk= +github.com/go-critic/go-critic v0.11.1 h1:/zBseUSUMytnRqxjlsYNbDDxpu3R2yH8oLXo/FOE8b8= +github.com/go-critic/go-critic v0.11.1/go.mod h1:aZVQR7+gazH6aDEQx4356SD7d8ez8MipYjXbEl5JAKA= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -167,8 +158,8 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= @@ -177,8 +168,9 @@ github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4 github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s= github.com/go-toolsmith/astcopy v1.1.0/go.mod h1:hXM6gan18VA1T/daUEHCFcYiW8Ai1tIwIzHY6srfEAw= github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= -github.com/go-toolsmith/astequal v1.1.0 h1:kHKm1AWqClYn15R0K1KKE4RG614D46n+nqUQ06E1dTw= github.com/go-toolsmith/astequal v1.1.0/go.mod h1:sedf7VIdCL22LD8qIvv7Nn9MuWJruQA/ysswh64lffQ= +github.com/go-toolsmith/astequal v1.2.0 h1:3Fs3CYZ1k9Vo4FzFhwwewC3CHISHDnVUPC4x0bI2+Cw= +github.com/go-toolsmith/astequal v1.2.0/go.mod h1:c8NZ3+kSFtFY/8lPso4v8LuJjdJiUFVnSuU3s0qrrDY= github.com/go-toolsmith/astfmt v1.1.0 h1:iJVPDPp6/7AaeLJEruMsBUlOYCmvg0MoCfJprsOmcco= github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlNMV634mhwuQ4= github.com/go-toolsmith/astp v1.1.0 h1:dXPuCl6u2llURjdPLLDxJeZInAeZ0/eZwFJmqZMnpQA= @@ -190,6 +182,8 @@ github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQi github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c= +github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-xmlfmt/xmlfmt v1.1.2 h1:Nea7b4icn8s57fTx1M5AI4qQT5HEM3rVUO8MuE6g80U= github.com/go-xmlfmt/xmlfmt v1.1.2/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= @@ -223,8 +217,9 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= @@ -233,8 +228,8 @@ github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe h1:6RGUuS7EGotKx6 github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ= github.com/golangci/gofmt v0.0.0-20231018234816-f50ced29576e h1:ULcKCDV1LOZPFxGZaA6TlQbiM3J2GCPnkx/bGF6sX/g= github.com/golangci/gofmt v0.0.0-20231018234816-f50ced29576e/go.mod h1:Pm5KhLPA8gSnQwrQ6ukebRcapGb/BG9iUkdaiCcGHJM= -github.com/golangci/golangci-lint v1.55.2 h1:yllEIsSJ7MtlDBwDJ9IMBkyEUz2fYE0b5B8IUgO1oP8= -github.com/golangci/golangci-lint v1.55.2/go.mod h1:H60CZ0fuqoTwlTvnbyjhpZPWp7KmsjwV2yupIMiMXbM= +github.com/golangci/golangci-lint v1.56.2 h1:dgQzlWHgNbCqJjuxRJhFEnHDVrrjuTGQHJ3RIZMpp/o= +github.com/golangci/golangci-lint v1.56.2/go.mod h1:7CfNO675+EY7j84jihO4iAqDQ80s3HCjcc5M6B7SlZQ= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= @@ -264,7 +259,6 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -272,18 +266,13 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gordonklaus/ineffassign v0.0.0-20230610083614-0e73809eb601 h1:mrEEilTAUmaAORhssPPkxj84TsHrPMLBGW2Z4SoTxm8= -github.com/gordonklaus/ineffassign v0.0.0-20230610083614-0e73809eb601/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= +github.com/gordonklaus/ineffassign v0.1.0 h1:y2Gd/9I7MdY1oEIt+n+rowjBNDcLQq3RsH5hwJd0f9s= +github.com/gordonklaus/ineffassign v0.1.0/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= @@ -296,10 +285,6 @@ github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= github.com/gostaticanalysis/testutil v0.4.0 h1:nhdCmubdmDF6VEatUNjgUZBJKWRqugoISdUv3PPQgHY= github.com/gostaticanalysis/testutil v0.4.0/go.mod h1:bLIoPefWXrRi/ssLFWX1dx7Repi5x3CuviD3dgAZaBU= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= @@ -310,15 +295,16 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jgautheron/goconst v1.6.0 h1:gbMLWKRMkzAc6kYsQL6/TxaoBUg3Jm9LSF/Ih1ADWGA= -github.com/jgautheron/goconst v1.6.0/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= +github.com/jgautheron/goconst v1.7.0 h1:cEqH+YBKLsECnRSd4F4TK5ri8t/aXtt/qoL0Ft252B0= +github.com/jgautheron/goconst v1.7.0/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af h1:KA9BjwUk7KlCh6S9EAGWBt1oExIUv9WyNCiRz5amv48= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= +github.com/jjti/go-spancheck v0.5.2 h1:WXTZG3efY/ji1Vi8mkH+23O3bLeKR6hp3tI3YB7XwKk= +github.com/jjti/go-spancheck v0.5.2/go.mod h1:ARPNI1JRG1V2Rjnd6/2f2NEfghjSVDZGVmruNKlnXU0= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -330,15 +316,14 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY= github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= -github.com/kisielk/errcheck v1.6.3 h1:dEKh+GLHcWm2oN34nMvDzn1sqI0i0WxPvrgiJA5JuM8= -github.com/kisielk/errcheck v1.6.3/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw= +github.com/kisielk/errcheck v1.7.0 h1:+SbscKmWJ5mOK/bO1zS60F5I9WwZDWOfRsC4RwfwRV0= +github.com/kisielk/errcheck v1.7.0/go.mod h1:1kLL+jV4e+CFfueBmI1dSK2ADDyQnlrnrY/FqKluHJQ= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkHAIKE/contextcheck v1.1.4 h1:B6zAaLhOEEcjvUgIYEqystmnFk1Oemn8bvJhbt0GMb8= github.com/kkHAIKE/contextcheck v1.1.4/go.mod h1:1+i/gWqokIa+dm31mqGLZhZJ7Uh44DJGZVmr6QRBNJg= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -349,8 +334,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= -github.com/kunwardeep/paralleltest v1.0.8 h1:Ul2KsqtzFxTlSU7IP0JusWlLiNqQaloB9vguyjbE558= -github.com/kunwardeep/paralleltest v1.0.8/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY= +github.com/kunwardeep/paralleltest v1.0.9 h1:3Sr2IfFNcsMmlqPk1cjTUbJ4zofKPGyHxenwPebgTug= +github.com/kunwardeep/paralleltest v1.0.9/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY= github.com/kyoh86/exportloopref v0.1.11 h1:1Z0bcmTypkL3Q4k+IDHMWTcnCliEZcaPiIe0/ymEyhQ= github.com/kyoh86/exportloopref v0.1.11/go.mod h1:qkV4UF1zGl6EkF1ox8L5t9SwyeBAZ3qLMd6up458uqA= github.com/ldez/gomoddirectives v0.2.3 h1:y7MBaisZVDYmKvt9/l1mjNCiSA1BVn34U0ObUcJwlhA= @@ -361,8 +346,8 @@ github.com/leonklingele/grouper v1.1.1 h1:suWXRU57D4/Enn6pXR0QVqqWWrnJ9Osrz+5rjt github.com/leonklingele/grouper v1.1.1/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= github.com/lufeee/execinquery v1.2.1 h1:hf0Ems4SHcUGBxpGN7Jz78z1ppVkP/837ZlETPCEtOM= github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM= -github.com/macabu/inamedparam v0.1.2 h1:RR5cnayM6Q7cDhQol32DE2BGAPGMnffJ31LFE+UklaU= -github.com/macabu/inamedparam v0.1.2/go.mod h1:Xg25QvY7IBRl1KLPV9Rbml8JOMZtF/iAkNkmV7eQgjw= +github.com/macabu/inamedparam v0.1.3 h1:2tk/phHkMlEL/1GNe/Yf6kkR/hkcUdAEY3L0hjYV1Mk= +github.com/macabu/inamedparam v0.1.3/go.mod h1:93FLICAIk/quk7eaPPQvbzihUdn/QkGDwIZEoLtpH6I= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= @@ -376,16 +361,16 @@ github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwM github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mbilski/exhaustivestruct v1.2.0 h1:wCBmUnSYufAHO6J4AVWY6ff+oxWxsVFrwgOdMUQePUo= github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= -github.com/mgechev/revive v1.3.4 h1:k/tO3XTaWY4DEHal9tWBkkUMJYO/dLDVyMmAQxmIMDc= -github.com/mgechev/revive v1.3.4/go.mod h1:W+pZCMu9qj8Uhfs1iJMQsEFLRozUfvwFwqVvRbSNLVw= +github.com/mgechev/revive v1.3.7 h1:502QY0vQGe9KtYJ9FpxMz9rL+Fc/P13CI5POL4uHCcE= +github.com/mgechev/revive v1.3.7/go.mod h1:RJ16jUbF0OWC3co/+XTxmFNgEpUPwnnA0BRllX2aDNA= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -403,21 +388,21 @@ github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81 github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nishanths/exhaustive v0.11.0 h1:T3I8nUGhl/Cwu5Z2hfc92l0e04D2GEW6e0l8pzda2l0= -github.com/nishanths/exhaustive v0.11.0/go.mod h1:RqwDsZ1xY0dNdqHho2z6X+bgzizwbLYOWnZbbl2wLB4= +github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhKRf3Swg= +github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7ecevsVDTgc2obs= github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= -github.com/nunnatsa/ginkgolinter v0.14.1 h1:khx0CqR5U4ghsscjJ+lZVthp3zjIFytRXPTaQ/TMiyA= -github.com/nunnatsa/ginkgolinter v0.14.1/go.mod h1:nY0pafUSst7v7F637e7fymaMlQqI9c0Wka2fGsDkzWg= +github.com/nunnatsa/ginkgolinter v0.15.2 h1:N2ORxUxPU56R9gsfLIlVVvCv/V/VVou5qVI1oBKBNHg= +github.com/nunnatsa/ginkgolinter v0.15.2/go.mod h1:oYxE7dt1vZI8cK2rZOs3RgTaBN2vggkqnENmoJ8kVvc= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= -github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= -github.com/onsi/gomega v1.28.1 h1:MijcGUbfYuznzK/5R4CPNoUP/9Xvuo20sXfEm6XxoTA= -github.com/onsi/gomega v1.28.1/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY= +github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM= +github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo= +github.com/onsi/gomega v1.31.1/go.mod h1:y40C95dwAD1Nz36SsEnxvfFe8FFfNxzI5eJ0EYGyAy0= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= -github.com/otiai10/copy v1.11.0 h1:OKBD80J/mLBrwnzXqGtFCzprFSGioo30JcmR4APsNwc= -github.com/otiai10/copy v1.11.0/go.mod h1:rSaLseMUsZFFbsFGc7wCJnnkTAvdc5L6VWxPE4308Ww= +github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= +github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= @@ -430,11 +415,10 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polyfloyd/go-errorlint v1.4.5 h1:70YWmMy4FgRHehGNOUask3HtSFSOLKgmDn7ryNe7LqI= -github.com/polyfloyd/go-errorlint v1.4.5/go.mod h1:sIZEbFoDOCnTYYZoVkjc4hTnM459tuWA9H/EkdXwsKk= +github.com/polyfloyd/go-errorlint v1.4.8 h1:jiEjKDH33ouFktyez7sckv6pHWif9B7SuS8cutDXFHw= +github.com/polyfloyd/go-errorlint v1.4.8/go.mod h1:NNCxFcFjZcw3xNjVdCchERkEM6Oz7wta2XJVxRftwO4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -466,8 +450,8 @@ github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:r github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryancurrah/gomodguard v1.3.0 h1:q15RT/pd6UggBXVBuLps8BXRvl5GPBcwVA7BJHMLuTw= github.com/ryancurrah/gomodguard v1.3.0/go.mod h1:ggBxb3luypPEzqVtq33ee7YSN35V28XeGnid8dnni50= @@ -477,10 +461,10 @@ github.com/sanposhiho/wastedassign/v2 v2.0.7 h1:J+6nrY4VW+gC9xFzUc+XjPD3g3wF3je/ github.com/sanposhiho/wastedassign/v2 v2.0.7/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= -github.com/sashamelentyev/usestdlibvars v1.24.0 h1:MKNzmXtGh5N0y74Z/CIaJh4GlB364l0K1RUT08WSWAc= -github.com/sashamelentyev/usestdlibvars v1.24.0/go.mod h1:9cYkq+gYJ+a5W2RPdhfaSCnTVUC1OQP/bSiiBhq3OZE= -github.com/securego/gosec/v2 v2.18.2 h1:DkDt3wCiOtAHf1XkiXZBhQ6m6mK/b9T/wD257R3/c+I= -github.com/securego/gosec/v2 v2.18.2/go.mod h1:xUuqSF6i0So56Y2wwohWAmB07EdBkUN6crbLlHwbyJs= +github.com/sashamelentyev/usestdlibvars v1.25.0 h1:IK8SI2QyFzy/2OD2PYnhy84dpfNo9qADrRt6LH8vSzU= +github.com/sashamelentyev/usestdlibvars v1.25.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= +github.com/securego/gosec/v2 v2.19.0 h1:gl5xMkOI0/E6Hxx0XCY2XujA3V7SNSefA8sC+3f1gnk= +github.com/securego/gosec/v2 v2.19.0/go.mod h1:hOkDcHz9J/XIgIlPDXalxjeVYsHxoWUc5zJSHxcB8YM= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= @@ -500,8 +484,8 @@ github.com/sonatard/noctx v0.0.2 h1:L7Dz4De2zDQhW8S0t+KUjY0MAQJd6SgVwhzNIc4ok00= github.com/sonatard/noctx v0.0.2/go.mod h1:kzFz+CzWSjQ2OzIm46uJZoXuBpa2+0y3T36U18dWqIo= github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= -github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= -github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= @@ -540,8 +524,8 @@ github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= -github.com/tetafro/godot v1.4.15 h1:QzdIs+XB8q+U1WmQEWKHQbKmCw06QuQM7gLx/dky2RM= -github.com/tetafro/godot v1.4.15/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio= +github.com/tetafro/godot v1.4.16 h1:4ChfhveiNLk4NveAZ9Pu2AN8QZ2nkUGFuadM9lrr5D0= +github.com/tetafro/godot v1.4.16/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio= github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 h1:quvGphlmUVU+nhpFa4gg4yJyTRJ13reZMDHrKwYw53M= github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966/go.mod h1:27bSVNWSBOHm+qRp1T9qzaIpsWEP6TbUnei/43HK+PQ= github.com/timonwong/loggercheck v0.9.4 h1:HKKhqrjcVj8sxL7K77beXh0adEm6DLjV/QOGeMXEVi4= @@ -552,8 +536,8 @@ github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+ github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= github.com/ultraware/funlen v0.1.0 h1:BuqclbkY6pO+cvxoq7OsktIXZpgBSkYTQtmwhAK81vI= github.com/ultraware/funlen v0.1.0/go.mod h1:XJqmOQja6DpxarLj6Jj1U7JuoS8PvL4nEqDaQhy22p4= -github.com/ultraware/whitespace v0.0.5 h1:hh+/cpIcopyMYbZNVov9iSxvJU3OYQg78Sfaqzi/CzI= -github.com/ultraware/whitespace v0.0.5/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= +github.com/ultraware/whitespace v0.1.0 h1:O1HKYoh0kIeqE8sFqZf1o0qbORXUCOQFrlaQyZsczZw= +github.com/ultraware/whitespace v0.1.0/go.mod h1:/se4r3beMFNmewJ4Xmz0nMQ941GJt+qmSHGP9emHYe0= github.com/uudashr/gocognit v1.1.2 h1:l6BAEKJqQH2UpKAPKdMfZf5kE4W/2xk8pfU1OVLvniI= github.com/uudashr/gocognit v1.1.2/go.mod h1:aAVdLURqcanke8h3vg35BC++eseDm66Z7KmchI5et4k= github.com/xen0n/gosmopolitan v1.2.2 h1:/p2KTnMzwRexIW8GlKawsTWOxn7UHA+jCMF/V8HHtvU= @@ -562,8 +546,8 @@ github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= github.com/yeya24/promlinter v0.2.0 h1:xFKDQ82orCU5jQujdaD8stOHiv8UN68BSdn2a8u8Y3o= github.com/yeya24/promlinter v0.2.0/go.mod h1:u54lkmBOZrpEbQQ6gox2zWKKLKu2SGe+2KOiextY+IA= -github.com/ykadowak/zerologlint v0.1.3 h1:TLy1dTW3Nuc+YE3bYRPToG1Q9Ej78b5UUN6bjbGdxPE= -github.com/ykadowak/zerologlint v0.1.3/go.mod h1:KaUskqF3e/v59oPmdq1U1DnKcuHokl2/K1U4pmIELKg= +github.com/ykadowak/zerologlint v0.1.5 h1:Gy/fMz1dFQN9JZTPjv1hxEk+sRWm05row04Yoolgdiw= +github.com/ykadowak/zerologlint v0.1.5/go.mod h1:KaUskqF3e/v59oPmdq1U1DnKcuHokl2/K1U4pmIELKg= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -573,18 +557,17 @@ github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= gitlab.com/bosi/decorder v0.4.1 h1:VdsdfxhstabyhZovHafFw+9eJ6eU0d2CkFNJcZz/NU4= gitlab.com/bosi/decorder v0.4.1/go.mod h1:jecSqWUew6Yle1pCr2eLWTensJMmsxHsBwt+PVbkAqA= -go-simpler.org/assert v0.6.0 h1:QxSrXa4oRuo/1eHMXSBFHKvJIpWABayzKldqZyugG7E= -go-simpler.org/assert v0.6.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= -go-simpler.org/sloglint v0.1.2 h1:IjdhF8NPxyn0Ckn2+fuIof7ntSnVUAqBFcQRrnG9AiM= -go-simpler.org/sloglint v0.1.2/go.mod h1:2LL+QImPfTslD5muNPydAEYmpXIj6o/WYcqnJjLi4o4= +go-simpler.org/assert v0.7.0 h1:OzWWZqfNxt8cLS+MlUp6Tgk1HjPkmgdKBq9qvy8lZsA= +go-simpler.org/assert v0.7.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= +go-simpler.org/musttag v0.8.0 h1:DR4UTgetNNhPRNo02rkK1hwDTRzAPotN+ZqYpdtEwWc= +go-simpler.org/musttag v0.8.0/go.mod h1:fiNdCkXt2S6je9Eblma3okjnlva9NT1Eg/WUt19rWu8= +go-simpler.org/sloglint v0.4.0 h1:UVJuUJo63iNQNFEOtZ6o1xAgagVg/giVLLvG9nNLobI= +go-simpler.org/sloglint v0.4.0/go.mod h1:v6zJ++j/thFPhefs2wEXoCKwT10yo5nkBDYRCXyqgNQ= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.tmz.dev/musttag v0.7.2 h1:1J6S9ipDbalBSODNT5jCep8dhZyMr4ttnjQagmGYR5s= -go.tmz.dev/musttag v0.7.2/go.mod h1:m6q5NiiSKMnQYokefa2xGoyoXnrswCbJ0AWYzf4Zs28= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= @@ -599,9 +582,7 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -613,12 +594,12 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea h1:vLCWI/yYrdEHyN2JzIzPO3aaQJHQdp89IZBA/+azVC4= -golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc h1:ao2WRsKSzW6KuUY9IWPwWahcHCgR0s52IfwutMfEbdM= +golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833 h1:jWGQJV4niP+CCmFW9ekjA9Zx8vYORzOUH2/Nl5WPuLQ= -golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20231219180239-dc181d75b848 h1:UhRVJ0i7bF9n/Hd8YjW3eKjlPVBHzbQdxrBgjbSKl64= +golang.org/x/exp/typeparams v0.0.0-20231219180239-dc181d75b848/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -631,7 +612,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -640,7 +620,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= @@ -649,8 +628,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -680,9 +659,6 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -692,17 +668,13 @@ golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -717,8 +689,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -750,17 +722,12 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -777,8 +744,9 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -790,14 +758,13 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -848,14 +815,8 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= @@ -869,8 +830,8 @@ golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= -golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= +golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -891,16 +852,12 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -930,13 +887,6 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -949,10 +899,6 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -965,8 +911,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -995,14 +941,14 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.4.6 h1:oFEHCKeID7to/3autwsWfnuv69j3NsfcXbvJKuIcep8= honnef.co/go/tools v0.4.6/go.mod h1:+rnGS1THNh8zMwnd2oVOTL9QF6vmfyG6ZXBULae2uc0= -mvdan.cc/gofumpt v0.5.0 h1:0EQ+Z56k8tXjj/6TQD25BFNKQXpCvT0rnansIc7Ug5E= -mvdan.cc/gofumpt v0.5.0/go.mod h1:HBeVDtMKRZpXyxFciAirzdKklDlGu8aAy1wEbH5Y9js= +mvdan.cc/gofumpt v0.6.0 h1:G3QvahNDmpD+Aek/bNOLrFR2XC6ZAdo62dZu65gmwGo= +mvdan.cc/gofumpt v0.6.0/go.mod h1:4L0wf+kgIPZtcCWXynNS2e6bhmj73umwnuXSZarixzA= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= -mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d h1:3rvTIIM22r9pvXk+q3swxUQAQOxksVMGK7sml4nG57w= -mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d/go.mod h1:IeHQjmn6TOD+e4Z3RFiZMMsLVL+A96Nvptar8Fj71is= +mvdan.cc/unparam v0.0.0-20240104100049-c549a3470d14 h1:zCr3iRRgdk5eIikZNDphGcM6KGVTx3Yu+/Uu9Es254w= +mvdan.cc/unparam v0.0.0-20240104100049-c549a3470d14/go.mod h1:ZzZjEpJDOmx8TdVU6umamY3Xy0UAQUI2DHbf05USVbI= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/tools/src/helm-docs/go.mod b/tools/src/helm-docs/go.mod index cc34e66cdf5..d58318f8e50 100644 --- a/tools/src/helm-docs/go.mod +++ b/tools/src/helm-docs/go.mod @@ -30,9 +30,9 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.16.0 // indirect github.com/subosito/gotenv v1.4.2 // indirect - golang.org/x/crypto v0.9.0 // indirect - golang.org/x/sys v0.8.0 // indirect - golang.org/x/text v0.9.0 // indirect + golang.org/x/crypto v0.18.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/text v0.14.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/helm v2.14.3+incompatible // indirect diff --git a/tools/src/helm-docs/go.sum b/tools/src/helm-docs/go.sum index 48bf1a0c9d4..ca28e665b02 100644 --- a/tools/src/helm-docs/go.sum +++ b/tools/src/helm-docs/go.sum @@ -1078,8 +1078,9 @@ golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1343,8 +1344,9 @@ golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1370,8 +1372,9 @@ golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/tools/src/kind/go.mod b/tools/src/kind/go.mod index 160b8d84b52..9ae20babd71 100644 --- a/tools/src/kind/go.mod +++ b/tools/src/kind/go.mod @@ -2,7 +2,7 @@ module github.com/envoyproxy/gateway/tools/src/kind go 1.21 -require sigs.k8s.io/kind v0.20.0 +require sigs.k8s.io/kind v0.22.0 require ( github.com/BurntSushi/toml v1.0.0 // indirect @@ -15,7 +15,7 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/spf13/cobra v1.4.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect + golang.org/x/sys v0.16.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect sigs.k8s.io/yaml v1.3.0 // indirect diff --git a/tools/src/kind/go.sum b/tools/src/kind/go.sum index 97b76db0a65..c910536346b 100644 --- a/tools/src/kind/go.sum +++ b/tools/src/kind/go.sum @@ -29,8 +29,9 @@ github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -38,7 +39,7 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -sigs.k8s.io/kind v0.20.0 h1:f0sc3v9mQbGnjBUaqSFST1dwIuiikKVGgoTwpoP33a8= -sigs.k8s.io/kind v0.20.0/go.mod h1:aBlbxg08cauDgZ612shr017/rZwqd7AS563FvpWKPVs= +sigs.k8s.io/kind v0.22.0 h1:z/+yr/azoOfzsfooqRsPw1wjJlqT/ukXP0ShkHwNlsI= +sigs.k8s.io/kind v0.22.0/go.mod h1:aBlbxg08cauDgZ612shr017/rZwqd7AS563FvpWKPVs= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/tools/src/setup-envtest/go.mod b/tools/src/setup-envtest/go.mod index 7c22047aa6d..dfd3c5e8929 100644 --- a/tools/src/setup-envtest/go.mod +++ b/tools/src/setup-envtest/go.mod @@ -15,8 +15,8 @@ require ( go.uber.org/goleak v1.1.12 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.19.1 // indirect - golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect - golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect - golang.org/x/text v0.3.7 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/text v0.14.0 // indirect google.golang.org/protobuf v1.27.1 // indirect ) diff --git a/tools/src/setup-envtest/go.sum b/tools/src/setup-envtest/go.sum index dccbcd32e80..21852a2c4b5 100644 --- a/tools/src/setup-envtest/go.sum +++ b/tools/src/setup-envtest/go.sum @@ -43,6 +43,7 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= @@ -93,8 +94,8 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -115,14 +116,14 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= diff --git a/tools/src/yamllint/requirements.txt b/tools/src/yamllint/requirements.txt index 5caab9d5754..53d77b343e3 100644 --- a/tools/src/yamllint/requirements.txt +++ b/tools/src/yamllint/requirements.txt @@ -1 +1 @@ -yamllint==1.33.0 +yamllint==1.35.1