diff --git a/.github/dependabot.yml b/.github/dependabot.yml index c7a5bee84ff..938a0fa2c49 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,26 +6,24 @@ version: 2 updates: - package-ecosystem: docker - directory: /tools/docker/envoy-gateway/ - schedule: - interval: weekly - - package-ecosystem: docker - directory: /site + directories: + - /tools/docker/envoy-gateway/ + - /site schedule: interval: weekly - package-ecosystem: github-actions - directory: / + directories: + - / + - /tools/github-actions/setup-deps schedule: interval: weekly ignore: # skip to update retest, because it won't work with the latest version - dependency-name: "envoyproxy/toolshed/gh-actions/retest" - - package-ecosystem: github-actions - directory: /tools/github-actions/setup-deps - schedule: - interval: weekly - package-ecosystem: gomod - directory: / + directories: + - "/" + - "examples/extension-server" schedule: interval: weekly groups: @@ -35,35 +33,22 @@ updates: go.opentelemetry.io: patterns: - "go.opentelemetry.io/*" + golang.org: + patterns: + - "golang.org/*" - package-ecosystem: pip - directory: /tools/src/codespell - schedule: - interval: weekly - - package-ecosystem: gomod - directory: /tools/src/helm-docs - schedule: - interval: weekly - - package-ecosystem: gomod - directory: /tools/src/buf + directories: + - /tools/src/codespell + - /tools/src/sphinx-build + - /tools/src/yamllint schedule: interval: weekly - package-ecosystem: gomod - directory: /tools/src/golangci-lint - schedule: - interval: weekly - - package-ecosystem: gomod - directory: /tools/src/kind - schedule: - interval: weekly - - package-ecosystem: gomod - directory: /tools/src/setup-envtest - schedule: - interval: weekly - - package-ecosystem: pip - directory: /tools/src/sphinx-build - schedule: - interval: weekly - - package-ecosystem: pip - directory: /tools/src/yamllint + directories: + - /tools/src/helm-docs + - /tools/src/buf + - /tools/src/golangci-lint + - /tools/src/kind + - /tools/src/setup-envtest schedule: interval: weekly diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index d3e4cd0a458..5cde7a2c549 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@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15 + uses: github/codeql-action/init@429e1977040da7a23b6822b13c129cd1ba93dbb2 # v3.26.2 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15 + uses: github/codeql-action/autobuild@429e1977040da7a23b6822b13c129cd1ba93dbb2 # v3.26.2 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15 + uses: github/codeql-action/analyze@429e1977040da7a23b6822b13c129cd1ba93dbb2 # v3.26.2 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/license-scan.yml b/.github/workflows/license-scan.yml index 31014adf8a5..68143314ecc 100644 --- a/.github/workflows/license-scan.yml +++ b/.github/workflows/license-scan.yml @@ -18,7 +18,7 @@ jobs: - name: Checkout code uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Run scanner - uses: google/osv-scanner-action/osv-scanner-action@7ac94f9d40028db4cacf8d53adec6626f5d3d2f7 # v1.8.2 + uses: google/osv-scanner-action/osv-scanner-action@c615bb556a9a61495d218c7d439e7c8abbbfb151 # v1.8.3 with: scan-args: |- --skip-git diff --git a/.github/workflows/osv-scanner.yml b/.github/workflows/osv-scanner.yml index 424ff41a189..8e2117a97e1 100644 --- a/.github/workflows/osv-scanner.yml +++ b/.github/workflows/osv-scanner.yml @@ -16,7 +16,7 @@ on: jobs: scan-scheduled: if: ${{ github.event_name == 'push' || github.event_name == 'schedule' }} - uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@7ac94f9d40028db4cacf8d53adec6626f5d3d2f7" # v1.8.2 + uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@c615bb556a9a61495d218c7d439e7c8abbbfb151" # v1.8.3 permissions: actions: read contents: read @@ -32,7 +32,7 @@ jobs: scan-pr: if: ${{ github.event_name == 'pull_request' || github.event_name == 'merge_group' }} - uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable-pr.yml@7ac94f9d40028db4cacf8d53adec6626f5d3d2f7" # v1.8.2 + uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable-pr.yml@c615bb556a9a61495d218c7d439e7c8abbbfb151" # v1.8.3 permissions: actions: read contents: read diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 99a10164ed7..5cb58c15398 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -40,6 +40,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15 + uses: github/codeql-action/upload-sarif@429e1977040da7a23b6822b13c129cd1ba93dbb2 # v3.26.2 with: sarif_file: results.sarif diff --git a/api/v1alpha1/accesslogging_types.go b/api/v1alpha1/accesslogging_types.go index 24272564488..78b78a485d6 100644 --- a/api/v1alpha1/accesslogging_types.go +++ b/api/v1alpha1/accesslogging_types.go @@ -123,15 +123,13 @@ const ( // - `x-accesslog-attr` - JSON encoded key/value pairs when a JSON format is used. // // +kubebuilder:validation:XValidation:rule="self.type == 'HTTP' || !has(self.http)",message="The http field may only be set when type is HTTP." +// +kubebuilder:validation:XValidation:message="BackendRefs must be used, backendRef is not supported.",rule="!has(self.backendRef)" +// +kubebuilder:validation:XValidation:message="must have at least one backend in backendRefs",rule="has(self.backendRefs) && self.backendRefs.size() > 0" +// +kubebuilder:validation:XValidation:message="BackendRefs only supports Service kind.",rule="has(self.backendRefs) ? self.backendRefs.all(f, f.kind == 'Service') : true" +// +kubebuilder:validation:XValidation:message="BackendRefs only supports Core group.",rule="has(self.backendRefs) ? (self.backendRefs.all(f, f.group == \"\")) : true" type ALSEnvoyProxyAccessLog struct { - // BackendRefs references a Kubernetes object that represents the gRPC service to which - // the access logs will be sent. Currently only Service is supported. - // - // +kubebuilder:validation:MinItems=1 - // +kubebuilder:validation:MaxItems=1 - // +kubebuilder:validation:XValidation:message="BackendRefs only supports Service kind.",rule="self.all(f, f.kind == 'Service')" - // +kubebuilder:validation:XValidation:message="BackendRefs only supports Core group.",rule="self.all(f, f.group == '')" - BackendRefs []BackendRef `json:"backendRefs"` + BackendCluster `json:",inline"` + // LogName defines the friendly name of the access log to be returned in // StreamAccessLogsMessage.Identifier. This allows the access log server // to differentiate between different access logs coming from the same Envoy. @@ -167,7 +165,11 @@ type FileEnvoyProxyAccessLog struct { // OpenTelemetryEnvoyProxyAccessLog defines the OpenTelemetry access log sink. // // +kubebuilder:validation:XValidation:message="host or backendRefs needs to be set",rule="has(self.host) || self.backendRefs.size() > 0" +// +kubebuilder:validation:XValidation:message="BackendRefs must be used, backendRef is not supported.",rule="!has(self.backendRef)" +// +kubebuilder:validation:XValidation:message="BackendRefs only supports Service kind.",rule="has(self.backendRefs) ? self.backendRefs.all(f, f.kind == 'Service') : true" +// +kubebuilder:validation:XValidation:message="BackendRefs only supports Core group.",rule="has(self.backendRefs) ? (self.backendRefs.all(f, f.group == \"\")) : true" type OpenTelemetryEnvoyProxyAccessLog struct { + BackendCluster `json:",inline"` // Host define the extension service hostname. // Deprecated: Use BackendRefs instead. // @@ -180,15 +182,6 @@ type OpenTelemetryEnvoyProxyAccessLog struct { // +kubebuilder:validation:Minimum=0 // +kubebuilder:default=4317 Port int32 `json:"port,omitempty"` - // BackendRefs references a Kubernetes object that represents the - // backend server to which the access log will be sent. - // Only Service kind is supported for now. - // - // +optional - // +kubebuilder:validation:MaxItems=1 - // +kubebuilder:validation:XValidation:message="only support Service kind.",rule="self.all(f, f.kind == 'Service')" - // +kubebuilder:validation:XValidation:message="BackendRefs only supports Core group.",rule="self.all(f, f.group == '')" - BackendRefs []BackendRef `json:"backendRefs,omitempty"` // 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/). // +optional diff --git a/api/v1alpha1/backendtrafficpolicy_types.go b/api/v1alpha1/backendtrafficpolicy_types.go index 061748bc3cd..9d15ccd6896 100644 --- a/api/v1alpha1/backendtrafficpolicy_types.go +++ b/api/v1alpha1/backendtrafficpolicy_types.go @@ -45,14 +45,51 @@ type BackendTrafficPolicy struct { // BackendTrafficPolicySpec defines the desired state of BackendTrafficPolicy. type BackendTrafficPolicySpec struct { PolicyTargetReferences `json:",inline"` + ClusterSettings `json:",inline"` // RateLimit allows the user to limit the number of incoming requests // to a predefined value based on attributes within the traffic flow. // +optional RateLimit *RateLimitSpec `json:"rateLimit,omitempty"` + // 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 + // +optional + FaultInjection *FaultInjection `json:"faultInjection,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"` + + // UseClientProtocol configures Envoy to prefer sending requests to backends using + // the same HTTP protocol that the incoming request used. Defaults to false, which means + // that Envoy will use the protocol indicated by the attached BackendRef. + // + // +optional + UseClientProtocol *bool `json:"useClientProtocol,omitempty"` + + // The compression config for the http streams. + // + // +optional + // +notImplementedHide + Compression []*Compression `json:"compression,omitempty"` +} + +// +kubebuilder:object:root=true + +// BackendTrafficPolicyList contains a list of BackendTrafficPolicy resources. +type BackendTrafficPolicyList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []BackendTrafficPolicy `json:"items"` +} + +// ClusterSettings provides the various knobs that can be set to control how traffic to a given +// backend will be configured. +type ClusterSettings struct { // LoadBalancer policy to apply when routing traffic from the gateway to - // the backend endpoints + // the backend endpoints. Defaults to `LeastRequest`. // +optional LoadBalancer *LoadBalancer `json:"loadBalancer,omitempty"` @@ -71,44 +108,22 @@ type BackendTrafficPolicySpec struct { // +optional HealthCheck *HealthCheck `json:"healthCheck,omitempty"` - // 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 - // +optional - FaultInjection *FaultInjection `json:"faultInjection,omitempty"` - // Circuit Breaker settings for the upstream connections and requests. // If not set, circuit breakers will be enabled with the default thresholds // // +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"` - - // UseClientProtocol configures Envoy to prefer sending requests to backends using - // the same HTTP protocol that the incoming request used. Defaults to false, which means - // that Envoy will use the protocol indicated by the attached BackendRef. - // - // +optional - UseClientProtocol *bool `json:"useClientProtocol,omitempty"` - // Timeout settings for the backend connections. // // +optional Timeout *Timeout `json:"timeout,omitempty"` - // The compression config for the http streams. - // - // +optional - // +notImplementedHide - Compression []*Compression `json:"compression,omitempty"` - // Connection includes backend connection settings. // // +optional Connection *BackendConnection `json:"connection,omitempty"` + // DNS includes dns resolution settings. // // +optional @@ -120,15 +135,6 @@ type BackendTrafficPolicySpec struct { HTTP2 *HTTP2Settings `json:"http2,omitempty"` } -// +kubebuilder:object:root=true - -// BackendTrafficPolicyList contains a list of BackendTrafficPolicy resources. -type BackendTrafficPolicyList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []BackendTrafficPolicy `json:"items"` -} - func init() { SchemeBuilder.Register(&BackendTrafficPolicy{}, &BackendTrafficPolicyList{}) } diff --git a/api/v1alpha1/clienttrafficpolicy_types.go b/api/v1alpha1/clienttrafficpolicy_types.go index 347eb946353..63b2c91fb2e 100644 --- a/api/v1alpha1/clienttrafficpolicy_types.go +++ b/api/v1alpha1/clienttrafficpolicy_types.go @@ -7,6 +7,7 @@ package v1alpha1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" ) @@ -134,6 +135,12 @@ type HeaderSettings struct { // // +optional PreserveXRequestID *bool `json:"preserveXRequestID,omitempty"` + + // EarlyRequestHeaders defines settings for early request header modification, before envoy performs + // routing, tracing and built-in header manipulation. + // + // +optional + EarlyRequestHeaders *gwapiv1.HTTPHeaderFilter `json:"earlyRequestHeaders,omitempty"` } // WithUnderscoresAction configures the action to take when an HTTP header with underscores diff --git a/api/v1alpha1/connection_types.go b/api/v1alpha1/connection_types.go index ff24c8edd4d..6f27794748b 100644 --- a/api/v1alpha1/connection_types.go +++ b/api/v1alpha1/connection_types.go @@ -22,7 +22,8 @@ type ClientConnection struct { // Note that when the suffix is not provided, the value is interpreted as bytes. // Default: 32768 bytes. // - // +kubebuilder:validation:XValidation:rule="type(self) == string ? self.matches(r\"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$\") : type(self) == int",message="bufferLimit must be of the format \"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$\"" + // +kubebuilder:validation:XIntOrString + // +kubebuilder:validation:Pattern="^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$" // +optional BufferLimit *resource.Quantity `json:"bufferLimit,omitempty"` // SocketBufferLimit provides configuration for the maximum buffer size in bytes for each incoming socket. @@ -30,7 +31,8 @@ type ClientConnection struct { // For example, 20Mi, 1Gi, 256Ki etc. // Note that when the suffix is not provided, the value is interpreted as bytes. // - // +kubebuilder:validation:XValidation:rule="type(self) == string ? self.matches(r\"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$\") : type(self) == int",message="socketBufferLimit must be of the format \"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$\"" + // +kubebuilder:validation:XIntOrString + // +kubebuilder:validation:Pattern="^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$" // +optional // +notImplementedHide SocketBufferLimit *resource.Quantity `json:"socketBufferLimit,omitempty"` @@ -44,7 +46,8 @@ type BackendConnection struct { // For example, 20Mi, 1Gi, 256Ki etc. // Note: that when the suffix is not provided, the value is interpreted as bytes. // - // +kubebuilder:validation:XValidation:rule="type(self) == string ? self.matches(r\"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$\") : type(self) == int",message="BufferLimit must be of the format \"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$\"" + // +kubebuilder:validation:XIntOrString + // +kubebuilder:validation:Pattern="^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$" // +optional BufferLimit *resource.Quantity `json:"bufferLimit,omitempty"` // SocketBufferLimit provides configuration for the maximum buffer size in bytes for each socket @@ -53,7 +56,8 @@ type BackendConnection struct { // For example, 20Mi, 1Gi, 256Ki etc. // Note that when the suffix is not provided, the value is interpreted as bytes. // - // +kubebuilder:validation:XValidation:rule="type(self) == string ? self.matches(r\"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$\") : type(self) == int",message="socketBufferLimit must be of the format \"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$\"" + // +kubebuilder:validation:XIntOrString + // +kubebuilder:validation:Pattern="^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$" // +optional // +notImplementedHide SocketBufferLimit *resource.Quantity `json:"socketBufferLimit,omitempty"` diff --git a/api/v1alpha1/envoypatchpolicy_types.go b/api/v1alpha1/envoypatchpolicy_types.go index 22effb69756..b23002e678f 100644 --- a/api/v1alpha1/envoypatchpolicy_types.go +++ b/api/v1alpha1/envoypatchpolicy_types.go @@ -111,7 +111,12 @@ type JSONPatchOperation struct { Op JSONPatchOperationType `json:"op"` // 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"` + // +optional + Path *string `json:"path,omitempty"` + // JSONPath specifies the locations of the target document/field where the operation will be performed + // Refer to https://datatracker.ietf.org/doc/rfc9535/ for more details. + // +optional + JSONPath *string `json:"jsonPath,omitempty"` // 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. diff --git a/api/v1alpha1/envoyproxy_metric_types.go b/api/v1alpha1/envoyproxy_metric_types.go index 8791ddbd490..0e571ef23c9 100644 --- a/api/v1alpha1/envoyproxy_metric_types.go +++ b/api/v1alpha1/envoyproxy_metric_types.go @@ -15,6 +15,7 @@ type ProxyMetrics struct { // Prometheus defines the configuration for Admin endpoint `/stats/prometheus`. Prometheus *ProxyPrometheusProvider `json:"prometheus,omitempty"` // Sinks defines the metric sinks where metrics are sent to. + // +kubebuilder:validation:MaxItems=16 Sinks []ProxyMetricSink `json:"sinks,omitempty"` // 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 @@ -54,7 +55,11 @@ type ProxyMetricSink struct { // ProxyOpenTelemetrySink defines the configuration for OpenTelemetry sink. // // +kubebuilder:validation:XValidation:message="host or backendRefs needs to be set",rule="has(self.host) || self.backendRefs.size() > 0" +// +kubebuilder:validation:XValidation:message="BackendRefs must be used, backendRef is not supported.",rule="!has(self.backendRef)" +// +kubebuilder:validation:XValidation:message="only supports Service kind.",rule="has(self.backendRefs) ? self.backendRefs.all(f, f.kind == 'Service') : true" +// +kubebuilder:validation:XValidation:message="BackendRefs only supports Core group.",rule="has(self.backendRefs) ? (self.backendRefs.all(f, f.group == \"\")) : true" type ProxyOpenTelemetrySink struct { + BackendCluster `json:",inline"` // Host define the service hostname. // Deprecated: Use BackendRefs instead. // @@ -68,15 +73,6 @@ type ProxyOpenTelemetrySink struct { // +kubebuilder:validation:Maximum=65535 // +kubebuilder:default=4317 Port int32 `json:"port,omitempty"` - // BackendRefs references a Kubernetes object that represents the - // backend server to which the metric will be sent. - // Only Service kind is supported for now. - // - // +optional - // +kubebuilder:validation:MaxItems=1 - // +kubebuilder:validation:XValidation:message="only support Service kind.",rule="self.all(f, f.kind == 'Service')" - // +kubebuilder:validation:XValidation:message="BackendRefs only supports Core group.",rule="self.all(f, f.group == '')" - BackendRefs []BackendRef `json:"backendRefs,omitempty"` // TODO: add support for customizing OpenTelemetry sink in https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/stat_sinks/open_telemetry/v3/open_telemetry.proto#envoy-v3-api-msg-extensions-stat-sinks-open-telemetry-v3-sinkconfig } diff --git a/api/v1alpha1/envoyproxy_types.go b/api/v1alpha1/envoyproxy_types.go index 910c6d1503a..e2ada31c3fc 100644 --- a/api/v1alpha1/envoyproxy_types.go +++ b/api/v1alpha1/envoyproxy_types.go @@ -112,6 +112,8 @@ type EnvoyProxySpec struct { // // - envoy.filters.http.jwt_authn // + // - envoy.filters.http.stateful_session + // // - envoy.filters.http.ext_proc // // - envoy.filters.http.wasm @@ -172,7 +174,7 @@ type FilterPosition struct { } // EnvoyFilter defines the type of Envoy HTTP filter. -// +kubebuilder:validation:Enum=envoy.filters.http.health_check;envoy.filters.http.fault;envoy.filters.http.cors;envoy.filters.http.ext_authz;envoy.filters.http.basic_auth;envoy.filters.http.oauth2;envoy.filters.http.jwt_authn;envoy.filters.http.ext_proc;envoy.filters.http.wasm;envoy.filters.http.rbac;envoy.filters.http.local_ratelimit;envoy.filters.http.ratelimit +// +kubebuilder:validation:Enum=envoy.filters.http.health_check;envoy.filters.http.fault;envoy.filters.http.cors;envoy.filters.http.ext_authz;envoy.filters.http.basic_auth;envoy.filters.http.oauth2;envoy.filters.http.jwt_authn;envoy.filters.http.stateful_session;envoy.filters.http.ext_proc;envoy.filters.http.wasm;envoy.filters.http.rbac;envoy.filters.http.local_ratelimit;envoy.filters.http.ratelimit type EnvoyFilter string const ( @@ -197,6 +199,9 @@ const ( // EnvoyFilterJWTAuthn defines the Envoy HTTP JWT authentication filter. EnvoyFilterJWTAuthn EnvoyFilter = "envoy.filters.http.jwt_authn" + // EnvoyFilterSessionPersistence defines the Envoy HTTP session persistence filter. + EnvoyFilterSessionPersistence EnvoyFilter = "envoy.filters.http.stateful_session" + // EnvoyFilterExtProc defines the Envoy HTTP external process filter. EnvoyFilterExtProc EnvoyFilter = "envoy.filters.http.ext_proc" diff --git a/api/v1alpha1/ext_auth_types.go b/api/v1alpha1/ext_auth_types.go index 13de5f9f6ac..2ecb8674aad 100644 --- a/api/v1alpha1/ext_auth_types.go +++ b/api/v1alpha1/ext_auth_types.go @@ -5,18 +5,10 @@ package v1alpha1 -import ( - gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" -) - // ExtAuth defines the configuration for External Authorization. // // +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) || !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) || !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) || !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) || !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" type ExtAuth struct { // GRPC defines the gRPC External Authorization service. // Either GRPCService or HTTPService must be specified, @@ -56,45 +48,25 @@ type ExtAuth struct { // The authorization request message is defined in // https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto // +kubebuilder:validation:XValidation:message="backendRef or backendRefs needs to be set",rule="has(self.backendRef) || self.backendRefs.size() > 0" +// +kubebuilder:validation:XValidation:message="BackendRefs must be used, backendRef is not supported.",rule="!has(self.backendRef)" +// +kubebuilder:validation:XValidation:message="Exactly one backendRef can be specified in backendRefs.",rule="has(self.backendRefs) && self.backendRefs.size()==1" +// +kubebuilder:validation:XValidation:message="BackendRefs only supports Service and Backend kind.",rule="has(self.backendRefs) ? self.backendRefs.all(f, f.kind == 'Service' || f.kind == 'Backend') : true" +// +kubebuilder:validation:XValidation:message="BackendRefs only supports Core and gateway.envoyproxy.io group.",rule="has(self.backendRefs) ? (self.backendRefs.all(f, f.group == \"\" || f.group == 'gateway.envoyproxy.io')) : true" 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. - // - // Deprecated: Use BackendRefs instead. - BackendRef *gwapiv1.BackendObjectReference `json:"backendRef,omitempty"` - - // BackendRefs references a Kubernetes object that represents the - // backend server to which the authorization request will be sent. // Only Service kind is supported for now. - // - // +optional - // +kubebuilder:validation:MaxItems=1 - // +kubebuilder:validation:XValidation:message="only support Service kind.",rule="self.all(f, f.kind == 'Service')" - // +kubebuilder:validation:XValidation:message="BackendRefs only supports Core group.",rule="self.all(f, f.group == '')" - BackendRefs []BackendRef `json:"backendRefs,omitempty"` + BackendCluster `json:",inline"` } // HTTPExtAuthService defines the HTTP External Authorization service // // +kubebuilder:validation:XValidation:message="backendRef or backendRefs needs to be set",rule="has(self.backendRef) || self.backendRefs.size() > 0" +// +kubebuilder:validation:XValidation:message="BackendRefs must be used, backendRef is not supported.",rule="!has(self.backendRef)" +// +kubebuilder:validation:XValidation:message="Exactly one backendRef can be specified in backendRefs.",rule="has(self.backendRefs) && self.backendRefs.size()==1" +// +kubebuilder:validation:XValidation:message="BackendRefs only supports Service and Backend kind.",rule="has(self.backendRefs) ? self.backendRefs.all(f, f.kind == 'Service' || f.kind == 'Backend') : true" +// +kubebuilder:validation:XValidation:message="BackendRefs only supports Core and gateway.envoyproxy.io group.",rule="has(self.backendRefs) ? (self.backendRefs.all(f, f.group == \"\" || f.group == 'gateway.envoyproxy.io')) : true" 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. - // - // Deprecated: Use BackendRefs instead. - BackendRef *gwapiv1.BackendObjectReference `json:"backendRef,omitempty"` - - // BackendRefs references a Kubernetes object that represents the - // backend server to which the authorization request will be sent. - // Only Service kind is supported for now. - // - // +optional - // +kubebuilder:validation:MaxItems=1 - // +kubebuilder:validation:XValidation:message="only support Service kind.",rule="self.all(f, f.kind == 'Service')" - // +kubebuilder:validation:XValidation:message="BackendRefs only supports Core group.",rule="self.all(f, f.group == '')" - BackendRefs []BackendRef `json:"backendRefs,omitempty"` + BackendCluster `json:",inline"` // Path is the path of the HTTP External Authorization service. // If path is specified, the authorization request will be sent to that path, diff --git a/api/v1alpha1/ext_proc_types.go b/api/v1alpha1/ext_proc_types.go index 27be5e6318d..9f19d92b48f 100644 --- a/api/v1alpha1/ext_proc_types.go +++ b/api/v1alpha1/ext_proc_types.go @@ -46,14 +46,12 @@ type ExtProcProcessingMode struct { } // ExtProc defines the configuration for External Processing filter. +// +kubebuilder:validation:XValidation:message="BackendRefs must be used, backendRef is not supported.",rule="!has(self.backendRef)" +// +kubebuilder:validation:XValidation:message="Exactly one backendRef can be specified in backendRefs.",rule="has(self.backendRefs) && self.backendRefs.size()==1" +// +kubebuilder:validation:XValidation:message="BackendRefs only supports Service and Backend kind.",rule="has(self.backendRefs) ? self.backendRefs.all(f, f.kind == 'Service' || f.kind == 'Backend') : true" +// +kubebuilder:validation:XValidation:message="BackendRefs only supports Core and gateway.envoyproxy.io group.",rule="has(self.backendRefs) ? (self.backendRefs.all(f, f.group == \"\" || f.group == 'gateway.envoyproxy.io')) : true" type ExtProc struct { - // BackendRefs defines the configuration of the external processing service - // - // +kubebuilder:validation:MinItems=1 - // +kubebuilder:validation:MaxItems=1 - // +kubebuilder:validation:XValidation:message="BackendRefs only supports Service and Backend kind.",rule="self.all(f, f.kind == 'Service' || f.kind == 'Backend')" - // +kubebuilder:validation:XValidation:message="BackendRefs only supports Core and gateway.envoyproxy.io group.",rule="self.all(f, f.group == '' || f.group == 'gateway.envoyproxy.io')" - BackendRefs []BackendRef `json:"backendRefs"` + BackendCluster `json:",inline"` // MessageTimeout is the timeout for a response to be returned from the external processor // Default: 200ms diff --git a/api/v1alpha1/healthcheck_types.go b/api/v1alpha1/healthcheck_types.go index cea83d2f5a1..990c95f141a 100644 --- a/api/v1alpha1/healthcheck_types.go +++ b/api/v1alpha1/healthcheck_types.go @@ -74,6 +74,7 @@ type PassiveHealthCheck struct { // // +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." +// +kubebuilder:validation:XValidation:rule="has(self.grpc) ? self.type == 'GRPC' : true", message="The grpc field can only be set if the Health Checker type is GRPC." type ActiveHealthCheck struct { // Timeout defines the time to wait for a health check response. // @@ -104,7 +105,7 @@ type ActiveHealthCheck struct { HealthyThreshold *uint32 `json:"healthyThreshold"` // Type defines the type of health checker. - // +kubebuilder:validation:Enum=HTTP;TCP + // +kubebuilder:validation:Enum=HTTP;TCP;GRPC // +unionDiscriminator Type ActiveHealthCheckerType `json:"type" yaml:"type"` @@ -117,10 +118,15 @@ type ActiveHealthCheck struct { // It's required while the health checker type is TCP. // +optional TCP *TCPActiveHealthChecker `json:"tcp,omitempty" yaml:"tcp,omitempty"` + + // GRPC defines the configuration of the GRPC health checker. + // It's optional, and can only be used if the specified type is GRPC. + // +optional + GRPC *GRPCActiveHealthChecker `json:"grpc,omitempty" yaml:"grpc,omitempty"` } // ActiveHealthCheckerType is the type of health checker. -// +kubebuilder:validation:Enum=HTTP;TCP +// +kubebuilder:validation:Enum=HTTP;TCP;GRPC type ActiveHealthCheckerType string const ( @@ -128,6 +134,8 @@ const ( ActiveHealthCheckerTypeHTTP ActiveHealthCheckerType = "HTTP" // ActiveHealthCheckerTypeTCP defines the TCP type of health checking. ActiveHealthCheckerTypeTCP ActiveHealthCheckerType = "TCP" + // ActiveHealthCheckerTypeGRPC defines the GRPC type of health checking. + ActiveHealthCheckerTypeGRPC ActiveHealthCheckerType = "GRPC" ) // HTTPActiveHealthChecker defines the settings of http health check. @@ -159,6 +167,15 @@ type TCPActiveHealthChecker struct { Receive *ActiveHealthCheckPayload `json:"receive,omitempty" yaml:"receive,omitempty"` } +// GRPCActiveHealthChecker defines the settings of the GRPC health check. +type GRPCActiveHealthChecker struct { + // Service to send in the health check request. + // If this is not specified, then the health check request applies to the entire + // server and not to a specific service. + // +optional + Service *string `json:"service,omitempty" yaml:"service,omitempty"` +} + // ActiveHealthCheckPayloadType is the type of the payload. // +kubebuilder:validation:Enum=Text;Binary type ActiveHealthCheckPayloadType string diff --git a/api/v1alpha1/shared_types.go b/api/v1alpha1/shared_types.go index c151fcd8b17..ec29fb5f292 100644 --- a/api/v1alpha1/shared_types.go +++ b/api/v1alpha1/shared_types.go @@ -473,6 +473,39 @@ type BackendRef struct { // BackendObjectReference references a Kubernetes object that represents the backend. // Only Service kind is supported for now. gwapiv1.BackendObjectReference `json:",inline"` + // Failover This indicates whether the backend is designated as a failover. + // Multiple failover backends can be configured. + // It is highly recommended to configure active or passive health checks to ensure that failover can be detected + // when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again. + // The overprovisioning factor is set to 1.4, meaning the failover backends will only start receiving traffic when + // the health of the active backends falls below 72%. + // +optional + Failover *bool `json:"failover,omitempty"` +} + +// BackendCluster contains all the configuration required for configuring access +// to a backend. This can include multiple endpoints, and settings that apply for +// managing the connection to all these endpoints. +type BackendCluster struct { + // BackendRef references a Kubernetes object that represents the + // backend server to which the authorization request will be sent. + // + // Deprecated: Use BackendRefs instead. + // +optional + BackendRef *gwapiv1.BackendObjectReference `json:"backendRef,omitempty"` + + // BackendRefs references a Kubernetes object that represents the + // backend server to which the authorization request will be sent. + // + // +kubebuilder:validation:MaxItems=16 + // +optional + BackendRefs []BackendRef `json:"backendRefs,omitempty"` + + // BackendSettings holds configuration for managing the connection + // to the backend. + // + // +optional + BackendSettings *ClusterSettings `json:"backendSettings,omitempty"` } // CIDR defines a CIDR Address range. @@ -492,14 +525,16 @@ type HTTP2Settings struct { // InitialStreamWindowSize sets the initial window size for HTTP/2 streams. // If not set, the default value is 64 KiB(64*1024). // - // +kubebuilder:validation:XValidation:rule="type(self) == string ? self.matches(r\"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$\") : type(self) == int",message="initialStreamWindowSize must be of the format \"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$\"" + // +kubebuilder:validation:XIntOrString + // +kubebuilder:validation:Pattern="^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$" // +optional InitialStreamWindowSize *resource.Quantity `json:"initialStreamWindowSize,omitempty"` // InitialConnectionWindowSize sets the initial window size for HTTP/2 connections. // If not set, the default value is 1 MiB. // - // +kubebuilder:validation:XValidation:rule="type(self) == string ? self.matches(r\"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$\") : type(self) == int",message="initialConnectionWindowSize must be of the format \"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$\"" + // +kubebuilder:validation:XIntOrString + // +kubebuilder:validation:Pattern="^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$" // +optional InitialConnectionWindowSize *resource.Quantity `json:"initialConnectionWindowSize,omitempty"` diff --git a/api/v1alpha1/tracing_types.go b/api/v1alpha1/tracing_types.go index b7be478de15..55fd63ef4e9 100644 --- a/api/v1alpha1/tracing_types.go +++ b/api/v1alpha1/tracing_types.go @@ -31,7 +31,11 @@ const ( // TracingProvider defines the tracing provider configuration. // // +kubebuilder:validation:XValidation:message="host or backendRefs needs to be set",rule="has(self.host) || self.backendRefs.size() > 0" +// +kubebuilder:validation:XValidation:message="BackendRefs must be used, backendRef is not supported.",rule="!has(self.backendRef)" +// +kubebuilder:validation:XValidation:message="only supports Service kind.",rule="has(self.backendRefs) ? self.backendRefs.all(f, f.kind == 'Service') : true" +// +kubebuilder:validation:XValidation:message="BackendRefs only supports Core group.",rule="has(self.backendRefs) ? (self.backendRefs.all(f, f.group == \"\")) : true" type TracingProvider struct { + BackendCluster `json:",inline"` // Type defines the tracing provider type. // +kubebuilder:validation:Enum=OpenTelemetry;Zipkin // +kubebuilder:default=OpenTelemetry @@ -48,15 +52,6 @@ type TracingProvider struct { // +kubebuilder:validation:Minimum=0 // +kubebuilder:default=4317 Port int32 `json:"port,omitempty"` - // BackendRefs references a Kubernetes object that represents the - // backend server to which the trace will be sent. - // Only Service kind is supported for now. - // - // +optional - // +kubebuilder:validation:MaxItems=1 - // +kubebuilder:validation:XValidation:message="only support Service kind.",rule="self.all(f, f.kind == 'Service')" - // +kubebuilder:validation:XValidation:message="BackendRefs only supports Core group.",rule="self.all(f, f.group == '')" - BackendRefs []BackendRef `json:"backendRefs,omitempty"` // Zipkin defines the Zipkin tracing provider configuration // +optional Zipkin *ZipkinTracingProvider `json:"zipkin,omitempty"` diff --git a/api/v1alpha1/validation/envoygateway_validate_test.go b/api/v1alpha1/validation/envoygateway_validate_test.go index 004a5ac8298..7bc6bbf3b23 100644 --- a/api/v1alpha1/validation/envoygateway_validate_test.go +++ b/api/v1alpha1/validation/envoygateway_validate_test.go @@ -662,7 +662,6 @@ func TestValidateEnvoyGateway(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { err := ValidateEnvoyGateway(tc.eg) if !tc.expect { diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 24e03df70c9..1680d26cca4 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -23,13 +23,7 @@ import ( // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ALSEnvoyProxyAccessLog) DeepCopyInto(out *ALSEnvoyProxyAccessLog) { *out = *in - if in.BackendRefs != nil { - in, out := &in.BackendRefs, &out.BackendRefs - *out = make([]BackendRef, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } + in.BackendCluster.DeepCopyInto(&out.BackendCluster) if in.LogName != nil { in, out := &in.LogName, &out.LogName *out = new(string) @@ -115,6 +109,11 @@ func (in *ActiveHealthCheck) DeepCopyInto(out *ActiveHealthCheck) { *out = new(TCPActiveHealthChecker) (*in).DeepCopyInto(*out) } + if in.GRPC != nil { + in, out := &in.GRPC, &out.GRPC + *out = new(GRPCActiveHealthChecker) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveHealthCheck. @@ -252,6 +251,38 @@ func (in *Backend) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendCluster) DeepCopyInto(out *BackendCluster) { + *out = *in + if in.BackendRef != nil { + in, out := &in.BackendRef, &out.BackendRef + *out = new(apisv1.BackendObjectReference) + (*in).DeepCopyInto(*out) + } + if in.BackendRefs != nil { + in, out := &in.BackendRefs, &out.BackendRefs + *out = make([]BackendRef, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.BackendSettings != nil { + in, out := &in.BackendSettings, &out.BackendSettings + *out = new(ClusterSettings) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendCluster. +func (in *BackendCluster) DeepCopy() *BackendCluster { + if in == nil { + return nil + } + out := new(BackendCluster) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackendConnection) DeepCopyInto(out *BackendConnection) { *out = *in @@ -343,6 +374,11 @@ func (in *BackendList) DeepCopyObject() runtime.Object { func (in *BackendRef) DeepCopyInto(out *BackendRef) { *out = *in in.BackendObjectReference.DeepCopyInto(&out.BackendObjectReference) + if in.Failover != nil { + in, out := &in.Failover, &out.Failover + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendRef. @@ -488,41 +524,17 @@ func (in *BackendTrafficPolicyList) DeepCopyObject() runtime.Object { func (in *BackendTrafficPolicySpec) DeepCopyInto(out *BackendTrafficPolicySpec) { *out = *in in.PolicyTargetReferences.DeepCopyInto(&out.PolicyTargetReferences) + in.ClusterSettings.DeepCopyInto(&out.ClusterSettings) if in.RateLimit != nil { in, out := &in.RateLimit, &out.RateLimit *out = new(RateLimitSpec) (*in).DeepCopyInto(*out) } - if in.LoadBalancer != nil { - in, out := &in.LoadBalancer, &out.LoadBalancer - *out = new(LoadBalancer) - (*in).DeepCopyInto(*out) - } - if in.ProxyProtocol != nil { - in, out := &in.ProxyProtocol, &out.ProxyProtocol - *out = new(ProxyProtocol) - **out = **in - } - if in.TCPKeepalive != nil { - in, out := &in.TCPKeepalive, &out.TCPKeepalive - *out = new(TCPKeepalive) - (*in).DeepCopyInto(*out) - } - if in.HealthCheck != nil { - in, out := &in.HealthCheck, &out.HealthCheck - *out = new(HealthCheck) - (*in).DeepCopyInto(*out) - } if in.FaultInjection != nil { in, out := &in.FaultInjection, &out.FaultInjection *out = new(FaultInjection) (*in).DeepCopyInto(*out) } - if in.CircuitBreaker != nil { - in, out := &in.CircuitBreaker, &out.CircuitBreaker - *out = new(CircuitBreaker) - (*in).DeepCopyInto(*out) - } if in.Retry != nil { in, out := &in.Retry, &out.Retry *out = new(Retry) @@ -533,11 +545,6 @@ func (in *BackendTrafficPolicySpec) DeepCopyInto(out *BackendTrafficPolicySpec) *out = new(bool) **out = **in } - 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)) @@ -549,21 +556,6 @@ func (in *BackendTrafficPolicySpec) DeepCopyInto(out *BackendTrafficPolicySpec) } } } - if in.Connection != nil { - in, out := &in.Connection, &out.Connection - *out = new(BackendConnection) - (*in).DeepCopyInto(*out) - } - if in.DNS != nil { - in, out := &in.DNS, &out.DNS - *out = new(DNS) - (*in).DeepCopyInto(*out) - } - if in.HTTP2 != nil { - in, out := &in.HTTP2, &out.HTTP2 - *out = new(HTTP2Settings) - (*in).DeepCopyInto(*out) - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTrafficPolicySpec. @@ -950,6 +942,66 @@ func (in *ClientValidationContext) DeepCopy() *ClientValidationContext { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterSettings) DeepCopyInto(out *ClusterSettings) { + *out = *in + if in.LoadBalancer != nil { + in, out := &in.LoadBalancer, &out.LoadBalancer + *out = new(LoadBalancer) + (*in).DeepCopyInto(*out) + } + if in.ProxyProtocol != nil { + in, out := &in.ProxyProtocol, &out.ProxyProtocol + *out = new(ProxyProtocol) + **out = **in + } + if in.TCPKeepalive != nil { + in, out := &in.TCPKeepalive, &out.TCPKeepalive + *out = new(TCPKeepalive) + (*in).DeepCopyInto(*out) + } + if in.HealthCheck != nil { + in, out := &in.HealthCheck, &out.HealthCheck + *out = new(HealthCheck) + (*in).DeepCopyInto(*out) + } + if in.CircuitBreaker != nil { + in, out := &in.CircuitBreaker, &out.CircuitBreaker + *out = new(CircuitBreaker) + (*in).DeepCopyInto(*out) + } + if in.Timeout != nil { + in, out := &in.Timeout, &out.Timeout + *out = new(Timeout) + (*in).DeepCopyInto(*out) + } + if in.Connection != nil { + in, out := &in.Connection, &out.Connection + *out = new(BackendConnection) + (*in).DeepCopyInto(*out) + } + if in.DNS != nil { + in, out := &in.DNS, &out.DNS + *out = new(DNS) + (*in).DeepCopyInto(*out) + } + if in.HTTP2 != nil { + in, out := &in.HTTP2, &out.HTTP2 + *out = new(HTTP2Settings) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterSettings. +func (in *ClusterSettings) DeepCopy() *ClusterSettings { + if in == nil { + return nil + } + out := new(ClusterSettings) + 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 @@ -1980,13 +2032,7 @@ func (in *ExtAuth) DeepCopy() *ExtAuth { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ExtProc) DeepCopyInto(out *ExtProc) { *out = *in - if in.BackendRefs != nil { - in, out := &in.BackendRefs, &out.BackendRefs - *out = make([]BackendRef, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } + in.BackendCluster.DeepCopyInto(&out.BackendCluster) if in.MessageTimeout != nil { in, out := &in.MessageTimeout, &out.MessageTimeout *out = new(apisv1.Duration) @@ -2282,20 +2328,29 @@ func (in *FilterPosition) DeepCopy() *FilterPosition { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *GRPCExtAuthService) DeepCopyInto(out *GRPCExtAuthService) { +func (in *GRPCActiveHealthChecker) DeepCopyInto(out *GRPCActiveHealthChecker) { *out = *in - if in.BackendRef != nil { - in, out := &in.BackendRef, &out.BackendRef - *out = new(apisv1.BackendObjectReference) - (*in).DeepCopyInto(*out) + if in.Service != nil { + in, out := &in.Service, &out.Service + *out = new(string) + **out = **in } - if in.BackendRefs != nil { - in, out := &in.BackendRefs, &out.BackendRefs - *out = make([]BackendRef, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCActiveHealthChecker. +func (in *GRPCActiveHealthChecker) DeepCopy() *GRPCActiveHealthChecker { + if in == nil { + return nil } + out := new(GRPCActiveHealthChecker) + in.DeepCopyInto(out) + 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.BackendCluster.DeepCopyInto(&out.BackendCluster) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCExtAuthService. @@ -2533,18 +2588,7 @@ func (in *HTTPClientTimeout) DeepCopy() *HTTPClientTimeout { // 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 - if in.BackendRef != nil { - in, out := &in.BackendRef, &out.BackendRef - *out = new(apisv1.BackendObjectReference) - (*in).DeepCopyInto(*out) - } - if in.BackendRefs != nil { - in, out := &in.BackendRefs, &out.BackendRefs - *out = make([]BackendRef, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } + in.BackendCluster.DeepCopyInto(&out.BackendCluster) if in.Path != nil { in, out := &in.Path, &out.Path *out = new(string) @@ -2680,6 +2724,11 @@ func (in *HeaderSettings) DeepCopyInto(out *HeaderSettings) { *out = new(bool) **out = **in } + if in.EarlyRequestHeaders != nil { + in, out := &in.EarlyRequestHeaders, &out.EarlyRequestHeaders + *out = new(apisv1.HTTPHeaderFilter) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HeaderSettings. @@ -2775,6 +2824,16 @@ func (in *ImageWasmCodeSource) DeepCopy() *ImageWasmCodeSource { // 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 + if in.Path != nil { + in, out := &in.Path, &out.Path + *out = new(string) + **out = **in + } + if in.JSONPath != nil { + in, out := &in.JSONPath, &out.JSONPath + *out = new(string) + **out = **in + } if in.From != nil { in, out := &in.From, &out.From *out = new(string) @@ -3512,18 +3571,12 @@ func (in *OIDCProvider) DeepCopy() *OIDCProvider { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OpenTelemetryEnvoyProxyAccessLog) DeepCopyInto(out *OpenTelemetryEnvoyProxyAccessLog) { *out = *in + in.BackendCluster.DeepCopyInto(&out.BackendCluster) if in.Host != nil { in, out := &in.Host, &out.Host *out = new(string) **out = **in } - if in.BackendRefs != nil { - in, out := &in.BackendRefs, &out.BackendRefs - *out = make([]BackendRef, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } if in.Resources != nil { in, out := &in.Resources, &out.Resources *out = make(map[string]string, len(*in)) @@ -3927,18 +3980,12 @@ func (in *ProxyMetrics) DeepCopy() *ProxyMetrics { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProxyOpenTelemetrySink) DeepCopyInto(out *ProxyOpenTelemetrySink) { *out = *in + in.BackendCluster.DeepCopyInto(&out.BackendCluster) if in.Host != nil { in, out := &in.Host, &out.Host *out = new(string) **out = **in } - if in.BackendRefs != nil { - in, out := &in.BackendRefs, &out.BackendRefs - *out = make([]BackendRef, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyOpenTelemetrySink. @@ -4820,18 +4867,12 @@ func (in *Timeout) DeepCopy() *Timeout { // 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 + in.BackendCluster.DeepCopyInto(&out.BackendCluster) if in.Host != nil { in, out := &in.Host, &out.Host *out = new(string) **out = **in } - if in.BackendRefs != nil { - in, out := &in.BackendRefs, &out.BackendRefs - *out = make([]BackendRef, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } if in.Zipkin != nil { in, out := &in.Zipkin, &out.Zipkin *out = new(ZipkinTracingProvider) 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 d94bd0fa0d3..a23e656788b 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -123,6 +123,9 @@ spec: description: Connection includes backend connection settings. properties: bufferLimit: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ anyOf: - type: integer - type: string @@ -132,13 +135,11 @@ spec: If unspecified, an implementation defined default is applied (32768 bytes). For example, 20Mi, 1Gi, 256Ki etc. Note: that when the suffix is not provided, the value is interpreted as bytes. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - x-kubernetes-validations: - - message: BufferLimit must be of the format "^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$" - rule: 'type(self) == string ? self.matches(r"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$") - : type(self) == int' socketBufferLimit: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ anyOf: - type: integer - type: string @@ -148,12 +149,7 @@ spec: SocketBufferLimit applies to socket streaming channel between TCP/IP stacks, it's in kernel space. For example, 20Mi, 1Gi, 256Ki etc. Note that when the suffix is not provided, the value is interpreted as bytes. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - x-kubernetes-validations: - - message: socketBufferLimit must be of the format "^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$" - rule: 'type(self) == string ? self.matches(r"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$") - : type(self) == int' type: object dns: description: DNS includes dns resolution settings. @@ -230,6 +226,18 @@ spec: active: description: Active health check configuration properties: + grpc: + description: |- + GRPC defines the configuration of the GRPC health checker. + It's optional, and can only be used if the specified type is GRPC. + properties: + service: + description: |- + Service to send in the health check request. + If this is not specified, then the health check request applies to the entire + server and not to a specific service. + type: string + type: object healthyThreshold: default: 1 description: HealthyThreshold defines the number of healthy @@ -384,9 +392,11 @@ spec: - enum: - HTTP - TCP + - GRPC - enum: - HTTP - TCP + - GRPC description: Type defines the type of health checker. type: string unhealthyThreshold: @@ -406,6 +416,9 @@ spec: - message: If Health Checker type is TCP, tcp field needs to be set. rule: 'self.type == ''TCP'' ? has(self.tcp) : !has(self.tcp)' + - message: The grpc field can only be set if the Health Checker + type is GRPC. + rule: 'has(self.grpc) ? self.type == ''GRPC'' : true' passive: description: Passive passive check configuration properties: @@ -457,31 +470,27 @@ spec: description: HTTP2 provides HTTP/2 configuration for backend connections. properties: initialConnectionWindowSize: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ anyOf: - type: integer - type: string description: |- InitialConnectionWindowSize sets the initial window size for HTTP/2 connections. If not set, the default value is 1 MiB. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - x-kubernetes-validations: - - message: initialConnectionWindowSize must be of the format "^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$" - rule: 'type(self) == string ? self.matches(r"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$") - : type(self) == int' initialStreamWindowSize: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ anyOf: - type: integer - type: string description: |- InitialStreamWindowSize sets the initial window size for HTTP/2 streams. If not set, the default value is 64 KiB(64*1024). - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - x-kubernetes-validations: - - message: initialStreamWindowSize must be of the format "^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$" - rule: 'type(self) == string ? self.matches(r"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$") - : type(self) == int' maxConcurrentStreams: description: |- MaxConcurrentStreams sets the maximum number of concurrent streams allowed per connection. @@ -501,7 +510,7 @@ spec: loadBalancer: description: |- LoadBalancer policy to apply when routing traffic from the gateway to - the backend endpoints + the backend endpoints. Defaults to `LeastRequest`. properties: consistentHash: description: |- 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 43443bf28cc..5483ff78e64 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml @@ -98,6 +98,9 @@ spec: description: Connection includes client connection settings. properties: bufferLimit: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ anyOf: - type: integer - type: string @@ -107,12 +110,7 @@ spec: For example, 20Mi, 1Gi, 256Ki etc. Note that when the suffix is not provided, the value is interpreted as bytes. Default: 32768 bytes. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - x-kubernetes-validations: - - message: bufferLimit must be of the format "^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$" - rule: 'type(self) == string ? self.matches(r"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$") - : type(self) == int' connectionLimit: description: ConnectionLimit defines limits related to connections properties: @@ -133,6 +131,9 @@ spec: type: integer type: object socketBufferLimit: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ anyOf: - type: integer - type: string @@ -141,12 +142,7 @@ spec: SocketBufferLimit applies to socket streaming channel between TCP/IP stacks, it's in kernel space. For example, 20Mi, 1Gi, 256Ki etc. Note that when the suffix is not provided, the value is interpreted as bytes. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - x-kubernetes-validations: - - message: socketBufferLimit must be of the format "^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$" - rule: 'type(self) == string ? self.matches(r"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$") - : type(self) == int' type: object enableProxyProtocol: description: |- @@ -163,6 +159,148 @@ spec: DisableRateLimitHeaders configures Envoy Proxy to omit the "X-RateLimit-" response headers when rate limiting is enabled. type: boolean + earlyRequestHeaders: + description: |- + EarlyRequestHeaders defines settings for early request header modification, before envoy performs + routing, tracing and built-in header manipulation. + properties: + add: + description: |- + Add adds the given header(s) (name, value) to the request + before the action. It appends to any existing values associated + with the header name. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + add: + - name: "my-header" + value: "bar,baz" + + + Output: + GET /foo HTTP/1.1 + my-header: foo,bar,baz + items: + description: HTTPHeader represents an HTTP Header name and + value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be + matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: |- + Remove the given header(s) from the HTTP request before the action. The + value of Remove is a list of HTTP header names. Note that the header + names are case-insensitive (see + https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + + + Input: + GET /foo HTTP/1.1 + my-header1: foo + my-header2: bar + my-header3: baz + + + Config: + remove: ["my-header1", "my-header3"] + + + Output: + GET /foo HTTP/1.1 + my-header2: bar + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + description: |- + Set overwrites the request with the given header (name, value) + before the action. + + + Input: + GET /foo HTTP/1.1 + my-header: foo + + + Config: + set: + - name: "my-header" + value: "bar" + + + Output: + GET /foo HTTP/1.1 + my-header: bar + items: + description: HTTPHeader represents an HTTP Header name and + value as defined by RFC 7230. + properties: + name: + description: |- + Name is the name of the HTTP Header to be matched. Name matching MUST be + case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + + + If multiple entries specify equivalent header names, the first entry with + an equivalent name MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. Due to the + case-insensitivity of header names, "foo" and "Foo" are considered + equivalent. + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be + matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object enableEnvoyHeaders: description: |- EnableEnvoyHeaders configures Envoy Proxy to add the "X-Envoy-" headers to requests @@ -283,31 +421,27 @@ spec: description: HTTP2 provides HTTP/2 configuration on the listener. properties: initialConnectionWindowSize: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ anyOf: - type: integer - type: string description: |- InitialConnectionWindowSize sets the initial window size for HTTP/2 connections. If not set, the default value is 1 MiB. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - x-kubernetes-validations: - - message: initialConnectionWindowSize must be of the format "^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$" - rule: 'type(self) == string ? self.matches(r"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$") - : type(self) == int' initialStreamWindowSize: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ anyOf: - type: integer - type: string description: |- InitialStreamWindowSize sets the initial window size for HTTP/2 streams. If not set, the default value is 64 KiB(64*1024). - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - x-kubernetes-validations: - - message: initialStreamWindowSize must be of the format "^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$" - rule: 'type(self) == string ? self.matches(r"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$") - : type(self) == int' maxConcurrentStreams: description: |- MaxConcurrentStreams sets the maximum number of concurrent streams allowed per connection. diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml index 61827ee1205..2778aa85a0b 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml @@ -54,13 +54,104 @@ spec: description: ExtProc defines the configuration for External Processing filter. properties: + backendRef: + description: |- + BackendRef references a Kubernetes object that represents the + backend server to which the authorization request will be sent. + + + Deprecated: Use BackendRefs instead. + 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". + + + Defaults to "Service" when not specified. + + + 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. + + + Support: Core (Services with a type other than ExternalName) + + + 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. + + + 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. + + + 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' backendRefs: - description: BackendRefs defines the configuration of the external - processing service + description: |- + BackendRefs references a Kubernetes object that represents the + backend server to which the authorization request will be sent. items: description: BackendRef defines how an ObjectReference that is specific to BackendRef. properties: + failover: + description: |- + Failover This indicates whether the backend is designated as a failover. + Multiple failover backends can be configured. + It is highly recommended to configure active or passive health checks to ensure that failover can be detected + when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again. + The overprovisioning factor is set to 1.4, meaning the failover backends will only start receiving traffic when + the health of the active backends falls below 72%. + type: boolean group: default: "" description: |- @@ -134,15 +225,605 @@ spec: - message: Must have port for Service reference rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' - maxItems: 1 - minItems: 1 + maxItems: 16 type: array - x-kubernetes-validations: - - message: BackendRefs only supports Service and Backend kind. - rule: self.all(f, f.kind == 'Service' || f.kind == 'Backend') - - message: BackendRefs only supports Core and gateway.envoyproxy.io - group. - rule: self.all(f, f.group == '' || f.group == 'gateway.envoyproxy.io') + backendSettings: + description: |- + BackendSettings holds configuration for managing the connection + to the backend. + properties: + circuitBreaker: + description: |- + Circuit Breaker settings for the upstream connections and requests. + If not set, circuit breakers will be enabled with the default thresholds + properties: + maxConnections: + default: 1024 + description: The maximum number of connections that + Envoy will establish to the referenced backend defined + within a xRoute rule. + format: int64 + maximum: 4294967295 + minimum: 0 + type: integer + maxParallelRequests: + default: 1024 + description: The maximum number of parallel requests + that Envoy will make to the referenced backend defined + within a xRoute rule. + format: int64 + maximum: 4294967295 + minimum: 0 + type: integer + maxParallelRetries: + default: 1024 + description: The maximum number of parallel retries + that Envoy will make to the referenced backend defined + within a xRoute rule. + format: int64 + maximum: 4294967295 + minimum: 0 + type: integer + maxPendingRequests: + default: 1024 + description: The maximum number of pending requests + that Envoy will queue to the referenced backend defined + within a xRoute rule. + format: int64 + 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 + connection: + description: Connection includes backend connection settings. + properties: + bufferLimit: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + BufferLimit Soft limit on size of the cluster’s connections read and write buffers. + BufferLimit applies to connection streaming (maybe non-streaming) channel between processes, it's in user space. + If unspecified, an implementation defined default is applied (32768 bytes). + For example, 20Mi, 1Gi, 256Ki etc. + Note: that when the suffix is not provided, the value is interpreted as bytes. + x-kubernetes-int-or-string: true + socketBufferLimit: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + SocketBufferLimit provides configuration for the maximum buffer size in bytes for each socket + to backend. + SocketBufferLimit applies to socket streaming channel between TCP/IP stacks, it's in kernel space. + For example, 20Mi, 1Gi, 256Ki etc. + Note that when the suffix is not provided, the value is interpreted as bytes. + x-kubernetes-int-or-string: true + type: object + dns: + description: DNS includes dns resolution settings. + properties: + dnsRefreshRate: + description: |- + DNSRefreshRate specifies the rate at which DNS records should be refreshed. + Defaults to 30 seconds. + type: string + respectDnsTtl: + description: |- + RespectDNSTTL indicates whether the DNS Time-To-Live (TTL) should be respected. + If the value is set to true, the DNS refresh rate will be set to the resource record’s TTL. + Defaults to true. + type: boolean + type: object + healthCheck: + description: HealthCheck allows gateway to perform active + health checking on backends. + properties: + active: + description: Active health check configuration + properties: + grpc: + description: |- + GRPC defines the configuration of the GRPC health checker. + It's optional, and can only be used if the specified type is GRPC. + properties: + service: + description: |- + Service to send in the health check request. + If this is not specified, then the health check request applies to the entire + server and not to a specific service. + type: string + type: object + 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: + 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 + path: + description: Path defines the HTTP path that + will be requested during health checking. + maxLength: 1024 + minLength: 1 + type: string + required: + - path + type: object + interval: + default: 3s + description: Interval defines the time between active + 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. + 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 + - GRPC + - enum: + - HTTP + - TCP + - GRPC + 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)' + - message: The grpc field can only be set if the Health + Checker type is GRPC. + rule: 'has(self.grpc) ? self.type == ''GRPC'' : true' + passive: + description: Passive passive check configuration + properties: + 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 + type: object + http2: + description: HTTP2 provides HTTP/2 configuration for backend + connections. + properties: + initialConnectionWindowSize: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + InitialConnectionWindowSize sets the initial window size for HTTP/2 connections. + If not set, the default value is 1 MiB. + x-kubernetes-int-or-string: true + initialStreamWindowSize: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + InitialStreamWindowSize sets the initial window size for HTTP/2 streams. + If not set, the default value is 64 KiB(64*1024). + x-kubernetes-int-or-string: true + maxConcurrentStreams: + description: |- + MaxConcurrentStreams sets the maximum number of concurrent streams allowed per connection. + If not set, the default value is 100. + format: int32 + maximum: 2147483647 + minimum: 1 + type: integer + onInvalidMessage: + description: |- + OnInvalidMessage determines if Envoy will terminate the connection or just the offending stream in the event of HTTP messaging error + It's recommended for L2 Envoy deployments to set this value to TerminateStream. + https://www.envoyproxy.io/docs/envoy/latest/configuration/best_practices/level_two + Default: TerminateConnection + type: string + type: object + loadBalancer: + description: |- + LoadBalancer policy to apply when routing traffic from the gateway to + the backend endpoints. Defaults to `LeastRequest`. + properties: + consistentHash: + description: |- + ConsistentHash defines the configuration when the load balancer type is + set to ConsistentHash + properties: + cookie: + description: Cookie configures the cookie hash policy + when the consistent hash type is set to Cookie. + properties: + attributes: + additionalProperties: + type: string + description: Additional Attributes to set for + the generated cookie. + type: object + name: + description: |- + Name of the cookie to hash. + If this cookie does not exist in the request, Envoy will generate a cookie and set + the TTL on the response back to the client based on Layer 4 + attributes of the backend endpoint, to ensure that these future requests + go to the same backend endpoint. Make sure to set the TTL field for this case. + type: string + ttl: + description: |- + TTL of the generated cookie if the cookie is not present. This value sets the + Max-Age attribute value. + type: string + required: + - name + type: object + header: + description: Header configures the header hash policy + when the consistent hash type is set to Header. + properties: + name: + description: Name of the header to hash. + type: string + required: + - name + type: object + tableSize: + default: 65537 + description: The table size for consistent hashing, + must be prime number limited to 5000011. + format: int64 + maximum: 5000011 + minimum: 2 + type: integer + type: + description: |- + ConsistentHashType defines the type of input to hash on. Valid Type values are + "SourceIP", + "Header", + "Cookie". + enum: + - SourceIP + - Header + - Cookie + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: If consistent hash type is header, the header + field must be set. + rule: 'self.type == ''Header'' ? has(self.header) + : !has(self.header)' + - message: If consistent hash type is cookie, the cookie + field must be set. + rule: 'self.type == ''Cookie'' ? has(self.cookie) + : !has(self.cookie)' + slowStart: + description: |- + 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 + properties: + window: + description: |- + 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 + type: string + required: + - window + type: object + type: + description: |- + Type decides the type of Load Balancer policy. + Valid LoadBalancerType values are + "ConsistentHash", + "LeastRequest", + "Random", + "RoundRobin". + enum: + - ConsistentHash + - LeastRequest + - Random + - RoundRobin + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: If LoadBalancer type is consistentHash, consistentHash + field needs to be set. + rule: 'self.type == ''ConsistentHash'' ? has(self.consistentHash) + : !has(self.consistentHash)' + - message: Currently SlowStart is only supported for RoundRobin + and LeastRequest load balancers. + rule: 'self.type in [''Random'', ''ConsistentHash''] ? + !has(self.slowStart) : true ' + proxyProtocol: + description: ProxyProtocol enables the Proxy Protocol when + communicating with the backend. + properties: + version: + description: |- + Version of ProxyProtol + Valid ProxyProtocolVersion values are + "V1" + "V2" + enum: + - V1 + - V2 + type: string + required: + - version + type: object + tcpKeepalive: + description: |- + TcpKeepalive settings associated with the upstream client connection. + Disabled by default. + properties: + idleTime: + description: |- + The duration a connection needs to be idle before keep-alive + probes start being sent. + The duration format is + Defaults to `7200s`. + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + interval: + description: |- + The duration between keep-alive probes. + Defaults to `75s`. + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + probes: + description: |- + The total number of unacknowledged probes to send before deciding + the connection is dead. + Defaults to 9. + 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 + type: object failOpen: description: |- FailOpen defines if requests or responses that cannot be processed due to connectivity to the @@ -187,9 +868,19 @@ spec: type: string type: object type: object - required: - - backendRefs type: object + x-kubernetes-validations: + - message: BackendRefs must be used, backendRef is not supported. + rule: '!has(self.backendRef)' + - message: Exactly one backendRef can be specified in backendRefs. + rule: has(self.backendRefs) && self.backendRefs.size()==1 + - message: BackendRefs only supports Service and Backend kind. + rule: 'has(self.backendRefs) ? self.backendRefs.all(f, f.kind + == ''Service'' || f.kind == ''Backend'') : true' + - message: BackendRefs only supports Core and gateway.envoyproxy.io + group. + rule: 'has(self.backendRefs) ? (self.backendRefs.all(f, f.group + == "" || f.group == ''gateway.envoyproxy.io'')) : true' maxItems: 16 type: array targetRef: 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 e385b0d4bb0..f57a644066f 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoypatchpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoypatchpolicies.yaml @@ -71,6 +71,11 @@ spec: for move or copy operations Refer to https://datatracker.ietf.org/doc/html/rfc6901 for more details. type: string + jsonPath: + description: |- + JSONPath specifies the locations of the target document/field where the operation will be performed + Refer to https://datatracker.ietf.org/doc/rfc9535/ for more details. + type: string op: description: Op is the type of operation to perform enum: @@ -93,7 +98,6 @@ spec: x-kubernetes-preserve-unknown-fields: true required: - op - - path type: object type: description: Type is the typed URL of the Envoy xDS Resource 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 74438fea24c..82865b93d50 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -251,6 +251,9 @@ spec: - envoy.filters.http.jwt_authn + - envoy.filters.http.stateful_session + + - envoy.filters.http.ext_proc @@ -286,6 +289,7 @@ spec: - envoy.filters.http.basic_auth - envoy.filters.http.oauth2 - envoy.filters.http.jwt_authn + - envoy.filters.http.stateful_session - envoy.filters.http.ext_proc - envoy.filters.http.wasm - envoy.filters.http.rbac @@ -304,6 +308,7 @@ spec: - envoy.filters.http.basic_auth - envoy.filters.http.oauth2 - envoy.filters.http.jwt_authn + - envoy.filters.http.stateful_session - envoy.filters.http.ext_proc - envoy.filters.http.wasm - envoy.filters.http.rbac @@ -320,6 +325,7 @@ spec: - envoy.filters.http.basic_auth - envoy.filters.http.oauth2 - envoy.filters.http.jwt_authn + - envoy.filters.http.stateful_session - envoy.filters.http.ext_proc - envoy.filters.http.wasm - envoy.filters.http.rbac @@ -10303,14 +10309,104 @@ spec: description: ALS defines the gRPC Access Log Service (ALS) sink. properties: + backendRef: + description: |- + BackendRef references a Kubernetes object that represents the + backend server to which the authorization request will be sent. + + + Deprecated: Use BackendRefs instead. + 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". + + + Defaults to "Service" when not specified. + + + 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. + + + Support: Core (Services with a type other than ExternalName) + + + 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. + + + 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. + + + 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' backendRefs: description: |- - BackendRefs references a Kubernetes object that represents the gRPC service to which - the access logs will be sent. Currently only Service is supported. + BackendRefs references a Kubernetes object that represents the + backend server to which the authorization request will be sent. items: description: BackendRef defines how an ObjectReference that is specific to BackendRef. properties: + failover: + description: |- + Failover This indicates whether the backend is designated as a failover. + Multiple failover backends can be configured. + It is highly recommended to configure active or passive health checks to ensure that failover can be detected + when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again. + The overprovisioning factor is set to 1.4, meaning the failover backends will only start receiving traffic when + the health of the active backends falls below 72%. + type: boolean group: default: "" description: |- @@ -10385,16 +10481,661 @@ spec: - message: Must have port for Service reference rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' - maxItems: 1 - minItems: 1 + maxItems: 16 type: array - x-kubernetes-validations: - - message: BackendRefs only supports Service - kind. - rule: self.all(f, f.kind == 'Service') - - message: BackendRefs only supports Core - group. - rule: self.all(f, f.group == '') + backendSettings: + description: |- + BackendSettings holds configuration for managing the connection + to the backend. + properties: + circuitBreaker: + description: |- + Circuit Breaker settings for the upstream connections and requests. + If not set, circuit breakers will be enabled with the default thresholds + properties: + maxConnections: + default: 1024 + description: The maximum number of + connections that Envoy will establish + to the referenced backend defined + within a xRoute rule. + format: int64 + maximum: 4294967295 + minimum: 0 + type: integer + maxParallelRequests: + default: 1024 + description: The maximum number of + parallel requests that Envoy will + make to the referenced backend defined + within a xRoute rule. + format: int64 + maximum: 4294967295 + minimum: 0 + type: integer + maxParallelRetries: + default: 1024 + description: The maximum number of + parallel retries that Envoy will + make to the referenced backend defined + within a xRoute rule. + format: int64 + maximum: 4294967295 + minimum: 0 + type: integer + maxPendingRequests: + default: 1024 + description: The maximum number of + pending requests that Envoy will + queue to the referenced backend + defined within a xRoute rule. + format: int64 + 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 + connection: + description: Connection includes backend + connection settings. + properties: + bufferLimit: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + BufferLimit Soft limit on size of the cluster’s connections read and write buffers. + BufferLimit applies to connection streaming (maybe non-streaming) channel between processes, it's in user space. + If unspecified, an implementation defined default is applied (32768 bytes). + For example, 20Mi, 1Gi, 256Ki etc. + Note: that when the suffix is not provided, the value is interpreted as bytes. + x-kubernetes-int-or-string: true + socketBufferLimit: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + SocketBufferLimit provides configuration for the maximum buffer size in bytes for each socket + to backend. + SocketBufferLimit applies to socket streaming channel between TCP/IP stacks, it's in kernel space. + For example, 20Mi, 1Gi, 256Ki etc. + Note that when the suffix is not provided, the value is interpreted as bytes. + x-kubernetes-int-or-string: true + type: object + dns: + description: DNS includes dns resolution + settings. + properties: + dnsRefreshRate: + description: |- + DNSRefreshRate specifies the rate at which DNS records should be refreshed. + Defaults to 30 seconds. + type: string + respectDnsTtl: + description: |- + RespectDNSTTL indicates whether the DNS Time-To-Live (TTL) should be respected. + If the value is set to true, the DNS refresh rate will be set to the resource record’s TTL. + Defaults to true. + type: boolean + type: object + healthCheck: + description: HealthCheck allows gateway + to perform active health checking on + backends. + properties: + active: + description: Active health check configuration + properties: + grpc: + description: |- + GRPC defines the configuration of the GRPC health checker. + It's optional, and can only be used if the specified type is GRPC. + properties: + service: + description: |- + Service to send in the health check request. + If this is not specified, then the health check request applies to the entire + server and not to a specific service. + type: string + type: object + 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: + 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 + path: + description: Path defines + the HTTP path that will + be requested during health + checking. + maxLength: 1024 + minLength: 1 + type: string + required: + - path + type: object + interval: + default: 3s + description: Interval defines + the time between active 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. + 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 + - GRPC + - enum: + - HTTP + - TCP + - GRPC + 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)' + - message: The grpc field can only + be set if the Health Checker type + is GRPC. + rule: 'has(self.grpc) ? self.type + == ''GRPC'' : true' + passive: + description: Passive passive check + configuration + properties: + 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 + type: object + http2: + description: HTTP2 provides HTTP/2 configuration + for backend connections. + properties: + initialConnectionWindowSize: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + InitialConnectionWindowSize sets the initial window size for HTTP/2 connections. + If not set, the default value is 1 MiB. + x-kubernetes-int-or-string: true + initialStreamWindowSize: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + InitialStreamWindowSize sets the initial window size for HTTP/2 streams. + If not set, the default value is 64 KiB(64*1024). + x-kubernetes-int-or-string: true + maxConcurrentStreams: + description: |- + MaxConcurrentStreams sets the maximum number of concurrent streams allowed per connection. + If not set, the default value is 100. + format: int32 + maximum: 2147483647 + minimum: 1 + type: integer + onInvalidMessage: + description: |- + OnInvalidMessage determines if Envoy will terminate the connection or just the offending stream in the event of HTTP messaging error + It's recommended for L2 Envoy deployments to set this value to TerminateStream. + https://www.envoyproxy.io/docs/envoy/latest/configuration/best_practices/level_two + Default: TerminateConnection + type: string + type: object + loadBalancer: + description: |- + LoadBalancer policy to apply when routing traffic from the gateway to + the backend endpoints. Defaults to `LeastRequest`. + properties: + consistentHash: + description: |- + ConsistentHash defines the configuration when the load balancer type is + set to ConsistentHash + properties: + cookie: + description: Cookie configures + the cookie hash policy when + the consistent hash type is + set to Cookie. + properties: + attributes: + additionalProperties: + type: string + description: Additional Attributes + to set for the generated + cookie. + type: object + name: + description: |- + Name of the cookie to hash. + If this cookie does not exist in the request, Envoy will generate a cookie and set + the TTL on the response back to the client based on Layer 4 + attributes of the backend endpoint, to ensure that these future requests + go to the same backend endpoint. Make sure to set the TTL field for this case. + type: string + ttl: + description: |- + TTL of the generated cookie if the cookie is not present. This value sets the + Max-Age attribute value. + type: string + required: + - name + type: object + header: + description: Header configures + the header hash policy when + the consistent hash type is + set to Header. + properties: + name: + description: Name of the header + to hash. + type: string + required: + - name + type: object + tableSize: + default: 65537 + description: The table size for + consistent hashing, must be + prime number limited to 5000011. + format: int64 + maximum: 5000011 + minimum: 2 + type: integer + type: + description: |- + ConsistentHashType defines the type of input to hash on. Valid Type values are + "SourceIP", + "Header", + "Cookie". + enum: + - SourceIP + - Header + - Cookie + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: If consistent hash type + is header, the header field must + be set. + rule: 'self.type == ''Header'' ? + has(self.header) : !has(self.header)' + - message: If consistent hash type + is cookie, the cookie field must + be set. + rule: 'self.type == ''Cookie'' ? + has(self.cookie) : !has(self.cookie)' + slowStart: + description: |- + 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 + properties: + window: + description: |- + 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 + type: string + required: + - window + type: object + type: + description: |- + Type decides the type of Load Balancer policy. + Valid LoadBalancerType values are + "ConsistentHash", + "LeastRequest", + "Random", + "RoundRobin". + enum: + - ConsistentHash + - LeastRequest + - Random + - RoundRobin + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: If LoadBalancer type is consistentHash, + consistentHash field needs to be set. + rule: 'self.type == ''ConsistentHash'' + ? has(self.consistentHash) : !has(self.consistentHash)' + - message: Currently SlowStart is only + supported for RoundRobin and LeastRequest + load balancers. + rule: 'self.type in [''Random'', ''ConsistentHash''] + ? !has(self.slowStart) : true ' + proxyProtocol: + description: ProxyProtocol enables the + Proxy Protocol when communicating with + the backend. + properties: + version: + description: |- + Version of ProxyProtol + Valid ProxyProtocolVersion values are + "V1" + "V2" + enum: + - V1 + - V2 + type: string + required: + - version + type: object + tcpKeepalive: + description: |- + TcpKeepalive settings associated with the upstream client connection. + Disabled by default. + properties: + idleTime: + description: |- + The duration a connection needs to be idle before keep-alive + probes start being sent. + The duration format is + Defaults to `7200s`. + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + interval: + description: |- + The duration between keep-alive probes. + Defaults to `75s`. + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + probes: + description: |- + The total number of unacknowledged probes to send before deciding + the connection is dead. + Defaults to 9. + 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 + type: object http: description: HTTP defines additional configuration specific to HTTP access logs. @@ -10436,13 +11177,24 @@ spec: - TCP type: string required: - - backendRefs - type type: object x-kubernetes-validations: - message: The http field may only be set when type is HTTP. rule: self.type == 'HTTP' || !has(self.http) + - message: BackendRefs must be used, backendRef + is not supported. + rule: '!has(self.backendRef)' + - message: must have at least one backend in backendRefs + rule: has(self.backendRefs) && self.backendRefs.size() + > 0 + - message: BackendRefs only supports Service kind. + rule: 'has(self.backendRefs) ? self.backendRefs.all(f, + f.kind == ''Service'') : true' + - message: BackendRefs only supports Core group. + rule: 'has(self.backendRefs) ? (self.backendRefs.all(f, + f.group == "")) : true' file: description: File defines the file accesslog sink. properties: @@ -10456,15 +11208,104 @@ spec: description: OpenTelemetry defines the OpenTelemetry accesslog sink. properties: + backendRef: + description: |- + BackendRef references a Kubernetes object that represents the + backend server to which the authorization request will be sent. + + + Deprecated: Use BackendRefs instead. + 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". + + + Defaults to "Service" when not specified. + + + 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. + + + Support: Core (Services with a type other than ExternalName) + + + 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. + + + 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. + + + 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' backendRefs: description: |- BackendRefs references a Kubernetes object that represents the - backend server to which the access log will be sent. - Only Service kind is supported for now. + backend server to which the authorization request will be sent. items: description: BackendRef defines how an ObjectReference that is specific to BackendRef. properties: + failover: + description: |- + Failover This indicates whether the backend is designated as a failover. + Multiple failover backends can be configured. + It is highly recommended to configure active or passive health checks to ensure that failover can be detected + when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again. + The overprovisioning factor is set to 1.4, meaning the failover backends will only start receiving traffic when + the health of the active backends falls below 72%. + type: boolean group: default: "" description: |- @@ -10539,39 +11380,695 @@ spec: - message: Must have port for Service reference rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' - maxItems: 1 + maxItems: 16 type: array - x-kubernetes-validations: - - message: only support Service kind. - rule: self.all(f, f.kind == 'Service') - - message: BackendRefs only supports Core - group. - rule: self.all(f, f.group == '') - host: - description: |- - Host define the extension service hostname. - Deprecated: Use BackendRefs instead. - type: string - port: - default: 4317 - description: |- - Port defines the port the extension service is exposed on. - Deprecated: Use BackendRefs instead. - format: int32 - minimum: 0 - type: integer - resources: - additionalProperties: - type: string + backendSettings: description: |- - 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/). - type: object + BackendSettings holds configuration for managing the connection + to the backend. + properties: + circuitBreaker: + description: |- + Circuit Breaker settings for the upstream connections and requests. + If not set, circuit breakers will be enabled with the default thresholds + properties: + maxConnections: + default: 1024 + description: The maximum number of + connections that Envoy will establish + to the referenced backend defined + within a xRoute rule. + format: int64 + maximum: 4294967295 + minimum: 0 + type: integer + maxParallelRequests: + default: 1024 + description: The maximum number of + parallel requests that Envoy will + make to the referenced backend defined + within a xRoute rule. + format: int64 + maximum: 4294967295 + minimum: 0 + type: integer + maxParallelRetries: + default: 1024 + description: The maximum number of + parallel retries that Envoy will + make to the referenced backend defined + within a xRoute rule. + format: int64 + maximum: 4294967295 + minimum: 0 + type: integer + maxPendingRequests: + default: 1024 + description: The maximum number of + pending requests that Envoy will + queue to the referenced backend + defined within a xRoute rule. + format: int64 + 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 + connection: + description: Connection includes backend + connection settings. + properties: + bufferLimit: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + BufferLimit Soft limit on size of the cluster’s connections read and write buffers. + BufferLimit applies to connection streaming (maybe non-streaming) channel between processes, it's in user space. + If unspecified, an implementation defined default is applied (32768 bytes). + For example, 20Mi, 1Gi, 256Ki etc. + Note: that when the suffix is not provided, the value is interpreted as bytes. + x-kubernetes-int-or-string: true + socketBufferLimit: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + SocketBufferLimit provides configuration for the maximum buffer size in bytes for each socket + to backend. + SocketBufferLimit applies to socket streaming channel between TCP/IP stacks, it's in kernel space. + For example, 20Mi, 1Gi, 256Ki etc. + Note that when the suffix is not provided, the value is interpreted as bytes. + x-kubernetes-int-or-string: true + type: object + dns: + description: DNS includes dns resolution + settings. + properties: + dnsRefreshRate: + description: |- + DNSRefreshRate specifies the rate at which DNS records should be refreshed. + Defaults to 30 seconds. + type: string + respectDnsTtl: + description: |- + RespectDNSTTL indicates whether the DNS Time-To-Live (TTL) should be respected. + If the value is set to true, the DNS refresh rate will be set to the resource record’s TTL. + Defaults to true. + type: boolean + type: object + healthCheck: + description: HealthCheck allows gateway + to perform active health checking on + backends. + properties: + active: + description: Active health check configuration + properties: + grpc: + description: |- + GRPC defines the configuration of the GRPC health checker. + It's optional, and can only be used if the specified type is GRPC. + properties: + service: + description: |- + Service to send in the health check request. + If this is not specified, then the health check request applies to the entire + server and not to a specific service. + type: string + type: object + 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: + 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 + path: + description: Path defines + the HTTP path that will + be requested during health + checking. + maxLength: 1024 + minLength: 1 + type: string + required: + - path + type: object + interval: + default: 3s + description: Interval defines + the time between active 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. + 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 + - GRPC + - enum: + - HTTP + - TCP + - GRPC + 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)' + - message: The grpc field can only + be set if the Health Checker type + is GRPC. + rule: 'has(self.grpc) ? self.type + == ''GRPC'' : true' + passive: + description: Passive passive check + configuration + properties: + 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 + type: object + http2: + description: HTTP2 provides HTTP/2 configuration + for backend connections. + properties: + initialConnectionWindowSize: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + InitialConnectionWindowSize sets the initial window size for HTTP/2 connections. + If not set, the default value is 1 MiB. + x-kubernetes-int-or-string: true + initialStreamWindowSize: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + InitialStreamWindowSize sets the initial window size for HTTP/2 streams. + If not set, the default value is 64 KiB(64*1024). + x-kubernetes-int-or-string: true + maxConcurrentStreams: + description: |- + MaxConcurrentStreams sets the maximum number of concurrent streams allowed per connection. + If not set, the default value is 100. + format: int32 + maximum: 2147483647 + minimum: 1 + type: integer + onInvalidMessage: + description: |- + OnInvalidMessage determines if Envoy will terminate the connection or just the offending stream in the event of HTTP messaging error + It's recommended for L2 Envoy deployments to set this value to TerminateStream. + https://www.envoyproxy.io/docs/envoy/latest/configuration/best_practices/level_two + Default: TerminateConnection + type: string + type: object + loadBalancer: + description: |- + LoadBalancer policy to apply when routing traffic from the gateway to + the backend endpoints. Defaults to `LeastRequest`. + properties: + consistentHash: + description: |- + ConsistentHash defines the configuration when the load balancer type is + set to ConsistentHash + properties: + cookie: + description: Cookie configures + the cookie hash policy when + the consistent hash type is + set to Cookie. + properties: + attributes: + additionalProperties: + type: string + description: Additional Attributes + to set for the generated + cookie. + type: object + name: + description: |- + Name of the cookie to hash. + If this cookie does not exist in the request, Envoy will generate a cookie and set + the TTL on the response back to the client based on Layer 4 + attributes of the backend endpoint, to ensure that these future requests + go to the same backend endpoint. Make sure to set the TTL field for this case. + type: string + ttl: + description: |- + TTL of the generated cookie if the cookie is not present. This value sets the + Max-Age attribute value. + type: string + required: + - name + type: object + header: + description: Header configures + the header hash policy when + the consistent hash type is + set to Header. + properties: + name: + description: Name of the header + to hash. + type: string + required: + - name + type: object + tableSize: + default: 65537 + description: The table size for + consistent hashing, must be + prime number limited to 5000011. + format: int64 + maximum: 5000011 + minimum: 2 + type: integer + type: + description: |- + ConsistentHashType defines the type of input to hash on. Valid Type values are + "SourceIP", + "Header", + "Cookie". + enum: + - SourceIP + - Header + - Cookie + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: If consistent hash type + is header, the header field must + be set. + rule: 'self.type == ''Header'' ? + has(self.header) : !has(self.header)' + - message: If consistent hash type + is cookie, the cookie field must + be set. + rule: 'self.type == ''Cookie'' ? + has(self.cookie) : !has(self.cookie)' + slowStart: + description: |- + 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 + properties: + window: + description: |- + 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 + type: string + required: + - window + type: object + type: + description: |- + Type decides the type of Load Balancer policy. + Valid LoadBalancerType values are + "ConsistentHash", + "LeastRequest", + "Random", + "RoundRobin". + enum: + - ConsistentHash + - LeastRequest + - Random + - RoundRobin + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: If LoadBalancer type is consistentHash, + consistentHash field needs to be set. + rule: 'self.type == ''ConsistentHash'' + ? has(self.consistentHash) : !has(self.consistentHash)' + - message: Currently SlowStart is only + supported for RoundRobin and LeastRequest + load balancers. + rule: 'self.type in [''Random'', ''ConsistentHash''] + ? !has(self.slowStart) : true ' + proxyProtocol: + description: ProxyProtocol enables the + Proxy Protocol when communicating with + the backend. + properties: + version: + description: |- + Version of ProxyProtol + Valid ProxyProtocolVersion values are + "V1" + "V2" + enum: + - V1 + - V2 + type: string + required: + - version + type: object + tcpKeepalive: + description: |- + TcpKeepalive settings associated with the upstream client connection. + Disabled by default. + properties: + idleTime: + description: |- + The duration a connection needs to be idle before keep-alive + probes start being sent. + The duration format is + Defaults to `7200s`. + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + interval: + description: |- + The duration between keep-alive probes. + Defaults to `75s`. + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + probes: + description: |- + The total number of unacknowledged probes to send before deciding + the connection is dead. + Defaults to 9. + 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 + type: object + host: + description: |- + Host define the extension service hostname. + Deprecated: Use BackendRefs instead. + type: string + port: + default: 4317 + description: |- + Port defines the port the extension service is exposed on. + Deprecated: Use BackendRefs instead. + format: int32 + minimum: 0 + type: integer + resources: + additionalProperties: + type: string + description: |- + 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/). + type: object type: object x-kubernetes-validations: - message: host or backendRefs needs to be set rule: has(self.host) || self.backendRefs.size() > 0 + - message: BackendRefs must be used, backendRef + is not supported. + rule: '!has(self.backendRef)' + - message: BackendRefs only supports Service kind. + rule: 'has(self.backendRefs) ? self.backendRefs.all(f, + f.kind == ''Service'') : true' + - message: BackendRefs only supports Core group. + rule: 'has(self.backendRefs) ? (self.backendRefs.all(f, + f.group == "")) : true' type: description: Type defines the type of accesslog sink. @@ -10688,15 +12185,104 @@ spec: OpenTelemetry defines the configuration for OpenTelemetry sink. It's required if the sink type is OpenTelemetry. properties: + backendRef: + description: |- + BackendRef references a Kubernetes object that represents the + backend server to which the authorization request will be sent. + + + Deprecated: Use BackendRefs instead. + 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". + + + Defaults to "Service" when not specified. + + + 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. + + + Support: Core (Services with a type other than ExternalName) + + + 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. + + + 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. + + + 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' backendRefs: description: |- BackendRefs references a Kubernetes object that represents the - backend server to which the metric will be sent. - Only Service kind is supported for now. + backend server to which the authorization request will be sent. items: description: BackendRef defines how an ObjectReference that is specific to BackendRef. properties: + failover: + description: |- + Failover This indicates whether the backend is designated as a failover. + Multiple failover backends can be configured. + It is highly recommended to configure active or passive health checks to ensure that failover can be detected + when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again. + The overprovisioning factor is set to 1.4, meaning the failover backends will only start receiving traffic when + the health of the active backends falls below 72%. + type: boolean group: default: "" description: |- @@ -10770,50 +12356,677 @@ spec: - message: Must have port for Service reference rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' - maxItems: 1 + maxItems: 16 type: array - x-kubernetes-validations: - - message: only support Service kind. - rule: self.all(f, f.kind == 'Service') - - message: BackendRefs only supports Core group. - rule: self.all(f, f.group == '') - host: - description: |- - Host define the service hostname. - Deprecated: Use BackendRefs instead. - type: string - port: - default: 4317 + backendSettings: description: |- - Port defines the port the service is exposed on. - Deprecated: Use BackendRefs instead. - format: int32 - maximum: 65535 - minimum: 0 - type: integer - type: object - x-kubernetes-validations: - - message: host or backendRefs needs to be set - rule: has(self.host) || self.backendRefs.size() > - 0 - type: - default: OpenTelemetry - description: |- - Type defines the metric sink type. - EG currently only supports OpenTelemetry. - enum: - - OpenTelemetry - type: string - required: - - type - type: object - x-kubernetes-validations: - - message: If MetricSink type is OpenTelemetry, openTelemetry - field needs to be set. - rule: 'self.type == ''OpenTelemetry'' ? has(self.openTelemetry) - : !has(self.openTelemetry)' - type: array - type: object + BackendSettings holds configuration for managing the connection + to the backend. + properties: + circuitBreaker: + description: |- + Circuit Breaker settings for the upstream connections and requests. + If not set, circuit breakers will be enabled with the default thresholds + properties: + maxConnections: + default: 1024 + description: The maximum number of connections + that Envoy will establish to the referenced + backend defined within a xRoute rule. + format: int64 + maximum: 4294967295 + minimum: 0 + type: integer + maxParallelRequests: + default: 1024 + description: The maximum number of parallel + requests that Envoy will make to the referenced + backend defined within a xRoute rule. + format: int64 + maximum: 4294967295 + minimum: 0 + type: integer + maxParallelRetries: + default: 1024 + description: The maximum number of parallel + retries that Envoy will make to the referenced + backend defined within a xRoute rule. + format: int64 + maximum: 4294967295 + minimum: 0 + type: integer + maxPendingRequests: + default: 1024 + description: The maximum number of pending + requests that Envoy will queue to the + referenced backend defined within a xRoute + rule. + format: int64 + 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 + connection: + description: Connection includes backend connection + settings. + properties: + bufferLimit: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + BufferLimit Soft limit on size of the cluster’s connections read and write buffers. + BufferLimit applies to connection streaming (maybe non-streaming) channel between processes, it's in user space. + If unspecified, an implementation defined default is applied (32768 bytes). + For example, 20Mi, 1Gi, 256Ki etc. + Note: that when the suffix is not provided, the value is interpreted as bytes. + x-kubernetes-int-or-string: true + socketBufferLimit: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + SocketBufferLimit provides configuration for the maximum buffer size in bytes for each socket + to backend. + SocketBufferLimit applies to socket streaming channel between TCP/IP stacks, it's in kernel space. + For example, 20Mi, 1Gi, 256Ki etc. + Note that when the suffix is not provided, the value is interpreted as bytes. + x-kubernetes-int-or-string: true + type: object + dns: + description: DNS includes dns resolution settings. + properties: + dnsRefreshRate: + description: |- + DNSRefreshRate specifies the rate at which DNS records should be refreshed. + Defaults to 30 seconds. + type: string + respectDnsTtl: + description: |- + RespectDNSTTL indicates whether the DNS Time-To-Live (TTL) should be respected. + If the value is set to true, the DNS refresh rate will be set to the resource record’s TTL. + Defaults to true. + type: boolean + type: object + healthCheck: + description: HealthCheck allows gateway to perform + active health checking on backends. + properties: + active: + description: Active health check configuration + properties: + grpc: + description: |- + GRPC defines the configuration of the GRPC health checker. + It's optional, and can only be used if the specified type is GRPC. + properties: + service: + description: |- + Service to send in the health check request. + If this is not specified, then the health check request applies to the entire + server and not to a specific service. + type: string + type: object + 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: + 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 + path: + description: Path defines the HTTP + path that will be requested during + health checking. + maxLength: 1024 + minLength: 1 + type: string + required: + - path + type: object + interval: + default: 3s + description: Interval defines the time + between active 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. + 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 + - GRPC + - enum: + - HTTP + - TCP + - GRPC + 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)' + - message: The grpc field can only be set + if the Health Checker type is GRPC. + rule: 'has(self.grpc) ? self.type == ''GRPC'' + : true' + passive: + description: Passive passive check configuration + properties: + 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 + type: object + http2: + description: HTTP2 provides HTTP/2 configuration + for backend connections. + properties: + initialConnectionWindowSize: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + InitialConnectionWindowSize sets the initial window size for HTTP/2 connections. + If not set, the default value is 1 MiB. + x-kubernetes-int-or-string: true + initialStreamWindowSize: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + InitialStreamWindowSize sets the initial window size for HTTP/2 streams. + If not set, the default value is 64 KiB(64*1024). + x-kubernetes-int-or-string: true + maxConcurrentStreams: + description: |- + MaxConcurrentStreams sets the maximum number of concurrent streams allowed per connection. + If not set, the default value is 100. + format: int32 + maximum: 2147483647 + minimum: 1 + type: integer + onInvalidMessage: + description: |- + OnInvalidMessage determines if Envoy will terminate the connection or just the offending stream in the event of HTTP messaging error + It's recommended for L2 Envoy deployments to set this value to TerminateStream. + https://www.envoyproxy.io/docs/envoy/latest/configuration/best_practices/level_two + Default: TerminateConnection + type: string + type: object + loadBalancer: + description: |- + LoadBalancer policy to apply when routing traffic from the gateway to + the backend endpoints. Defaults to `LeastRequest`. + properties: + consistentHash: + description: |- + ConsistentHash defines the configuration when the load balancer type is + set to ConsistentHash + properties: + cookie: + description: Cookie configures the cookie + hash policy when the consistent hash + type is set to Cookie. + properties: + attributes: + additionalProperties: + type: string + description: Additional Attributes + to set for the generated cookie. + type: object + name: + description: |- + Name of the cookie to hash. + If this cookie does not exist in the request, Envoy will generate a cookie and set + the TTL on the response back to the client based on Layer 4 + attributes of the backend endpoint, to ensure that these future requests + go to the same backend endpoint. Make sure to set the TTL field for this case. + type: string + ttl: + description: |- + TTL of the generated cookie if the cookie is not present. This value sets the + Max-Age attribute value. + type: string + required: + - name + type: object + header: + description: Header configures the header + hash policy when the consistent hash + type is set to Header. + properties: + name: + description: Name of the header + to hash. + type: string + required: + - name + type: object + tableSize: + default: 65537 + description: The table size for consistent + hashing, must be prime number limited + to 5000011. + format: int64 + maximum: 5000011 + minimum: 2 + type: integer + type: + description: |- + ConsistentHashType defines the type of input to hash on. Valid Type values are + "SourceIP", + "Header", + "Cookie". + enum: + - SourceIP + - Header + - Cookie + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: If consistent hash type is header, + the header field must be set. + rule: 'self.type == ''Header'' ? has(self.header) + : !has(self.header)' + - message: If consistent hash type is cookie, + the cookie field must be set. + rule: 'self.type == ''Cookie'' ? has(self.cookie) + : !has(self.cookie)' + slowStart: + description: |- + 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 + properties: + window: + description: |- + 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 + type: string + required: + - window + type: object + type: + description: |- + Type decides the type of Load Balancer policy. + Valid LoadBalancerType values are + "ConsistentHash", + "LeastRequest", + "Random", + "RoundRobin". + enum: + - ConsistentHash + - LeastRequest + - Random + - RoundRobin + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: If LoadBalancer type is consistentHash, + consistentHash field needs to be set. + rule: 'self.type == ''ConsistentHash'' ? has(self.consistentHash) + : !has(self.consistentHash)' + - message: Currently SlowStart is only supported + for RoundRobin and LeastRequest load balancers. + rule: 'self.type in [''Random'', ''ConsistentHash''] + ? !has(self.slowStart) : true ' + proxyProtocol: + description: ProxyProtocol enables the Proxy + Protocol when communicating with the backend. + properties: + version: + description: |- + Version of ProxyProtol + Valid ProxyProtocolVersion values are + "V1" + "V2" + enum: + - V1 + - V2 + type: string + required: + - version + type: object + tcpKeepalive: + description: |- + TcpKeepalive settings associated with the upstream client connection. + Disabled by default. + properties: + idleTime: + description: |- + The duration a connection needs to be idle before keep-alive + probes start being sent. + The duration format is + Defaults to `7200s`. + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + interval: + description: |- + The duration between keep-alive probes. + Defaults to `75s`. + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + probes: + description: |- + The total number of unacknowledged probes to send before deciding + the connection is dead. + Defaults to 9. + 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 + type: object + host: + description: |- + Host define the service hostname. + Deprecated: Use BackendRefs instead. + type: string + port: + default: 4317 + description: |- + Port defines the port the service is exposed on. + Deprecated: Use BackendRefs instead. + format: int32 + maximum: 65535 + minimum: 0 + type: integer + type: object + x-kubernetes-validations: + - message: host or backendRefs needs to be set + rule: has(self.host) || self.backendRefs.size() > + 0 + - message: BackendRefs must be used, backendRef is not + supported. + rule: '!has(self.backendRef)' + - message: only supports Service kind. + rule: 'has(self.backendRefs) ? self.backendRefs.all(f, + f.kind == ''Service'') : true' + - message: BackendRefs only supports Core group. + rule: 'has(self.backendRefs) ? (self.backendRefs.all(f, + f.group == "")) : true' + type: + default: OpenTelemetry + description: |- + Type defines the metric sink type. + EG currently only supports OpenTelemetry. + enum: + - OpenTelemetry + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: If MetricSink type is OpenTelemetry, openTelemetry + field needs to be set. + rule: 'self.type == ''OpenTelemetry'' ? has(self.openTelemetry) + : !has(self.openTelemetry)' + maxItems: 16 + type: array + type: object tracing: description: |- Tracing defines tracing configuration for managed proxies. @@ -10884,15 +13097,104 @@ spec: provider: description: Provider defines the tracing provider. properties: + backendRef: + description: |- + BackendRef references a Kubernetes object that represents the + backend server to which the authorization request will be sent. + + + Deprecated: Use BackendRefs instead. + 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". + + + Defaults to "Service" when not specified. + + + 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. + + + Support: Core (Services with a type other than ExternalName) + + + 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. + + + 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. + + + 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' backendRefs: description: |- BackendRefs references a Kubernetes object that represents the - backend server to which the trace will be sent. - Only Service kind is supported for now. + backend server to which the authorization request will be sent. items: description: BackendRef defines how an ObjectReference that is specific to BackendRef. properties: + failover: + description: |- + Failover This indicates whether the backend is designated as a failover. + Multiple failover backends can be configured. + It is highly recommended to configure active or passive health checks to ensure that failover can be detected + when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again. + The overprovisioning factor is set to 1.4, meaning the failover backends will only start receiving traffic when + the health of the active backends falls below 72%. + type: boolean group: default: "" description: |- @@ -10966,13 +13268,625 @@ spec: - message: Must have port for Service reference rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' - maxItems: 1 + maxItems: 16 type: array - x-kubernetes-validations: - - message: only support Service kind. - rule: self.all(f, f.kind == 'Service') - - message: BackendRefs only supports Core group. - rule: self.all(f, f.group == '') + backendSettings: + description: |- + BackendSettings holds configuration for managing the connection + to the backend. + properties: + circuitBreaker: + description: |- + Circuit Breaker settings for the upstream connections and requests. + If not set, circuit breakers will be enabled with the default thresholds + properties: + maxConnections: + default: 1024 + description: The maximum number of connections + that Envoy will establish to the referenced + backend defined within a xRoute rule. + format: int64 + maximum: 4294967295 + minimum: 0 + type: integer + maxParallelRequests: + default: 1024 + description: The maximum number of parallel requests + that Envoy will make to the referenced backend + defined within a xRoute rule. + format: int64 + maximum: 4294967295 + minimum: 0 + type: integer + maxParallelRetries: + default: 1024 + description: The maximum number of parallel retries + that Envoy will make to the referenced backend + defined within a xRoute rule. + format: int64 + maximum: 4294967295 + minimum: 0 + type: integer + maxPendingRequests: + default: 1024 + description: The maximum number of pending requests + that Envoy will queue to the referenced backend + defined within a xRoute rule. + format: int64 + 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 + connection: + description: Connection includes backend connection + settings. + properties: + bufferLimit: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + BufferLimit Soft limit on size of the cluster’s connections read and write buffers. + BufferLimit applies to connection streaming (maybe non-streaming) channel between processes, it's in user space. + If unspecified, an implementation defined default is applied (32768 bytes). + For example, 20Mi, 1Gi, 256Ki etc. + Note: that when the suffix is not provided, the value is interpreted as bytes. + x-kubernetes-int-or-string: true + socketBufferLimit: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + SocketBufferLimit provides configuration for the maximum buffer size in bytes for each socket + to backend. + SocketBufferLimit applies to socket streaming channel between TCP/IP stacks, it's in kernel space. + For example, 20Mi, 1Gi, 256Ki etc. + Note that when the suffix is not provided, the value is interpreted as bytes. + x-kubernetes-int-or-string: true + type: object + dns: + description: DNS includes dns resolution settings. + properties: + dnsRefreshRate: + description: |- + DNSRefreshRate specifies the rate at which DNS records should be refreshed. + Defaults to 30 seconds. + type: string + respectDnsTtl: + description: |- + RespectDNSTTL indicates whether the DNS Time-To-Live (TTL) should be respected. + If the value is set to true, the DNS refresh rate will be set to the resource record’s TTL. + Defaults to true. + type: boolean + type: object + healthCheck: + description: HealthCheck allows gateway to perform + active health checking on backends. + properties: + active: + description: Active health check configuration + properties: + grpc: + description: |- + GRPC defines the configuration of the GRPC health checker. + It's optional, and can only be used if the specified type is GRPC. + properties: + service: + description: |- + Service to send in the health check request. + If this is not specified, then the health check request applies to the entire + server and not to a specific service. + type: string + type: object + 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: + 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 + path: + description: Path defines the HTTP path + that will be requested during health + checking. + maxLength: 1024 + minLength: 1 + type: string + required: + - path + type: object + interval: + default: 3s + description: Interval defines the time between + active 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. + 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 + - GRPC + - enum: + - HTTP + - TCP + - GRPC + 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)' + - message: The grpc field can only be set if the + Health Checker type is GRPC. + rule: 'has(self.grpc) ? self.type == ''GRPC'' + : true' + passive: + description: Passive passive check configuration + properties: + 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 + type: object + http2: + description: HTTP2 provides HTTP/2 configuration for + backend connections. + properties: + initialConnectionWindowSize: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + InitialConnectionWindowSize sets the initial window size for HTTP/2 connections. + If not set, the default value is 1 MiB. + x-kubernetes-int-or-string: true + initialStreamWindowSize: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + InitialStreamWindowSize sets the initial window size for HTTP/2 streams. + If not set, the default value is 64 KiB(64*1024). + x-kubernetes-int-or-string: true + maxConcurrentStreams: + description: |- + MaxConcurrentStreams sets the maximum number of concurrent streams allowed per connection. + If not set, the default value is 100. + format: int32 + maximum: 2147483647 + minimum: 1 + type: integer + onInvalidMessage: + description: |- + OnInvalidMessage determines if Envoy will terminate the connection or just the offending stream in the event of HTTP messaging error + It's recommended for L2 Envoy deployments to set this value to TerminateStream. + https://www.envoyproxy.io/docs/envoy/latest/configuration/best_practices/level_two + Default: TerminateConnection + type: string + type: object + loadBalancer: + description: |- + LoadBalancer policy to apply when routing traffic from the gateway to + the backend endpoints. Defaults to `LeastRequest`. + properties: + consistentHash: + description: |- + ConsistentHash defines the configuration when the load balancer type is + set to ConsistentHash + properties: + cookie: + description: Cookie configures the cookie + hash policy when the consistent hash type + is set to Cookie. + properties: + attributes: + additionalProperties: + type: string + description: Additional Attributes to + set for the generated cookie. + type: object + name: + description: |- + Name of the cookie to hash. + If this cookie does not exist in the request, Envoy will generate a cookie and set + the TTL on the response back to the client based on Layer 4 + attributes of the backend endpoint, to ensure that these future requests + go to the same backend endpoint. Make sure to set the TTL field for this case. + type: string + ttl: + description: |- + TTL of the generated cookie if the cookie is not present. This value sets the + Max-Age attribute value. + type: string + required: + - name + type: object + header: + description: Header configures the header + hash policy when the consistent hash type + is set to Header. + properties: + name: + description: Name of the header to hash. + type: string + required: + - name + type: object + tableSize: + default: 65537 + description: The table size for consistent + hashing, must be prime number limited to + 5000011. + format: int64 + maximum: 5000011 + minimum: 2 + type: integer + type: + description: |- + ConsistentHashType defines the type of input to hash on. Valid Type values are + "SourceIP", + "Header", + "Cookie". + enum: + - SourceIP + - Header + - Cookie + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: If consistent hash type is header, + the header field must be set. + rule: 'self.type == ''Header'' ? has(self.header) + : !has(self.header)' + - message: If consistent hash type is cookie, + the cookie field must be set. + rule: 'self.type == ''Cookie'' ? has(self.cookie) + : !has(self.cookie)' + slowStart: + description: |- + 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 + properties: + window: + description: |- + 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 + type: string + required: + - window + type: object + type: + description: |- + Type decides the type of Load Balancer policy. + Valid LoadBalancerType values are + "ConsistentHash", + "LeastRequest", + "Random", + "RoundRobin". + enum: + - ConsistentHash + - LeastRequest + - Random + - RoundRobin + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: If LoadBalancer type is consistentHash, + consistentHash field needs to be set. + rule: 'self.type == ''ConsistentHash'' ? has(self.consistentHash) + : !has(self.consistentHash)' + - message: Currently SlowStart is only supported for + RoundRobin and LeastRequest load balancers. + rule: 'self.type in [''Random'', ''ConsistentHash''] + ? !has(self.slowStart) : true ' + proxyProtocol: + description: ProxyProtocol enables the Proxy Protocol + when communicating with the backend. + properties: + version: + description: |- + Version of ProxyProtol + Valid ProxyProtocolVersion values are + "V1" + "V2" + enum: + - V1 + - V2 + type: string + required: + - version + type: object + tcpKeepalive: + description: |- + TcpKeepalive settings associated with the upstream client connection. + Disabled by default. + properties: + idleTime: + description: |- + The duration a connection needs to be idle before keep-alive + probes start being sent. + The duration format is + Defaults to `7200s`. + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + interval: + description: |- + The duration between keep-alive probes. + Defaults to `75s`. + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + probes: + description: |- + The total number of unacknowledged probes to send before deciding + the connection is dead. + Defaults to 9. + 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 + type: object host: description: |- Host define the provider service hostname. @@ -11015,6 +13929,14 @@ spec: x-kubernetes-validations: - message: host or backendRefs needs to be set rule: has(self.host) || self.backendRefs.size() > 0 + - message: BackendRefs must be used, backendRef is not supported. + rule: '!has(self.backendRef)' + - message: only supports Service kind. + rule: 'has(self.backendRefs) ? self.backendRefs.all(f, f.kind + == ''Service'') : true' + - message: BackendRefs only supports Core group. + rule: 'has(self.backendRefs) ? (self.backendRefs.all(f, + f.group == "")) : true' samplingRate: default: 100 description: |- 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 3906b325b3d..da6c3ae25fc 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -260,7 +260,6 @@ spec: 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. Deprecated: Use BackendRefs instead. @@ -342,11 +341,19 @@ spec: description: |- BackendRefs references a Kubernetes object that represents the backend server to which the authorization request will be sent. - Only Service kind is supported for now. items: description: BackendRef defines how an ObjectReference that is specific to BackendRef. properties: + failover: + description: |- + Failover This indicates whether the backend is designated as a failover. + Multiple failover backends can be configured. + It is highly recommended to configure active or passive health checks to ensure that failover can be detected + when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again. + The overprovisioning factor is set to 1.4, meaning the failover backends will only start receiving traffic when + the health of the active backends falls below 72%. + type: boolean group: default: "" description: |- @@ -420,17 +427,626 @@ spec: - message: Must have port for Service reference rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' - maxItems: 1 + maxItems: 16 type: array - x-kubernetes-validations: - - message: only support Service kind. - rule: self.all(f, f.kind == 'Service') - - message: BackendRefs only supports Core group. - rule: self.all(f, f.group == '') + backendSettings: + description: |- + BackendSettings holds configuration for managing the connection + to the backend. + properties: + circuitBreaker: + description: |- + Circuit Breaker settings for the upstream connections and requests. + If not set, circuit breakers will be enabled with the default thresholds + properties: + maxConnections: + default: 1024 + description: The maximum number of connections that + Envoy will establish to the referenced backend defined + within a xRoute rule. + format: int64 + maximum: 4294967295 + minimum: 0 + type: integer + maxParallelRequests: + default: 1024 + description: The maximum number of parallel requests + that Envoy will make to the referenced backend defined + within a xRoute rule. + format: int64 + maximum: 4294967295 + minimum: 0 + type: integer + maxParallelRetries: + default: 1024 + description: The maximum number of parallel retries + that Envoy will make to the referenced backend defined + within a xRoute rule. + format: int64 + maximum: 4294967295 + minimum: 0 + type: integer + maxPendingRequests: + default: 1024 + description: The maximum number of pending requests + that Envoy will queue to the referenced backend + defined within a xRoute rule. + format: int64 + 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 + connection: + description: Connection includes backend connection settings. + properties: + bufferLimit: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + BufferLimit Soft limit on size of the cluster’s connections read and write buffers. + BufferLimit applies to connection streaming (maybe non-streaming) channel between processes, it's in user space. + If unspecified, an implementation defined default is applied (32768 bytes). + For example, 20Mi, 1Gi, 256Ki etc. + Note: that when the suffix is not provided, the value is interpreted as bytes. + x-kubernetes-int-or-string: true + socketBufferLimit: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + SocketBufferLimit provides configuration for the maximum buffer size in bytes for each socket + to backend. + SocketBufferLimit applies to socket streaming channel between TCP/IP stacks, it's in kernel space. + For example, 20Mi, 1Gi, 256Ki etc. + Note that when the suffix is not provided, the value is interpreted as bytes. + x-kubernetes-int-or-string: true + type: object + dns: + description: DNS includes dns resolution settings. + properties: + dnsRefreshRate: + description: |- + DNSRefreshRate specifies the rate at which DNS records should be refreshed. + Defaults to 30 seconds. + type: string + respectDnsTtl: + description: |- + RespectDNSTTL indicates whether the DNS Time-To-Live (TTL) should be respected. + If the value is set to true, the DNS refresh rate will be set to the resource record’s TTL. + Defaults to true. + type: boolean + type: object + healthCheck: + description: HealthCheck allows gateway to perform active + health checking on backends. + properties: + active: + description: Active health check configuration + properties: + grpc: + description: |- + GRPC defines the configuration of the GRPC health checker. + It's optional, and can only be used if the specified type is GRPC. + properties: + service: + description: |- + Service to send in the health check request. + If this is not specified, then the health check request applies to the entire + server and not to a specific service. + type: string + type: object + 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: + 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 + path: + description: Path defines the HTTP path that + will be requested during health checking. + maxLength: 1024 + minLength: 1 + type: string + required: + - path + type: object + interval: + default: 3s + description: Interval defines the time between + active 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. + 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 + - GRPC + - enum: + - HTTP + - TCP + - GRPC + 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)' + - message: The grpc field can only be set if the Health + Checker type is GRPC. + rule: 'has(self.grpc) ? self.type == ''GRPC'' : + true' + passive: + description: Passive passive check configuration + properties: + 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 + type: object + http2: + description: HTTP2 provides HTTP/2 configuration for backend + connections. + properties: + initialConnectionWindowSize: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + InitialConnectionWindowSize sets the initial window size for HTTP/2 connections. + If not set, the default value is 1 MiB. + x-kubernetes-int-or-string: true + initialStreamWindowSize: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + InitialStreamWindowSize sets the initial window size for HTTP/2 streams. + If not set, the default value is 64 KiB(64*1024). + x-kubernetes-int-or-string: true + maxConcurrentStreams: + description: |- + MaxConcurrentStreams sets the maximum number of concurrent streams allowed per connection. + If not set, the default value is 100. + format: int32 + maximum: 2147483647 + minimum: 1 + type: integer + onInvalidMessage: + description: |- + OnInvalidMessage determines if Envoy will terminate the connection or just the offending stream in the event of HTTP messaging error + It's recommended for L2 Envoy deployments to set this value to TerminateStream. + https://www.envoyproxy.io/docs/envoy/latest/configuration/best_practices/level_two + Default: TerminateConnection + type: string + type: object + loadBalancer: + description: |- + LoadBalancer policy to apply when routing traffic from the gateway to + the backend endpoints. Defaults to `LeastRequest`. + properties: + consistentHash: + description: |- + ConsistentHash defines the configuration when the load balancer type is + set to ConsistentHash + properties: + cookie: + description: Cookie configures the cookie hash + policy when the consistent hash type is set + to Cookie. + properties: + attributes: + additionalProperties: + type: string + description: Additional Attributes to set + for the generated cookie. + type: object + name: + description: |- + Name of the cookie to hash. + If this cookie does not exist in the request, Envoy will generate a cookie and set + the TTL on the response back to the client based on Layer 4 + attributes of the backend endpoint, to ensure that these future requests + go to the same backend endpoint. Make sure to set the TTL field for this case. + type: string + ttl: + description: |- + TTL of the generated cookie if the cookie is not present. This value sets the + Max-Age attribute value. + type: string + required: + - name + type: object + header: + description: Header configures the header hash + policy when the consistent hash type is set + to Header. + properties: + name: + description: Name of the header to hash. + type: string + required: + - name + type: object + tableSize: + default: 65537 + description: The table size for consistent hashing, + must be prime number limited to 5000011. + format: int64 + maximum: 5000011 + minimum: 2 + type: integer + type: + description: |- + ConsistentHashType defines the type of input to hash on. Valid Type values are + "SourceIP", + "Header", + "Cookie". + enum: + - SourceIP + - Header + - Cookie + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: If consistent hash type is header, the + header field must be set. + rule: 'self.type == ''Header'' ? has(self.header) + : !has(self.header)' + - message: If consistent hash type is cookie, the + cookie field must be set. + rule: 'self.type == ''Cookie'' ? has(self.cookie) + : !has(self.cookie)' + slowStart: + description: |- + 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 + properties: + window: + description: |- + 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 + type: string + required: + - window + type: object + type: + description: |- + Type decides the type of Load Balancer policy. + Valid LoadBalancerType values are + "ConsistentHash", + "LeastRequest", + "Random", + "RoundRobin". + enum: + - ConsistentHash + - LeastRequest + - Random + - RoundRobin + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: If LoadBalancer type is consistentHash, consistentHash + field needs to be set. + rule: 'self.type == ''ConsistentHash'' ? has(self.consistentHash) + : !has(self.consistentHash)' + - message: Currently SlowStart is only supported for RoundRobin + and LeastRequest load balancers. + rule: 'self.type in [''Random'', ''ConsistentHash''] + ? !has(self.slowStart) : true ' + proxyProtocol: + description: ProxyProtocol enables the Proxy Protocol + when communicating with the backend. + properties: + version: + description: |- + Version of ProxyProtol + Valid ProxyProtocolVersion values are + "V1" + "V2" + enum: + - V1 + - V2 + type: string + required: + - version + type: object + tcpKeepalive: + description: |- + TcpKeepalive settings associated with the upstream client connection. + Disabled by default. + properties: + idleTime: + description: |- + The duration a connection needs to be idle before keep-alive + probes start being sent. + The duration format is + Defaults to `7200s`. + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + interval: + description: |- + The duration between keep-alive probes. + Defaults to `75s`. + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + probes: + description: |- + The total number of unacknowledged probes to send before deciding + the connection is dead. + Defaults to 9. + 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 + type: object type: object x-kubernetes-validations: - message: backendRef or backendRefs needs to be set rule: has(self.backendRef) || self.backendRefs.size() > 0 + - message: BackendRefs must be used, backendRef is not supported. + rule: '!has(self.backendRef)' + - message: Exactly one backendRef can be specified in backendRefs. + rule: has(self.backendRefs) && self.backendRefs.size()==1 + - message: BackendRefs only supports Service and Backend kind. + rule: 'has(self.backendRefs) ? self.backendRefs.all(f, f.kind + == ''Service'' || f.kind == ''Backend'') : true' + - message: BackendRefs only supports Core and gateway.envoyproxy.io + group. + rule: 'has(self.backendRefs) ? (self.backendRefs.all(f, f.group + == "" || f.group == ''gateway.envoyproxy.io'')) : true' headersToExtAuth: description: |- HeadersToExtAuth defines the client request headers that will be included @@ -456,7 +1072,6 @@ spec: 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. Deprecated: Use BackendRefs instead. @@ -538,11 +1153,19 @@ spec: description: |- BackendRefs references a Kubernetes object that represents the backend server to which the authorization request will be sent. - Only Service kind is supported for now. items: description: BackendRef defines how an ObjectReference that is specific to BackendRef. properties: + failover: + description: |- + Failover This indicates whether the backend is designated as a failover. + Multiple failover backends can be configured. + It is highly recommended to configure active or passive health checks to ensure that failover can be detected + when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again. + The overprovisioning factor is set to 1.4, meaning the failover backends will only start receiving traffic when + the health of the active backends falls below 72%. + type: boolean group: default: "" description: |- @@ -616,13 +1239,611 @@ spec: - message: Must have port for Service reference rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' - maxItems: 1 + maxItems: 16 type: array - x-kubernetes-validations: - - message: only support Service kind. - rule: self.all(f, f.kind == 'Service') - - message: BackendRefs only supports Core group. - rule: self.all(f, f.group == '') + backendSettings: + description: |- + BackendSettings holds configuration for managing the connection + to the backend. + properties: + circuitBreaker: + description: |- + Circuit Breaker settings for the upstream connections and requests. + If not set, circuit breakers will be enabled with the default thresholds + properties: + maxConnections: + default: 1024 + description: The maximum number of connections that + Envoy will establish to the referenced backend defined + within a xRoute rule. + format: int64 + maximum: 4294967295 + minimum: 0 + type: integer + maxParallelRequests: + default: 1024 + description: The maximum number of parallel requests + that Envoy will make to the referenced backend defined + within a xRoute rule. + format: int64 + maximum: 4294967295 + minimum: 0 + type: integer + maxParallelRetries: + default: 1024 + description: The maximum number of parallel retries + that Envoy will make to the referenced backend defined + within a xRoute rule. + format: int64 + maximum: 4294967295 + minimum: 0 + type: integer + maxPendingRequests: + default: 1024 + description: The maximum number of pending requests + that Envoy will queue to the referenced backend + defined within a xRoute rule. + format: int64 + 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 + connection: + description: Connection includes backend connection settings. + properties: + bufferLimit: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + BufferLimit Soft limit on size of the cluster’s connections read and write buffers. + BufferLimit applies to connection streaming (maybe non-streaming) channel between processes, it's in user space. + If unspecified, an implementation defined default is applied (32768 bytes). + For example, 20Mi, 1Gi, 256Ki etc. + Note: that when the suffix is not provided, the value is interpreted as bytes. + x-kubernetes-int-or-string: true + socketBufferLimit: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + SocketBufferLimit provides configuration for the maximum buffer size in bytes for each socket + to backend. + SocketBufferLimit applies to socket streaming channel between TCP/IP stacks, it's in kernel space. + For example, 20Mi, 1Gi, 256Ki etc. + Note that when the suffix is not provided, the value is interpreted as bytes. + x-kubernetes-int-or-string: true + type: object + dns: + description: DNS includes dns resolution settings. + properties: + dnsRefreshRate: + description: |- + DNSRefreshRate specifies the rate at which DNS records should be refreshed. + Defaults to 30 seconds. + type: string + respectDnsTtl: + description: |- + RespectDNSTTL indicates whether the DNS Time-To-Live (TTL) should be respected. + If the value is set to true, the DNS refresh rate will be set to the resource record’s TTL. + Defaults to true. + type: boolean + type: object + healthCheck: + description: HealthCheck allows gateway to perform active + health checking on backends. + properties: + active: + description: Active health check configuration + properties: + grpc: + description: |- + GRPC defines the configuration of the GRPC health checker. + It's optional, and can only be used if the specified type is GRPC. + properties: + service: + description: |- + Service to send in the health check request. + If this is not specified, then the health check request applies to the entire + server and not to a specific service. + type: string + type: object + 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: + 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 + path: + description: Path defines the HTTP path that + will be requested during health checking. + maxLength: 1024 + minLength: 1 + type: string + required: + - path + type: object + interval: + default: 3s + description: Interval defines the time between + active 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. + 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 + - GRPC + - enum: + - HTTP + - TCP + - GRPC + 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)' + - message: The grpc field can only be set if the Health + Checker type is GRPC. + rule: 'has(self.grpc) ? self.type == ''GRPC'' : + true' + passive: + description: Passive passive check configuration + properties: + 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 + type: object + http2: + description: HTTP2 provides HTTP/2 configuration for backend + connections. + properties: + initialConnectionWindowSize: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + InitialConnectionWindowSize sets the initial window size for HTTP/2 connections. + If not set, the default value is 1 MiB. + x-kubernetes-int-or-string: true + initialStreamWindowSize: + allOf: + - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + - pattern: ^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$ + anyOf: + - type: integer + - type: string + description: |- + InitialStreamWindowSize sets the initial window size for HTTP/2 streams. + If not set, the default value is 64 KiB(64*1024). + x-kubernetes-int-or-string: true + maxConcurrentStreams: + description: |- + MaxConcurrentStreams sets the maximum number of concurrent streams allowed per connection. + If not set, the default value is 100. + format: int32 + maximum: 2147483647 + minimum: 1 + type: integer + onInvalidMessage: + description: |- + OnInvalidMessage determines if Envoy will terminate the connection or just the offending stream in the event of HTTP messaging error + It's recommended for L2 Envoy deployments to set this value to TerminateStream. + https://www.envoyproxy.io/docs/envoy/latest/configuration/best_practices/level_two + Default: TerminateConnection + type: string + type: object + loadBalancer: + description: |- + LoadBalancer policy to apply when routing traffic from the gateway to + the backend endpoints. Defaults to `LeastRequest`. + properties: + consistentHash: + description: |- + ConsistentHash defines the configuration when the load balancer type is + set to ConsistentHash + properties: + cookie: + description: Cookie configures the cookie hash + policy when the consistent hash type is set + to Cookie. + properties: + attributes: + additionalProperties: + type: string + description: Additional Attributes to set + for the generated cookie. + type: object + name: + description: |- + Name of the cookie to hash. + If this cookie does not exist in the request, Envoy will generate a cookie and set + the TTL on the response back to the client based on Layer 4 + attributes of the backend endpoint, to ensure that these future requests + go to the same backend endpoint. Make sure to set the TTL field for this case. + type: string + ttl: + description: |- + TTL of the generated cookie if the cookie is not present. This value sets the + Max-Age attribute value. + type: string + required: + - name + type: object + header: + description: Header configures the header hash + policy when the consistent hash type is set + to Header. + properties: + name: + description: Name of the header to hash. + type: string + required: + - name + type: object + tableSize: + default: 65537 + description: The table size for consistent hashing, + must be prime number limited to 5000011. + format: int64 + maximum: 5000011 + minimum: 2 + type: integer + type: + description: |- + ConsistentHashType defines the type of input to hash on. Valid Type values are + "SourceIP", + "Header", + "Cookie". + enum: + - SourceIP + - Header + - Cookie + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: If consistent hash type is header, the + header field must be set. + rule: 'self.type == ''Header'' ? has(self.header) + : !has(self.header)' + - message: If consistent hash type is cookie, the + cookie field must be set. + rule: 'self.type == ''Cookie'' ? has(self.cookie) + : !has(self.cookie)' + slowStart: + description: |- + 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 + properties: + window: + description: |- + 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 + type: string + required: + - window + type: object + type: + description: |- + Type decides the type of Load Balancer policy. + Valid LoadBalancerType values are + "ConsistentHash", + "LeastRequest", + "Random", + "RoundRobin". + enum: + - ConsistentHash + - LeastRequest + - Random + - RoundRobin + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: If LoadBalancer type is consistentHash, consistentHash + field needs to be set. + rule: 'self.type == ''ConsistentHash'' ? has(self.consistentHash) + : !has(self.consistentHash)' + - message: Currently SlowStart is only supported for RoundRobin + and LeastRequest load balancers. + rule: 'self.type in [''Random'', ''ConsistentHash''] + ? !has(self.slowStart) : true ' + proxyProtocol: + description: ProxyProtocol enables the Proxy Protocol + when communicating with the backend. + properties: + version: + description: |- + Version of ProxyProtol + Valid ProxyProtocolVersion values are + "V1" + "V2" + enum: + - V1 + - V2 + type: string + required: + - version + type: object + tcpKeepalive: + description: |- + TcpKeepalive settings associated with the upstream client connection. + Disabled by default. + properties: + idleTime: + description: |- + The duration a connection needs to be idle before keep-alive + probes start being sent. + The duration format is + Defaults to `7200s`. + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + interval: + description: |- + The duration between keep-alive probes. + Defaults to `75s`. + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + probes: + description: |- + The total number of unacknowledged probes to send before deciding + the connection is dead. + Defaults to 9. + 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 + type: object headersToBackend: description: |- HeadersToBackend are the authorization response headers that will be added @@ -643,6 +1864,17 @@ spec: x-kubernetes-validations: - message: backendRef or backendRefs needs to be set rule: has(self.backendRef) || self.backendRefs.size() > 0 + - message: BackendRefs must be used, backendRef is not supported. + rule: '!has(self.backendRef)' + - message: Exactly one backendRef can be specified in backendRefs. + rule: has(self.backendRefs) && self.backendRefs.size()==1 + - message: BackendRefs only supports Service and Backend kind. + rule: 'has(self.backendRefs) ? self.backendRefs.all(f, f.kind + == ''Service'' || f.kind == ''Backend'') : true' + - message: BackendRefs only supports Core and gateway.envoyproxy.io + group. + rule: 'has(self.backendRefs) ? (self.backendRefs.all(f, f.group + == "" || f.group == ''gateway.envoyproxy.io'')) : true' type: object x-kubernetes-validations: - message: one of grpc or http must be specified @@ -650,24 +1882,6 @@ spec: - 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) || !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) || !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) || !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) || !has(self.http.backendRef.kind) - || self.http.backendRef.kind == ''Service'') : true' jwt: description: JWT defines the configuration for JSON Web Token (JWT) authentication. diff --git a/examples/extension-server/cmd/extension-server/main.go b/examples/extension-server/cmd/extension-server/main.go index 33e08ddc914..9df1f4a885c 100644 --- a/examples/extension-server/cmd/extension-server/main.go +++ b/examples/extension-server/cmd/extension-server/main.go @@ -13,11 +13,11 @@ import ( "os/signal" "syscall" - pb "github.com/envoyproxy/gateway/proto/extension" + "github.com/exampleorg/envoygateway-extension/internal/extensionserver" "github.com/urfave/cli/v2" "google.golang.org/grpc" - "github.com/exampleorg/envoygateway-extension/internal/extensionserver" + pb "github.com/envoyproxy/gateway/proto/extension" ) func main() { diff --git a/examples/extension-server/go.mod b/examples/extension-server/go.mod index a1c8e2fc44c..df377d5e338 100644 --- a/examples/extension-server/go.mod +++ b/examples/extension-server/go.mod @@ -9,7 +9,7 @@ require ( google.golang.org/grpc v1.65.0 google.golang.org/protobuf v1.34.2 k8s.io/apimachinery v0.30.3 - sigs.k8s.io/controller-runtime v0.18.4 + sigs.k8s.io/controller-runtime v0.18.5 sigs.k8s.io/gateway-api v1.1.0 ) @@ -29,11 +29,11 @@ require ( github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect - golang.org/x/net v0.27.0 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/sys v0.24.0 // indirect + golang.org/x/text v0.17.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240805194559-2c9e96a0b5d4 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/examples/extension-server/go.sum b/examples/extension-server/go.sum index e6a6ba81bb1..fc7d8df4b19 100644 --- a/examples/extension-server/go.sum +++ b/examples/extension-server/go.sum @@ -76,34 +76,34 @@ 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.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= 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/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.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.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.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= 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.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= -golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= +golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= 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-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240805194559-2c9e96a0b5d4 h1:OsSGQeIIsyOEOimVxLEIL4rwGcnrjOydQaiA2bOnZUM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240805194559-2c9e96a0b5d4/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= @@ -126,8 +126,8 @@ k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak= k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.18.4 h1:87+guW1zhvuPLh1PHybKdYFLU0YJp4FhJRmiHvm5BZw= -sigs.k8s.io/controller-runtime v0.18.4/go.mod h1:TVoGrfdpbA9VRFaRnKgk9P5/atA0pMwq+f+msb9M8Sg= +sigs.k8s.io/controller-runtime v0.18.5 h1:nTHio/W+Q4aBlQMgbnC5hZb4IjIidyrizMai9P6n4Rk= +sigs.k8s.io/controller-runtime v0.18.5/go.mod h1:TVoGrfdpbA9VRFaRnKgk9P5/atA0pMwq+f+msb9M8Sg= sigs.k8s.io/gateway-api v1.1.0 h1:DsLDXCi6jR+Xz8/xd0Z1PYl2Pn0TyaFMOPPZIj4inDM= sigs.k8s.io/gateway-api v1.1.0/go.mod h1:ZH4lHrL2sDi0FHZ9jjneb8kKnGzFWyrTya35sWUTrRs= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= diff --git a/examples/extension-server/internal/extensionserver/server.go b/examples/extension-server/internal/extensionserver/server.go index a2776a9f966..2c060869b88 100644 --- a/examples/extension-server/internal/extensionserver/server.go +++ b/examples/extension-server/internal/extensionserver/server.go @@ -11,15 +11,15 @@ import ( "fmt" "log/slog" - pb "github.com/envoyproxy/gateway/proto/extension" corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" listenerv3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" bav3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/basic_auth/v3" hcm "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" "github.com/envoyproxy/go-control-plane/pkg/wellknown" + "github.com/exampleorg/envoygateway-extension/api/v1alpha1" "google.golang.org/protobuf/types/known/anypb" - "github.com/exampleorg/envoygateway-extension/api/v1alpha1" + pb "github.com/envoyproxy/gateway/proto/extension" ) type Server struct { diff --git a/go.mod b/go.mod index e66adb8a3db..b6a37be1e63 100644 --- a/go.mod +++ b/go.mod @@ -5,12 +5,12 @@ go 1.22.5 replace github.com/imdario/mergo => github.com/imdario/mergo v0.3.16 require ( - fortio.org/fortio v1.66.0 + fortio.org/fortio v1.66.1 fortio.org/log v1.16.0 github.com/Masterminds/semver/v3 v3.2.1 github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc - github.com/docker/cli v27.1.1+incompatible + github.com/docker/cli v27.1.2+incompatible github.com/dominikbraun/graph v0.23.0 github.com/envoyproxy/go-control-plane v0.12.1-0.20240612043845-c54ec4ce422d github.com/envoyproxy/ratelimit v1.4.1-0.20230427142404-e2a87f41d3a7 @@ -23,11 +23,12 @@ require ( github.com/golang/protobuf v1.5.4 github.com/google/cel-go v0.21.0 github.com/google/go-cmp v0.6.0 - github.com/google/go-containerregistry v0.20.1 + github.com/google/go-containerregistry v0.20.2 github.com/grafana/tempo v1.5.0 github.com/hashicorp/go-multierror v1.1.1 github.com/miekg/dns v1.1.61 - github.com/prometheus/client_golang v1.19.1 + github.com/ohler55/ojg v1.24.0 + github.com/prometheus/client_golang v1.20.0 github.com/prometheus/common v0.55.0 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 @@ -43,12 +44,12 @@ require ( go.opentelemetry.io/otel/sdk/metric v1.28.0 go.opentelemetry.io/proto/otlp v1.3.1 go.uber.org/zap v1.27.0 - golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 - golang.org/x/sys v0.22.0 + golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 + golang.org/x/sys v0.24.0 google.golang.org/grpc v1.65.0 google.golang.org/protobuf v1.34.2 gopkg.in/yaml.v3 v3.0.1 - helm.sh/helm/v3 v3.15.3 + helm.sh/helm/v3 v3.15.4 k8s.io/api v0.30.3 k8s.io/apiextensions-apiserver v0.30.3 k8s.io/apimachinery v0.30.3 @@ -56,7 +57,7 @@ require ( k8s.io/client-go v0.30.3 k8s.io/kubectl v0.30.3 k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 - sigs.k8s.io/controller-runtime v0.18.4 + sigs.k8s.io/controller-runtime v0.18.5 sigs.k8s.io/gateway-api v1.1.0 sigs.k8s.io/mcs-api v0.1.0 sigs.k8s.io/yaml v1.4.0 @@ -64,7 +65,7 @@ require ( require ( github.com/docker/docker v27.1.1+incompatible - github.com/replicatedhq/troubleshoot v0.98.0 + github.com/replicatedhq/troubleshoot v0.99.0 ) require ( @@ -75,10 +76,10 @@ require ( cloud.google.com/go/storage v1.40.0 // indirect dario.cat/mergo v1.0.0 // indirect filippo.io/edwards25519 v1.1.0 // indirect - fortio.org/cli v1.7.0 // indirect + fortio.org/cli v1.8.0 // indirect fortio.org/dflag v1.7.2 // indirect fortio.org/scli v1.15.1 // indirect - fortio.org/sets v1.1.1 // indirect + fortio.org/sets v1.2.0 // indirect fortio.org/struct2env v0.4.1 // indirect fortio.org/version v1.0.4 // indirect github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect @@ -87,7 +88,7 @@ require ( github.com/Masterminds/sprig/v3 v3.2.3 // indirect github.com/Masterminds/squirrel v1.5.4 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/Microsoft/hcsshim v0.12.3 // indirect + github.com/Microsoft/hcsshim v0.12.5 // indirect github.com/antlr4-go/antlr/v4 v4.13.0 // indirect github.com/apparentlymart/go-cidr v1.1.0 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect @@ -95,18 +96,19 @@ require ( github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/c9s/goprocinfo v0.0.0-20170724085704-0010a05ce49f // indirect - github.com/cilium/ebpf v0.11.0 // indirect + github.com/cilium/ebpf v0.16.0 // indirect github.com/containerd/cgroups/v3 v3.0.3 // indirect - github.com/containerd/containerd v1.7.17 // indirect + github.com/containerd/containerd v1.7.20 // indirect github.com/containerd/errdefs v0.1.0 // indirect github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect - github.com/containers/image/v5 v5.31.1 // indirect + github.com/containers/image/v5 v5.32.1 // indirect github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect - github.com/containers/ocicrypt v1.1.10 // indirect - github.com/containers/storage v1.54.0 // indirect + github.com/containers/ocicrypt v1.2.0 // indirect + github.com/containers/storage v1.55.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect - github.com/cyphar/filepath-securejoin v0.2.5 // indirect + github.com/cyphar/filepath-securejoin v0.3.1 // indirect github.com/distribution/distribution/v3 v3.0.0-beta.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/distribution v2.8.3+incompatible // indirect @@ -142,7 +144,7 @@ require ( github.com/jackc/pgx/v5 v5.6.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmoiron/sqlx v1.3.5 // indirect - github.com/klauspost/compress v1.17.8 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/klauspost/pgzip v1.2.6 // indirect github.com/kortschak/goroutine v1.1.2 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect @@ -153,7 +155,7 @@ require ( github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/microsoft/go-mssqldb v1.7.2 // indirect github.com/mistifyio/go-zfs/v3 v3.0.1 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect @@ -164,9 +166,9 @@ require ( github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/locker v1.0.1 // indirect github.com/moby/patternmatcher v0.6.0 // indirect - github.com/moby/sys/mountinfo v0.7.1 // indirect + github.com/moby/sys/mountinfo v0.7.2 // indirect github.com/moby/sys/sequential v0.5.0 // indirect - github.com/moby/sys/user v0.1.0 // indirect + github.com/moby/sys/user v0.2.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opencontainers/runtime-spec v1.2.0 // indirect @@ -189,7 +191,7 @@ require ( github.com/spf13/viper v1.19.0 // indirect github.com/stoewer/go-strcase v1.2.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/sylabs/sif/v2 v2.16.0 // indirect + github.com/sylabs/sif/v2 v2.18.0 // indirect github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect github.com/tchap/go-patricia/v2 v2.3.1 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect @@ -204,8 +206,8 @@ require ( go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect - golang.org/x/crypto v0.25.0 // indirect - golang.org/x/crypto/x509roots/fallback v0.0.0-20240626151235-a6a393ffd658 // indirect + golang.org/x/crypto v0.26.0 // indirect + golang.org/x/crypto/x509roots/fallback v0.0.0-20240806160748-b2d3a6a4b4d3 // indirect google.golang.org/api v0.172.0 // indirect google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect @@ -213,7 +215,7 @@ require ( k8s.io/apiserver v0.30.3 // indirect k8s.io/kubelet v0.30.3 // indirect k8s.io/metrics v0.30.3 // indirect - oras.land/oras-go v1.2.5 // indirect + oras.land/oras-go v1.2.6 // indirect periph.io/x/host/v3 v3.8.2 // indirect ) @@ -274,17 +276,17 @@ require ( go.opentelemetry.io/otel/trace v1.28.0 // indirect go.starlark.net v0.0.0-20240520160348-046347dcd104 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/mod v0.19.0 // indirect - golang.org/x/net v0.27.0 - golang.org/x/oauth2 v0.21.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/term v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/mod v0.20.0 // indirect + golang.org/x/net v0.28.0 + golang.org/x/oauth2 v0.22.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/term v0.23.0 // indirect + golang.org/x/text v0.17.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.22.0 // indirect + golang.org/x/tools v0.23.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240805194559-2c9e96a0b5d4 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect k8s.io/component-base v0.30.3 // indirect diff --git a/go.sum b/go.sum index ed3fe16fab6..42ae9448cf4 100644 --- a/go.sum +++ b/go.sum @@ -191,18 +191,18 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= fortio.org/assert v1.2.1 h1:48I39urpeDj65RP1KguF7akCjILNeu6vICiYMEysR7Q= fortio.org/assert v1.2.1/go.mod h1:039mG+/iYDPO8Ibx8TrNuJCm2T2SuhwRI3uL9nHTTls= -fortio.org/cli v1.7.0 h1:w+uXZLGi4t3Vn/BvbeMuSw84Z1pvNPG9HqeGfpP68cc= -fortio.org/cli v1.7.0/go.mod h1:s4vxWz7P7T4cYOWdMF0NA693Nu1gK9OW4KoDj54/Do4= +fortio.org/cli v1.8.0 h1:Mz1phmUwkQaXESGb1nIWBY+CHli/GYIlhwpktorh9sY= +fortio.org/cli v1.8.0/go.mod h1:pk/JBE8LcXtNuo5Yj2bLsVbwPaHo8NWdbstSN0cpbFk= fortio.org/dflag v1.7.2 h1:lUhXFvDlw4CJj/q7hPv/TC+n/wVoQylzQO6bUg5GQa0= fortio.org/dflag v1.7.2/go.mod h1:6yO/NIgrWfQH195WbHJ3Y45SCx11ffivQjfx2C/FS1U= -fortio.org/fortio v1.66.0 h1:9F/200qIu136z847bxs/NeAoYdJaQlVofYlppi3qwcw= -fortio.org/fortio v1.66.0/go.mod h1:eUl5MRscw6CiWAStai8aB3/8unxA9uNzJRXdhKEaq1s= +fortio.org/fortio v1.66.1 h1:NiVVHUy/DkMoOA/oLJHs0slsTnm/h3ocLbSfvP6NXIc= +fortio.org/fortio v1.66.1/go.mod h1:3qkJSza2B2PC8TVen78wIupHgnsXvlzUnSvgQfiKfUM= fortio.org/log v1.16.0 h1:GhU8/9NkYZmEIzvTN/DTMedDAStLJraWUUVUA2EbNDc= fortio.org/log v1.16.0/go.mod h1:t58Spg9njjymvRioh5F6qKGSupEsnMjXLGWIS1i3khE= fortio.org/scli v1.15.1 h1:Upza50brpEZwUk8Nn2gdP4BjgqJZY3J+z7KLrrAzPjY= fortio.org/scli v1.15.1/go.mod h1:9LOD4iPe9u73KeJGYC/Af1oFniOafO7oZ9VvwENMf/c= -fortio.org/sets v1.1.1 h1:Q7Z1Ft2lpUc1N7bfI8HofIK0QskrOflfYRyKT2LzBng= -fortio.org/sets v1.1.1/go.mod h1:J2BwIxNOLWsSU7IMZUg541kh3Au4JEKHrghVwXs68tE= +fortio.org/sets v1.2.0 h1:FBfC7R2xrOJtkcioUbY6WqEzdujuBoZRbSdp1fYF4Kk= +fortio.org/sets v1.2.0/go.mod h1:J2BwIxNOLWsSU7IMZUg541kh3Au4JEKHrghVwXs68tE= fortio.org/struct2env v0.4.1 h1:rJludAMO5eBvpWplWEQNqoVDFZr4RWMQX7RUapgZyc0= fortio.org/struct2env v0.4.1/go.mod h1:lENUe70UwA1zDUCX+8AsO663QCFqYaprk5lnPhjD410= fortio.org/version v1.0.4 h1:FWUMpJ+hVTNc4RhvvOJzb0xesrlRmG/a+D6bjbQ4+5U= @@ -252,8 +252,8 @@ github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8 github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/Microsoft/hcsshim v0.12.3 h1:LS9NXqXhMoqNCplK1ApmVSfB4UnVLRDWRapB6EIlxE0= -github.com/Microsoft/hcsshim v0.12.3/go.mod h1:Iyl1WVpZzr+UkzjekHZbV8o5Z9ZkxNGx6CtY2Qg/JVQ= +github.com/Microsoft/hcsshim v0.12.5 h1:bpTInLlDy/nDRWFVcefDZZ1+U8tS+rz3MxjKgu9boo0= +github.com/Microsoft/hcsshim v0.12.5/go.mod h1:tIUGego4G1EN5Hb6KC90aDYiUI2dqLSTTOCjVNpOgZ8= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= @@ -310,8 +310,8 @@ github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXH 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/cilium/ebpf v0.11.0 h1:V8gS/bTCCjX9uUnkUFUpPsksM8n1lXBAvHcpiFk1X2Y= -github.com/cilium/ebpf v0.11.0/go.mod h1:WE7CZAnqOL2RouJ4f1uyNhqr2P4CCvXFIqdRDUgWsVs= +github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok= +github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE= 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= @@ -327,24 +327,26 @@ github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1Ig github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= -github.com/containerd/containerd v1.7.17 h1:KjNnn0+tAVQHAoaWRjmdak9WlvnFR/8rU1CHHy8Rm2A= -github.com/containerd/containerd v1.7.17/go.mod h1:vK+hhT4TIv2uejlcDlbVIc8+h/BqtKLIyNrtCZol8lI= +github.com/containerd/containerd v1.7.20 h1:Sl6jQYk3TRavaU83h66QMbI2Nqg9Jm6qzwX57Vsn1SQ= +github.com/containerd/containerd v1.7.20/go.mod h1:52GsS5CwquuqPuLncsXwG0t2CiUce+KsNHJZQJvAgR0= github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM= github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= 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/containers/image/v5 v5.31.1 h1:3x9soI6Biml/GiDLpkSmKrkRSwVGctxu/vONpoUdklA= -github.com/containers/image/v5 v5.31.1/go.mod h1:5QfOqSackPkSbF7Qxc1DnVNnPJKQ+KWLkfEfDpK590Q= +github.com/containers/image/v5 v5.32.1 h1:fVa7GxRC4BCPGsfSRs4JY12WyeY26SUYQ0NuANaCFrI= +github.com/containers/image/v5 v5.32.1/go.mod h1:v1l73VeMugfj/QtKI+jhYbwnwFCFnNGckvbST3rQ5Hk= github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA= github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY= -github.com/containers/ocicrypt v1.1.10 h1:r7UR6o8+lyhkEywetubUUgcKFjOWOaWz8cEBrCPX0ic= -github.com/containers/ocicrypt v1.1.10/go.mod h1:YfzSSr06PTHQwSTUKqDSjish9BeW1E4HUmreluQcMd8= -github.com/containers/storage v1.54.0 h1:xwYAlf6n9OnIlURQLLg3FYHbO74fQ/2W2N6EtQEUM4I= -github.com/containers/storage v1.54.0/go.mod h1:PlMOoinRrBSnhYODLxt4EXl0nmJt+X0kjG0Xdt9fMTw= +github.com/containers/ocicrypt v1.2.0 h1:X14EgRK3xNFvJEfI5O4Qn4T3E25ANudSOZz/sirVuPM= +github.com/containers/ocicrypt v1.2.0/go.mod h1:ZNviigQajtdlxIZGibvblVuIFBKIuUI2M0QM12SD31U= +github.com/containers/storage v1.55.0 h1:wTWZ3YpcQf1F+dSP4KxG9iqDfpQY1otaUXjPpffuhgg= +github.com/containers/storage v1.55.0/go.mod h1:28cB81IDk+y7ok60Of6u52RbCeBRucbFOeLunhER1RQ= 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= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= @@ -364,8 +366,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/cyphar/filepath-securejoin v0.2.5 h1:6iR5tXJ/e6tJZzzdMc1km3Sa7RRIVBKAK32O2s7AYfo= -github.com/cyphar/filepath-securejoin v0.2.5/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/cyphar/filepath-securejoin v0.3.1 h1:1V7cHiaW+C+39wEfpH6XlLBQo3j/PciWFrgfCLS8XrE= +github.com/cyphar/filepath-securejoin v0.3.1/go.mod h1:F7i41x/9cBF7lzCrVsYs9fuzwRZm4NQsGTBdpp6mETc= github.com/datawire/dlib v1.3.0 h1:KkmyXU1kwm3oPBk1ypR70YbcOlEXWzEbx5RE0iRXTGk= github.com/datawire/dlib v1.3.0/go.mod h1:NiGDmetmbkBvtznpWSx6C0vA0s0LK9aHna3LJDqjruk= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -380,8 +382,8 @@ github.com/distribution/distribution/v3 v3.0.0-beta.1 h1:X+ELTxPuZ1Xe5MsD3kp2wfG github.com/distribution/distribution/v3 v3.0.0-beta.1/go.mod h1:O9O8uamhHzWWQVTjuQpyYUVm/ShPHPUDgvQMpHGVBDs= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/cli v27.1.1+incompatible h1:goaZxOqs4QKxznZjjBWKONQci/MywhtRv2oNn0GkeZE= -github.com/docker/cli v27.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v27.1.2+incompatible h1:nYviRv5Y+YAKx3dFrTvS1ErkyVVunKOhoweCTE1BsnI= +github.com/docker/cli v27.1.2+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 v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= @@ -529,6 +531,8 @@ github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= +github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= +github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= github.com/go-redis/redis/v7 v7.4.1 h1:PASvf36gyUpr2zdOUS/9Zqc80GbM+9BDyiJSJDDOrTI= github.com/go-redis/redis/v7 v7.4.1/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= @@ -618,8 +622,8 @@ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-containerregistry v0.20.1 h1:eTgx9QNYugV4DN5mz4U8hiAGTi1ybXn0TPi4Smd8du0= -github.com/google/go-containerregistry v0.20.1/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI= +github.com/google/go-containerregistry v0.20.2 h1:B1wPJ1SN/S7pB+ZAimcciVD+r+yV/l/DSArMxlbwseo= +github.com/google/go-containerregistry v0.20.2/go.mod h1:z38EKdKh4h7IP2gSfUUqEvalZBqs6AoLeWfUy34nQC8= github.com/google/go-intervals v0.0.2 h1:FGrVEiUnTRKR8yE04qzXYaJMtnIYqobR5QbblK3ixcM= github.com/google/go-intervals v0.0.2/go.mod h1:MkaR3LNRfeKLPmqgJYs4E66z5InYjmCjbbr4TQlcT6Y= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -759,8 +763,12 @@ github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Cc github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= +github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/jsimonetti/rtnetlink/v2 v2.0.1 h1:xda7qaHDSVOsADNouv7ukSuicKZO7GgVUCXxpaIEIlM= +github.com/jsimonetti/rtnetlink/v2 v2.0.1/go.mod h1:7MoNYNbb3UaDHtF8udiJo/RH6VsTKP1pqKLUTVCvToE= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -777,8 +785,8 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL 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.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= -github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= -github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -834,12 +842,16 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= +github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= +github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= +github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= github.com/microsoft/go-mssqldb v1.7.2 h1:CHkFJiObW7ItKTJfHo1QX7QBBD1iV+mn1eOyRP3b/PA= github.com/microsoft/go-mssqldb v1.7.2/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA= github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs= @@ -869,12 +881,12 @@ github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkV github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g= -github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= +github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= +github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= -github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= -github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= +github.com/moby/sys/user v0.2.0 h1:OnpapJsRp25vkhw8TFG6OLJODNh/3rEwRWtJ3kakwRM= +github.com/moby/sys/user v0.2.0/go.mod h1:RYstrcWOJpVh+6qzUqp2bU3eaRpdiQeKGlKitaH0PM8= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -899,6 +911,8 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/ohler55/ojg v1.24.0 h1:y2AVez6fPTszK/jPhaAYMCAzAoSleConMqSDD5wJKJg= +github.com/ohler55/ojg v1.24.0/go.mod h1:gQhDVpQLqrmnd2eqGAvJtn+NfKoYJbe/A4Sj3/Vro4o= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -957,8 +971,8 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= -github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_golang v1.20.0 h1:jBzTZ7B099Rg24tny+qngoynol8LtVYlA2bqx3vEloI= +github.com/prometheus/client_golang v1.20.0/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -985,8 +999,8 @@ github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb github.com/redis/go-redis/extra/redisotel/v9 v9.0.5/go.mod h1:WZjPDy7VNzn77AAfnAfVjZNvfJTYfPetfZk5yoSTLaQ= github.com/redis/go-redis/v9 v9.1.0 h1:137FnGdk+EQdCbye1FW+qOEcY5S+SpY9T0NiuqvtfMY= github.com/redis/go-redis/v9 v9.1.0/go.mod h1:urWj3He21Dj5k4TK1y59xH8Uj6ATueP8AH1cY3lZl4c= -github.com/replicatedhq/troubleshoot v0.98.0 h1:+R3rMV84sGr24/OOr9PHYt9NPXsZHB24/8N4IH1rJFI= -github.com/replicatedhq/troubleshoot v0.98.0/go.mod h1:L+ocOIFN2a65xiXHQT57ythmXXw4mWkWwH4dfZJPJ8g= +github.com/replicatedhq/troubleshoot v0.99.0 h1:KtsCe/8EL1VPQrokZw3bcKo8HcCTRUMEtUb2+SJ5l1k= +github.com/replicatedhq/troubleshoot v0.99.0/go.mod h1:5rRx3kCUCX9Adl3ST1mzo57FICjIJMaIrkj3rTrzvv4= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= @@ -1077,8 +1091,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/sylabs/sif/v2 v2.16.0 h1:2eqaBaQQsn5DZTzm3QZm0HupZQEjNXfxRnCmtyCihEU= -github.com/sylabs/sif/v2 v2.16.0/go.mod h1:d5TxgD/mhMUU3kWLmZmWJQ99Wg0asaTP0bq3ezR1xpg= +github.com/sylabs/sif/v2 v2.18.0 h1:eXugsS1qx7St2Wu/AJ21KnsQiVCpouPlTigABh+6KYI= +github.com/sylabs/sif/v2 v2.18.0/go.mod h1:GOQj7LIBqp15fjqH5i8ZEbLp8SXJi9S+xbRO+QQAdRo= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes= @@ -1204,10 +1218,10 @@ golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= -golang.org/x/crypto/x509roots/fallback v0.0.0-20240626151235-a6a393ffd658 h1:i7K6wQLN/0oxF7FT3tKkfMCstxoT4VGG36YIB9ZKLzI= -golang.org/x/crypto/x509roots/fallback v0.0.0-20240626151235-a6a393ffd658/go.mod h1:kNa9WdvYnzFwC79zRpLRMJbdEFlhyM5RPFBBZp/wWH8= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/crypto/x509roots/fallback v0.0.0-20240806160748-b2d3a6a4b4d3 h1:oWb21rU9Q9XrRwXLB7jHc1rbp6EiiimZZv5MLxpu4T0= +golang.org/x/crypto/x509roots/fallback v0.0.0-20240806160748-b2d3a6a4b4d3/go.mod h1:kNa9WdvYnzFwC79zRpLRMJbdEFlhyM5RPFBBZp/wWH8= 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= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1218,8 +1232,8 @@ 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-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= -golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= 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= @@ -1246,8 +1260,8 @@ 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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= -golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.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= @@ -1309,8 +1323,8 @@ golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfS golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= 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.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= 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= @@ -1336,8 +1350,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= +golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= 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= @@ -1352,8 +1366,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/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.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.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= @@ -1447,14 +1461,14 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.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= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1466,8 +1480,8 @@ golang.org/x/text v0.3.5/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.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= 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= @@ -1535,8 +1549,8 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= -golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= +golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= 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= @@ -1712,8 +1726,8 @@ google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUE google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240805194559-2c9e96a0b5d4 h1:OsSGQeIIsyOEOimVxLEIL4rwGcnrjOydQaiA2bOnZUM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240805194559-2c9e96a0b5d4/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= 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.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1811,8 +1825,8 @@ gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= -helm.sh/helm/v3 v3.15.3 h1:HcZDaVFe9uHa6hpsR54mJjYyRy4uz/pc6csg27nxFOc= -helm.sh/helm/v3 v3.15.3/go.mod h1:FzSIP8jDQaa6WAVg9F+OkKz7J0ZmAga4MABtTbsb9WQ= +helm.sh/helm/v3 v3.15.4 h1:UFHd6oZ1IN3FsUZ7XNhOQDyQ2QYknBNWRHH57e9cbHY= +helm.sh/helm/v3 v3.15.4/go.mod h1:phOwlxqGSgppCY/ysWBNRhG3MtnpsttOzxaTK+Mt40E= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1870,8 +1884,8 @@ k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak= k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo= -oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo= +oras.land/oras-go v1.2.6 h1:z8cmxQXBU8yZ4mkytWqXfo6tZcamPwjsuxYU81xJ8Lk= +oras.land/oras-go v1.2.6/go.mod h1:OVPc1PegSEe/K8YiLfosrlqlqTN9PUyFvOw5Y9gwrT8= periph.io/x/host/v3 v3.8.2 h1:ayKUDzgUCN0g8+/xM9GTkWaOBhSLVcVHGTfjAOi8OsQ= periph.io/x/host/v3 v3.8.2/go.mod h1:yFL76AesNHR68PboofSWYaQTKmvPXsQH2Apvp/ls/K4= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= @@ -1879,8 +1893,8 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= 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.18.4 h1:87+guW1zhvuPLh1PHybKdYFLU0YJp4FhJRmiHvm5BZw= -sigs.k8s.io/controller-runtime v0.18.4/go.mod h1:TVoGrfdpbA9VRFaRnKgk9P5/atA0pMwq+f+msb9M8Sg= +sigs.k8s.io/controller-runtime v0.18.5 h1:nTHio/W+Q4aBlQMgbnC5hZb4IjIidyrizMai9P6n4Rk= +sigs.k8s.io/controller-runtime v0.18.5/go.mod h1:TVoGrfdpbA9VRFaRnKgk9P5/atA0pMwq+f+msb9M8Sg= sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI= sigs.k8s.io/gateway-api v1.1.0 h1:DsLDXCi6jR+Xz8/xd0Z1PYl2Pn0TyaFMOPPZIj4inDM= sigs.k8s.io/gateway-api v1.1.0/go.mod h1:ZH4lHrL2sDi0FHZ9jjneb8kKnGzFWyrTya35sWUTrRs= diff --git a/internal/cmd/egctl/config.go b/internal/cmd/egctl/config.go index 13a0f6bed21..501146676e0 100644 --- a/internal/cmd/egctl/config.go +++ b/internal/cmd/egctl/config.go @@ -79,7 +79,6 @@ func retrieveConfigDump(args []string, includeEds bool, configType envoyConfigTy var wg sync.WaitGroup wg.Add(len(pods)) for _, pod := range pods { - pod := pod go func() { fw, err := portForwarder(cli, pod, adminPort) if err != nil { @@ -170,7 +169,6 @@ func fetchRunningEnvoyPods(c kube.CLIClient, nn types.NamespacedName, labelSelec podsNamespacedNames := []types.NamespacedName{} for _, pod := range pods { - pod := pod podNsName := utils.NamespacedName(&pod) if pod.Status.Phase != "Running" { return podsNamespacedNames, fmt.Errorf("pod %s is not running", podNsName) diff --git a/internal/cmd/egctl/translate.go b/internal/cmd/egctl/translate.go index 2bf4cda177f..ceb4e9deee3 100644 --- a/internal/cmd/egctl/translate.go +++ b/internal/cmd/egctl/translate.go @@ -63,47 +63,48 @@ func newTranslateCommand() *cobra.Command { addMissingResources bool outTypes []string dnsDomain string + namespace string ) translateCommand := &cobra.Command{ Use: "translate", Short: "Translate Configuration from an input type to an output type", Example: ` # Translate Gateway API Resources into All xDS Resources. - egctl experimental translate --from gateway-api --to xds --file + egctl experimental translate --from gateway-api --to xds --file -n # Translate Gateway API Resources into All xDS Resources in JSON output. - egctl experimental translate --from gateway-api --to xds --type all --output json --file + egctl experimental translate --from gateway-api --to xds --type all --output json --file -n # Translate Gateway API Resources into All xDS Resources in YAML output. - egctl experimental translate --from gateway-api --to xds --type all --output yaml --file + egctl experimental translate --from gateway-api --to xds --type all --output yaml --file -n # Translate Gateway API Resources into Bootstrap xDS Resources. - egctl experimental translate --from gateway-api --to xds --type bootstrap --file + egctl experimental translate --from gateway-api --to xds --type bootstrap --file -n # Translate Gateway API Resources into Cluster xDS Resources. - egctl experimental translate --from gateway-api --to xds --type cluster --file + egctl experimental translate --from gateway-api --to xds --type cluster --file -n # Translate Gateway API Resources into Listener xDS Resources. - egctl experimental translate --from gateway-api --to xds --type listener --file + egctl experimental translate --from gateway-api --to xds --type listener --file -n # Translate Gateway API Resources into Route xDS Resources. - egctl experimental translate --from gateway-api --to xds --type route --file + egctl experimental translate --from gateway-api --to xds --type route --file -n # Translate Gateway API Resources into Cluster xDS Resources with short syntax. - egctl x translate --from gateway-api --to xds -t cluster -o yaml -f + egctl x translate --from gateway-api --to xds -t cluster -o yaml -f -n # Translate Gateway API Resources into All xDS Resources with dummy resources added. - egctl x translate --from gateway-api --to xds -t cluster --add-missing-resources -f + egctl x translate --from gateway-api --to xds -t cluster --add-missing-resources -f -n # Translate Gateway API Resources into All xDS Resources in YAML output, # also print the Gateway API Resources with updated status in the same output. - egctl experimental translate --from gateway-api --to gateway-api,xds --type all --output yaml --file + egctl experimental translate --from gateway-api --to gateway-api,xds --type all --output yaml --file -n # Translate Gateway API Resources into IR in YAML output, egctl experimental translate --from gateway-api --to ir --output yaml --file `, RunE: func(cmd *cobra.Command, args []string) error { - return translate(cmd.OutOrStdout(), inFile, inType, outTypes, output, resourceType, addMissingResources, dnsDomain) + return translate(cmd.OutOrStdout(), inFile, inType, outTypes, output, resourceType, addMissingResources, namespace, dnsDomain) }, } @@ -117,6 +118,8 @@ func newTranslateCommand() *cobra.Command { translateCommand.PersistentFlags().StringVarP(&resourceType, "type", "t", string(AllEnvoyConfigType), getValidResourceTypesStr()) translateCommand.PersistentFlags().BoolVarP(&addMissingResources, "add-missing-resources", "", false, "Provides dummy resources if missed") translateCommand.PersistentFlags().StringVarP(&dnsDomain, "dns-domain", "", "cluster.local", "DNS domain used by k8s services, default is cluster.local") + translateCommand.PersistentFlags().StringVarP(&namespace, "namespace", "n", "envoy-gateway-system", "Namespace where envoy gateway is installed.") + return translateCommand } @@ -220,7 +223,7 @@ func validate(inFile, inType string, outTypes []string, resourceType string) err return nil } -func translate(w io.Writer, inFile, inType string, outTypes []string, output, resourceType string, addMissingResources bool, dnsDomain string) error { +func translate(w io.Writer, inFile, inType string, outTypes []string, output, resourceType string, addMissingResources bool, namespace, dnsDomain string) error { if err := validate(inFile, inType, outTypes, resourceType); err != nil { return err } @@ -247,7 +250,7 @@ func translate(w io.Writer, inFile, inType string, outTypes []string, output, re } } if outType == xdsType { - res, err := translateGatewayAPIToXds(dnsDomain, resourceType, resources) + res, err := translateGatewayAPIToXds(namespace, dnsDomain, resourceType, resources) if err != nil { return err } @@ -333,7 +336,7 @@ func translateGatewayAPIToGatewayAPI(resources *gatewayapi.Resources) (gatewayap return gRes.Resources, nil } -func translateGatewayAPIToXds(dnsDomain string, resourceType string, resources *gatewayapi.Resources) (map[string]any, error) { +func translateGatewayAPIToXds(namespace, dnsDomain string, resourceType string, resources *gatewayapi.Resources) (map[string]any, error) { if resources.GatewayClass == nil { return nil, fmt.Errorf("the GatewayClass resource is required") } @@ -363,7 +366,7 @@ func translateGatewayAPIToXds(dnsDomain string, resourceType string, resources * xTranslator := &translator.Translator{ // Set some default settings for translation GlobalRateLimit: &translator.GlobalRateLimitSettings{ - ServiceURL: ratelimit.GetServiceURL("envoy-gateway", dnsDomain), + ServiceURL: ratelimit.GetServiceURL(namespace, dnsDomain), }, } if resources.EnvoyProxyForGatewayClass != nil { diff --git a/internal/cmd/egctl/translate_test.go b/internal/cmd/egctl/translate_test.go index 43fac41ebdd..9207c8bb75b 100644 --- a/internal/cmd/egctl/translate_test.go +++ b/internal/cmd/egctl/translate_test.go @@ -292,8 +292,6 @@ func TestTranslate(t *testing.T) { flag.Parse() for _, tc := range testCases { - tc := tc - t.Run(tc.name+"|"+tc.resourceType, func(t *testing.T) { b := bytes.NewBufferString("") root := newTranslateCommand() diff --git a/internal/cmd/egctl/version.go b/internal/cmd/egctl/version.go index 5cab0035358..7492effeee6 100644 --- a/internal/cmd/egctl/version.go +++ b/internal/cmd/egctl/version.go @@ -99,7 +99,6 @@ func versions(w io.Writer, containerName, output string, remote bool) error { } for _, pod := range pods.Items { - pod := pod if pod.Status.Phase != "Running" { fmt.Fprintf(w, "WARN: pod %s/%s is not running, skipping it.", pod.Namespace, pod.Name) diff --git a/internal/cmd/server_test.go b/internal/cmd/server_test.go index dffe10670c9..4ce4178dbfd 100644 --- a/internal/cmd/server_test.go +++ b/internal/cmd/server_test.go @@ -52,7 +52,6 @@ func TestGetConfigValidate(t *testing.T) { }, } for _, test := range tests { - test := test t.Run(test.name, func(t *testing.T) { file, err := os.CreateTemp("", "config") require.NoError(t, err) diff --git a/internal/envoygateway/config/config_test.go b/internal/envoygateway/config/config_test.go index 2b3f461f762..59bba129434 100644 --- a/internal/envoygateway/config/config_test.go +++ b/internal/envoygateway/config/config_test.go @@ -63,7 +63,6 @@ func TestValidate(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { err := tc.cfg.Validate() if !tc.expect { diff --git a/internal/envoygateway/config/decoder_test.go b/internal/envoygateway/config/decoder_test.go index 67520f2e5dd..5bbbb959ed7 100644 --- a/internal/envoygateway/config/decoder_test.go +++ b/internal/envoygateway/config/decoder_test.go @@ -347,7 +347,6 @@ func TestDecode(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.in, func(t *testing.T) { eg, err := Decode(tc.in) if tc.expect { diff --git a/internal/extension/registry/extension_manager_test.go b/internal/extension/registry/extension_manager_test.go index f64160ed5ca..a6cd9751d2e 100644 --- a/internal/extension/registry/extension_manager_test.go +++ b/internal/extension/registry/extension_manager_test.go @@ -65,7 +65,6 @@ func TestGetExtensionServerAddress(t *testing.T) { } for _, tc := range tests { - tc := tc t.Run(tc.Name, func(t *testing.T) { out := getExtensionServerAddress(tc.Service) require.Equal(t, tc.Expected, out) diff --git a/internal/gatewayapi/backendtrafficpolicy.go b/internal/gatewayapi/backendtrafficpolicy.go index 120918a8f6a..466f889167a 100644 --- a/internal/gatewayapi/backendtrafficpolicy.go +++ b/internal/gatewayapi/backendtrafficpolicy.go @@ -9,10 +9,8 @@ import ( "errors" "fmt" "math" - "math/big" "sort" "strings" - "time" perr "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -307,60 +305,42 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen errs = errors.Join(errs, err) } } - if policy.Spec.LoadBalancer != nil { - if lb, err = t.buildLoadBalancer(policy); err != nil { - err = perr.WithMessage(err, "LoadBalancer") - errs = errors.Join(errs, err) - } + if lb, err = buildLoadBalancer(policy.Spec.ClusterSettings); err != nil { + err = perr.WithMessage(err, "LoadBalancer") + errs = errors.Join(errs, err) } - if policy.Spec.ProxyProtocol != nil { - pp = t.buildProxyProtocol(policy) - } - if policy.Spec.HealthCheck != nil { - hc = t.buildHealthCheck(policy) - } - if policy.Spec.CircuitBreaker != nil { - if cb, err = t.buildCircuitBreaker(policy); err != nil { - err = perr.WithMessage(err, "CircuitBreaker") - errs = errors.Join(errs, err) - } + pp = buildProxyProtocol(policy.Spec.ClusterSettings) + hc = buildHealthCheck(policy.Spec.ClusterSettings) + if cb, err = buildCircuitBreaker(policy.Spec.ClusterSettings); err != nil { + err = perr.WithMessage(err, "CircuitBreaker") + errs = errors.Join(errs, err) } if policy.Spec.FaultInjection != nil { fi = t.buildFaultInjection(policy) } - if policy.Spec.TCPKeepalive != nil { - if ka, err = t.buildTCPKeepAlive(policy); err != nil { - err = perr.WithMessage(err, "TCPKeepalive") - errs = errors.Join(errs, err) - } + if ka, err = buildTCPKeepAlive(policy.Spec.ClusterSettings); err != nil { + err = perr.WithMessage(err, "TCPKeepalive") + errs = errors.Join(errs, err) } if policy.Spec.Retry != nil { rt = t.buildRetry(policy) } - if policy.Spec.Timeout != nil { - if to, err = t.buildTimeout(policy, nil); err != nil { - err = perr.WithMessage(err, "Timeout") - errs = errors.Join(errs, err) - } + if to, err = buildTimeout(policy.Spec.ClusterSettings, nil); err != nil { + err = perr.WithMessage(err, "Timeout") + errs = errors.Join(errs, err) } - if policy.Spec.Connection != nil { - if bc, err = t.buildBackendConnection(policy); err != nil { - err = perr.WithMessage(err, "BackendConnection") - errs = errors.Join(errs, err) - } + if bc, err = buildBackendConnection(policy.Spec.ClusterSettings); err != nil { + err = perr.WithMessage(err, "BackendConnection") + errs = errors.Join(errs, err) } - if policy.Spec.HTTP2 != nil { - if h2, err = buildIRHTTP2Settings(policy.Spec.HTTP2); err != nil { - err = perr.WithMessage(err, "HTTP2") - errs = errors.Join(errs, err) - } + if h2, err = buildIRHTTP2Settings(policy.Spec.HTTP2); err != nil { + err = perr.WithMessage(err, "HTTP2") + errs = errors.Join(errs, err) } - if policy.Spec.DNS != nil { - ds = t.translateDNS(policy) - } + ds = translateDNS(policy.Spec.ClusterSettings) // Early return if got any errors if errs != nil { @@ -414,17 +394,15 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen Retry: rt, BackendConnection: bc, HTTP2: h2, + DNS: ds, } - r.DNS = ds // Update the Host field in HealthCheck, now that we have access to the Route Hostname. r.Traffic.HealthCheck.SetHTTPHostIfAbsent(r.Hostname) // Some timeout setting originate from the route. - if policy.Spec.Timeout != nil { - if to, err = t.buildTimeout(policy, r); err == nil { - r.Traffic.Timeout = to - } + if to, err = buildTimeout(policy.Spec.ClusterSettings, r); err == nil { + r.Traffic.Timeout = to } if policy.Spec.UseClientProtocol != nil { @@ -461,52 +439,36 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back errs = errors.Join(errs, err) } } - if policy.Spec.LoadBalancer != nil { - if lb, err = t.buildLoadBalancer(policy); err != nil { - err = perr.WithMessage(err, "LoadBalancer") - errs = errors.Join(errs, err) - } - } - if policy.Spec.ProxyProtocol != nil { - pp = t.buildProxyProtocol(policy) + if lb, err = buildLoadBalancer(policy.Spec.ClusterSettings); err != nil { + err = perr.WithMessage(err, "LoadBalancer") + errs = errors.Join(errs, err) } - if policy.Spec.HealthCheck != nil { - hc = t.buildHealthCheck(policy) - } - if policy.Spec.CircuitBreaker != nil { - if cb, err = t.buildCircuitBreaker(policy); err != nil { - err = perr.WithMessage(err, "CircuitBreaker") - errs = errors.Join(errs, err) - } + pp = buildProxyProtocol(policy.Spec.ClusterSettings) + hc = buildHealthCheck(policy.Spec.ClusterSettings) + if cb, err = buildCircuitBreaker(policy.Spec.ClusterSettings); err != nil { + err = perr.WithMessage(err, "CircuitBreaker") + errs = errors.Join(errs, err) } if policy.Spec.FaultInjection != nil { fi = t.buildFaultInjection(policy) } - if policy.Spec.TCPKeepalive != nil { - if ka, err = t.buildTCPKeepAlive(policy); err != nil { - err = perr.WithMessage(err, "TCPKeepalive") - errs = errors.Join(errs, err) - } + if ka, err = buildTCPKeepAlive(policy.Spec.ClusterSettings); err != nil { + err = perr.WithMessage(err, "TCPKeepalive") + errs = errors.Join(errs, err) } if policy.Spec.Retry != nil { rt = t.buildRetry(policy) } - if policy.Spec.Timeout != nil { - if ct, err = t.buildTimeout(policy, nil); err != nil { - err = perr.WithMessage(err, "Timeout") - errs = errors.Join(errs, err) - } + if ct, err = buildTimeout(policy.Spec.ClusterSettings, nil); err != nil { + err = perr.WithMessage(err, "Timeout") + errs = errors.Join(errs, err) } - if policy.Spec.HTTP2 != nil { - if h2, err = buildIRHTTP2Settings(policy.Spec.HTTP2); err != nil { - err = perr.WithMessage(err, "HTTP2") - errs = errors.Join(errs, err) - } + if h2, err = buildIRHTTP2Settings(policy.Spec.HTTP2); err != nil { + err = perr.WithMessage(err, "HTTP2") + errs = errors.Join(errs, err) } - if policy.Spec.DNS != nil { - ds = t.translateDNS(policy) - } + ds = translateDNS(policy.Spec.ClusterSettings) // Early return if got any errors if errs != nil { @@ -529,26 +491,15 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back } for _, r := range tcp.Routes { - // policy(targeting xRoute) has already set it, so we skip it. - if r.LoadBalancer != nil || r.ProxyProtocol != nil || - r.HealthCheck != nil || r.CircuitBreaker != nil || - r.TCPKeepalive != nil || r.Timeout != nil { - continue - } - - r.LoadBalancer = lb - r.ProxyProtocol = pp - r.HealthCheck = hc - r.CircuitBreaker = cb - r.TCPKeepalive = ka - - if r.Timeout == nil { - r.Timeout = ct - } - - if r.DNS == nil { - r.DNS = ds - } + // only set attributes which weren't already set by a more + // specific policy + setIfNil(&r.LoadBalancer, lb) + setIfNil(&r.ProxyProtocol, pp) + setIfNil(&r.HealthCheck, hc) + setIfNil(&r.CircuitBreaker, cb) + setIfNil(&r.TCPKeepalive, ka) + setIfNil(&r.Timeout, ct) + setIfNil(&r.DNS, ds) } } @@ -564,19 +515,11 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back route := udp.Route - // policy(targeting xRoute) has already set it, so we skip it. - if route.LoadBalancer != nil || route.Timeout != nil { - continue - } - - route.LoadBalancer = lb - if route.Timeout == nil { - route.Timeout = ct - } - - if route.DNS == nil { - route.DNS = ds - } + // only set attributes which weren't already set by a more + // specific policy + setIfNil(&route.LoadBalancer, lb) + setIfNil(&route.Timeout, ct) + setIfNil(&route.DNS, ds) } for _, http := range x.HTTP { @@ -604,25 +547,18 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back TCPKeepalive: ka, Retry: rt, HTTP2: h2, - } - - if r.DNS == nil { - r.DNS = ds + DNS: ds, } // Update the Host field in HealthCheck, now that we have access to the Route Hostname. r.Traffic.HealthCheck.SetHTTPHostIfAbsent(r.Hostname) - if policy.Spec.Timeout != nil { - if ct, err = t.buildTimeout(policy, r); err == nil { - r.Traffic.Timeout = ct - } + if ct, err = buildTimeout(policy.Spec.ClusterSettings, r); err == nil { + r.Traffic.Timeout = ct } if policy.Spec.UseClientProtocol != nil { - if r.UseClientProtocol == nil { - r.UseClientProtocol = policy.Spec.UseClientProtocol - } + setIfNil(&r.UseClientProtocol, policy.Spec.UseClientProtocol) } } } @@ -653,7 +589,7 @@ func (t *Translator) buildLocalRateLimit(policy *egv1a1.BackendTrafficPolicy) (* // limit. If no such rule is found, EG uses a default limit of uint32 max. var defaultLimit *ir.RateLimitValue for _, rule := range local.Rules { - if rule.ClientSelectors == nil || len(rule.ClientSelectors) == 0 { + if len(rule.ClientSelectors) == 0 { if defaultLimit != nil { return nil, fmt.Errorf("local rateLimit can not have more than one rule without clientSelectors") } @@ -815,222 +751,6 @@ func buildRateLimitRule(rule egv1a1.RateLimitRule) (*ir.RateLimitRule, error) { return irRule, nil } -func (t *Translator) buildLoadBalancer(policy *egv1a1.BackendTrafficPolicy) (*ir.LoadBalancer, error) { - var lb *ir.LoadBalancer - switch policy.Spec.LoadBalancer.Type { - case egv1a1.ConsistentHashLoadBalancerType: - consistentHash, err := t.buildConsistentHashLoadBalancer(policy) - if err != nil { - return nil, perr.WithMessage(err, "ConsistentHash") - } - - lb = &ir.LoadBalancer{ - ConsistentHash: consistentHash, - } - case egv1a1.LeastRequestLoadBalancerType: - lb = &ir.LoadBalancer{} - if policy.Spec.LoadBalancer.SlowStart != nil { - if policy.Spec.LoadBalancer.SlowStart.Window != nil { - lb.LeastRequest = &ir.LeastRequest{ - SlowStart: &ir.SlowStart{ - Window: policy.Spec.LoadBalancer.SlowStart.Window, - }, - } - } - } - case egv1a1.RandomLoadBalancerType: - lb = &ir.LoadBalancer{ - Random: &ir.Random{}, - } - case egv1a1.RoundRobinLoadBalancerType: - lb = &ir.LoadBalancer{ - RoundRobin: &ir.RoundRobin{ - SlowStart: &ir.SlowStart{}, - }, - } - if policy.Spec.LoadBalancer.SlowStart != nil { - if policy.Spec.LoadBalancer.SlowStart.Window != nil { - lb.RoundRobin = &ir.RoundRobin{ - SlowStart: &ir.SlowStart{ - Window: policy.Spec.LoadBalancer.SlowStart.Window, - }, - } - } - } - } - - return lb, nil -} - -func (t *Translator) buildConsistentHashLoadBalancer(policy *egv1a1.BackendTrafficPolicy) (*ir.ConsistentHash, error) { - consistentHash := &ir.ConsistentHash{} - - if policy.Spec.LoadBalancer.ConsistentHash.TableSize != nil { - tableSize := policy.Spec.LoadBalancer.ConsistentHash.TableSize - - if *tableSize > MaxConsistentHashTableSize || !big.NewInt(int64(*tableSize)).ProbablyPrime(0) { - return nil, fmt.Errorf("invalid TableSize value %d", *tableSize) - } - - consistentHash.TableSize = tableSize - } - - switch policy.Spec.LoadBalancer.ConsistentHash.Type { - case egv1a1.SourceIPConsistentHashType: - consistentHash.SourceIP = ptr.To(true) - case egv1a1.HeaderConsistentHashType: - consistentHash.Header = &ir.Header{ - Name: policy.Spec.LoadBalancer.ConsistentHash.Header.Name, - } - case egv1a1.CookieConsistentHashType: - consistentHash.Cookie = policy.Spec.LoadBalancer.ConsistentHash.Cookie - } - - return consistentHash, nil -} - -func (t *Translator) translateDNS(policy *egv1a1.BackendTrafficPolicy) *ir.DNS { - ds := &ir.DNS{} - if policy.Spec.DNS.RespectDNSTTL != nil { - ds.RespectDNSTTL = policy.Spec.DNS.RespectDNSTTL - } - if policy.Spec.DNS.DNSRefreshRate != nil { - ds.DNSRefreshRate = policy.Spec.DNS.DNSRefreshRate - } - return ds -} - -func (t *Translator) buildProxyProtocol(policy *egv1a1.BackendTrafficPolicy) *ir.ProxyProtocol { - var pp *ir.ProxyProtocol - switch policy.Spec.ProxyProtocol.Version { - case egv1a1.ProxyProtocolVersionV1: - pp = &ir.ProxyProtocol{ - Version: ir.ProxyProtocolVersionV1, - } - case egv1a1.ProxyProtocolVersionV2: - pp = &ir.ProxyProtocol{ - Version: ir.ProxyProtocolVersionV2, - } - } - - return pp -} - -func (t *Translator) buildHealthCheck(policy *egv1a1.BackendTrafficPolicy) *ir.HealthCheck { - 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.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.ActiveHealthCheckerTypeHTTP: - irHC.HTTP = t.buildHTTPActiveHealthChecker(hc.HTTP) - case egv1a1.ActiveHealthCheckerTypeTCP: - irHC.TCP = t.buildTCPActiveHealthChecker(hc.TCP) - } - - return irHC -} - -func (t *Translator) buildHTTPActiveHealthChecker(h *egv1a1.HTTPActiveHealthChecker) *ir.HTTPHealthChecker { - if h == nil { - return nil - } - - irHTTP := &ir.HTTPHealthChecker{ - Path: h.Path, - Method: h.Method, - } - if irHTTP.Method != nil { - *irHTTP.Method = strings.ToUpper(*irHTTP.Method) - } - - // deduplicate http statuses - statusSet := sets.NewInt() - for _, r := range h.ExpectedStatuses { - statusSet.Insert(int(r)) - } - irStatuses := make([]ir.HTTPStatus, 0, statusSet.Len()) - - for _, r := range statusSet.List() { - irStatuses = append(irStatuses, ir.HTTPStatus(r)) - } - irHTTP.ExpectedStatuses = irStatuses - - irHTTP.ExpectedResponse = translateActiveHealthCheckPayload(h.ExpectedResponse) - return irHTTP -} - -func (t *Translator) buildTCPActiveHealthChecker(h *egv1a1.TCPActiveHealthChecker) *ir.TCPHealthChecker { - if h == nil { - return nil - } - - irTCP := &ir.TCPHealthChecker{ - Send: translateActiveHealthCheckPayload(h.Send), - Receive: translateActiveHealthCheckPayload(h.Receive), - } - return irTCP -} - -func translateActiveHealthCheckPayload(p *egv1a1.ActiveHealthCheckPayload) *ir.HealthCheckPayload { - if p == nil { - return nil - } - - irPayload := &ir.HealthCheckPayload{} - switch p.Type { - case egv1a1.ActiveHealthCheckPayloadTypeText: - irPayload.Text = p.Text - case egv1a1.ActiveHealthCheckPayloadTypeBinary: - irPayload.Binary = make([]byte, len(p.Binary)) - copy(irPayload.Binary, p.Binary) - } - - return irPayload -} - func ratelimitUnitToDuration(unit egv1a1.RateLimitUnit) int64 { var seconds int64 @@ -1047,144 +767,6 @@ func ratelimitUnitToDuration(unit egv1a1.RateLimitUnit) int64 { return seconds } -func (t *Translator) buildCircuitBreaker(policy *egv1a1.BackendTrafficPolicy) (*ir.CircuitBreaker, error) { - var cb *ir.CircuitBreaker - pcb := policy.Spec.CircuitBreaker - - if pcb != nil { - cb = &ir.CircuitBreaker{} - - if pcb.MaxConnections != nil { - if ui32, ok := int64ToUint32(*pcb.MaxConnections); ok { - cb.MaxConnections = &ui32 - } else { - return nil, fmt.Errorf("invalid MaxConnections value %d", *pcb.MaxConnections) - } - } - - if pcb.MaxParallelRequests != nil { - if ui32, ok := int64ToUint32(*pcb.MaxParallelRequests); ok { - cb.MaxParallelRequests = &ui32 - } else { - return nil, fmt.Errorf("invalid MaxParallelRequests value %d", *pcb.MaxParallelRequests) - } - } - - if pcb.MaxPendingRequests != nil { - if ui32, ok := int64ToUint32(*pcb.MaxPendingRequests); ok { - cb.MaxPendingRequests = &ui32 - } else { - return nil, fmt.Errorf("invalid MaxPendingRequests value %d", *pcb.MaxPendingRequests) - } - } - - if pcb.MaxParallelRetries != nil { - if ui32, ok := int64ToUint32(*pcb.MaxParallelRetries); ok { - cb.MaxParallelRetries = &ui32 - } else { - return nil, fmt.Errorf("invalid MaxParallelRetries value %d", *pcb.MaxParallelRetries) - } - } - - if pcb.MaxRequestsPerConnection != nil { - if ui32, ok := int64ToUint32(*pcb.MaxRequestsPerConnection); ok { - cb.MaxRequestsPerConnection = &ui32 - } else { - return nil, fmt.Errorf("invalid MaxRequestsPerConnection value %d", *pcb.MaxRequestsPerConnection) - } - } - - } - - return cb, nil -} - -func (t *Translator) buildTimeout(policy *egv1a1.BackendTrafficPolicy, r *ir.HTTPRoute) (*ir.Timeout, error) { - var ( - tto *ir.TCPTimeout - hto *ir.HTTPTimeout - terr bool - errs error - ) - - pto := policy.Spec.Timeout - - if pto.TCP != nil && pto.TCP.ConnectTimeout != nil { - d, err := time.ParseDuration(string(*pto.TCP.ConnectTimeout)) - if err != nil { - terr = true - errs = errors.Join(errs, fmt.Errorf("invalid ConnectTimeout value %s", *pto.TCP.ConnectTimeout)) - } 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 { - terr = true - errs = errors.Join(errs, fmt.Errorf("invalid ConnectionIdleTimeout value %s", *pto.HTTP.ConnectionIdleTimeout)) - } else { - cit = ptr.To(metav1.Duration{Duration: d}) - } - } - - if pto.HTTP.MaxConnectionDuration != nil { - d, err := time.ParseDuration(string(*pto.HTTP.MaxConnectionDuration)) - if err != nil { - terr = true - errs = errors.Join(errs, fmt.Errorf("invalid MaxConnectionDuration value %s", *pto.HTTP.MaxConnectionDuration)) - } else { - mcd = ptr.To(metav1.Duration{Duration: d}) - } - } - - hto = &ir.HTTPTimeout{ - ConnectionIdleTimeout: cit, - MaxConnectionDuration: mcd, - } - } - - // http request timeout is translated during the gateway-api route resource translation - // merge route timeout setting with backendtrafficpolicy timeout settings - if terr { - if r != nil && r.Traffic != nil && r.Traffic.Timeout != nil { - return r.Traffic.Timeout.DeepCopy(), errs - } - } else { - // http request timeout is translated during the gateway-api route resource translation - // merge route timeout setting with backendtrafficpolicy timeout settings - if r != nil && - r.Traffic != nil && - r.Traffic.Timeout != nil && - r.Traffic.Timeout.HTTP != nil && - r.Traffic.Timeout.HTTP.RequestTimeout != nil { - if hto == nil { - hto = &ir.HTTPTimeout{ - RequestTimeout: r.Traffic.Timeout.HTTP.RequestTimeout, - } - } else { - hto.RequestTimeout = r.Traffic.Timeout.HTTP.RequestTimeout - } - } - - if hto != nil || tto != nil { - return &ir.Timeout{ - TCP: tto, - HTTP: hto, - }, nil - } - } - - return nil, errs -} - func int64ToUint32(in int64) (uint32, bool) { if in >= 0 && in <= math.MaxUint32 { return uint32(in), true @@ -1192,31 +774,6 @@ func int64ToUint32(in int64) (uint32, bool) { return 0, false } -func (t *Translator) buildBackendConnection(policy *egv1a1.BackendTrafficPolicy) (*ir.BackendConnection, error) { - var ( - bcIR = &ir.BackendConnection{} - bc = &egv1a1.BackendConnection{} - ) - - if policy.Spec.Connection != nil { - bc = policy.Spec.Connection - - if bc.BufferLimit != nil { - bf, ok := bc.BufferLimit.AsInt64() - if !ok { - return nil, fmt.Errorf("invalid BufferLimit value %s", bc.BufferLimit.String()) - } - if bf < 0 || bf > math.MaxUint32 { - return nil, fmt.Errorf("BufferLimit value %s is out of range", bc.BufferLimit.String()) - } - - bcIR.BufferLimitBytes = ptr.To(uint32(bf)) - } - } - - return bcIR, nil -} - func (t *Translator) buildFaultInjection(policy *egv1a1.BackendTrafficPolicy) *ir.FaultInjection { var fi *ir.FaultInjection if policy.Spec.FaultInjection != nil { @@ -1244,36 +801,6 @@ func (t *Translator) buildFaultInjection(policy *egv1a1.BackendTrafficPolicy) *i return fi } -func (t *Translator) buildTCPKeepAlive(policy *egv1a1.BackendTrafficPolicy) (*ir.TCPKeepalive, error) { - 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 { - return nil, fmt.Errorf("invalid IdleTime value %s", *pka.IdleTime) - } - ka.IdleTime = ptr.To(uint32(d.Seconds())) - } - - if pka.Interval != nil { - d, err := time.ParseDuration(string(*pka.Interval)) - if err != nil { - return nil, fmt.Errorf("invalid Interval value %s", *pka.Interval) - } - ka.Interval = ptr.To(uint32(d.Seconds())) - } - - } - return ka, nil -} - func (t *Translator) buildRetry(policy *egv1a1.BackendTrafficPolicy) *ir.Retry { var rt *ir.Retry if policy.Spec.Retry != nil { diff --git a/internal/gatewayapi/backendtrafficpolicy_test.go b/internal/gatewayapi/backendtrafficpolicy_test.go index d40d1e68c76..ebf721fb07d 100644 --- a/internal/gatewayapi/backendtrafficpolicy_test.go +++ b/internal/gatewayapi/backendtrafficpolicy_test.go @@ -46,7 +46,6 @@ func TestInt64ToUint32(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.Name, func(t *testing.T) { out, success := int64ToUint32(tc.In) require.Equal(t, tc.Out, out) diff --git a/internal/gatewayapi/clienttrafficpolicy.go b/internal/gatewayapi/clienttrafficpolicy.go index 1d7e8e89a84..44d813c255c 100644 --- a/internal/gatewayapi/clienttrafficpolicy.go +++ b/internal/gatewayapi/clienttrafficpolicy.go @@ -18,6 +18,7 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" "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" @@ -417,7 +418,7 @@ func (t *Translator) translateClientTrafficPolicyForListener(policy *egv1a1.Clie } // Translate Proxy Protocol - enableProxyProtocol = buildProxyProtocol(policy.Spec.EnableProxyProtocol) + enableProxyProtocol = ptr.Deref(policy.Spec.EnableProxyProtocol, false) // Translate Client Timeout Settings timeout, err = buildClientTimeout(policy.Spec.Timeout) @@ -432,7 +433,10 @@ func (t *Translator) translateClientTrafficPolicyForListener(policy *egv1a1.Clie translateClientIPDetection(policy.Spec.ClientIPDetection, httpIR) // Translate Header Settings - translateListenerHeaderSettings(policy.Spec.Headers, httpIR) + if err = translateListenerHeaderSettings(policy.Spec.Headers, httpIR); err != nil { + err = perr.WithMessage(err, "Headers") + errs = errors.Join(errs, err) + } // Translate Path Settings translatePathSettings(policy.Spec.Path, httpIR) @@ -604,14 +608,6 @@ func buildClientTimeout(clientTimeout *egv1a1.ClientTimeout) (*ir.ClientTimeout, return irClientTimeout, nil } -func buildProxyProtocol(enableProxyProtocol *bool) bool { - if enableProxyProtocol != nil && *enableProxyProtocol { - return true - } - - return false -} - func translateClientIPDetection(clientIPDetection *egv1a1.ClientIPDetectionSettings, httpIR *ir.HTTPListener) { // Return early if not set if clientIPDetection == nil { @@ -621,9 +617,9 @@ func translateClientIPDetection(clientIPDetection *egv1a1.ClientIPDetectionSetti httpIR.ClientIPDetection = (*ir.ClientIPDetectionSettings)(clientIPDetection) } -func translateListenerHeaderSettings(headerSettings *egv1a1.HeaderSettings, httpIR *ir.HTTPListener) { +func translateListenerHeaderSettings(headerSettings *egv1a1.HeaderSettings, httpIR *ir.HTTPListener) error { if headerSettings == nil { - return + return nil } httpIR.Headers = &ir.HeaderSettings{ EnableEnvoyHeaders: ptr.Deref(headerSettings.EnableEnvoyHeaders, false), @@ -642,6 +638,16 @@ func translateListenerHeaderSettings(headerSettings *egv1a1.HeaderSettings, http httpIR.Headers.XForwardedClientCert.CertDetailsToAdd = headerSettings.XForwardedClientCert.CertDetailsToAdd } } + + if headerSettings.EarlyRequestHeaders != nil { + headersToAdd, headersToRemove, err := translateEarlyRequestHeaders(headerSettings.EarlyRequestHeaders) + if err != nil { + return err + } + httpIR.Headers.EarlyAddRequestHeaders = headersToAdd + httpIR.Headers.EarlyRemoveRequestHeaders = headersToRemove + } + return nil } func translateHTTP1Settings(http1Settings *egv1a1.HTTP1Settings, httpIR *ir.HTTPListener) error { @@ -877,3 +883,130 @@ func buildConnection(connection *egv1a1.ClientConnection) (*ir.ClientConnection, return irConnection, nil } + +func translateEarlyRequestHeaders(headerModifier *gwapiv1.HTTPHeaderFilter) ([]ir.AddHeader, []string, error) { + // Make sure the header modifier config actually exists + if headerModifier == nil { + return nil, nil, nil + } + var errs error + emptyFilterConfig := true // keep track of whether the provided config is empty or not + + var AddRequestHeaders []ir.AddHeader + var RemoveRequestHeaders []string + + // Add request headers + if headersToAdd := headerModifier.Add; headersToAdd != nil { + if len(headersToAdd) > 0 { + emptyFilterConfig = false + } + for _, addHeader := range headersToAdd { + emptyFilterConfig = false + if addHeader.Name == "" { + errs = errors.Join(errs, fmt.Errorf("EarlyRequestHeaders cannot add a header with an empty name")) + // try to process the rest of the headers and produce a valid config. + continue + } + // Per Gateway API specification on HTTPHeaderName, : and / are invalid characters in header names + if strings.ContainsAny(string(addHeader.Name), "/:") { + errs = errors.Join(errs, fmt.Errorf("EarlyRequestHeaders Filter cannot set headers with a '/' or ':' character in them. Header: %q", string(addHeader.Name))) + continue + } + // Check if the header is a duplicate + headerKey := string(addHeader.Name) + canAddHeader := true + for _, h := range AddRequestHeaders { + if strings.EqualFold(h.Name, headerKey) { + canAddHeader = false + break + } + } + + if !canAddHeader { + continue + } + + newHeader := ir.AddHeader{ + Name: headerKey, + Append: true, + Value: strings.Split(addHeader.Value, ","), + } + + AddRequestHeaders = append(AddRequestHeaders, newHeader) + } + } + + // Set headers + if headersToSet := headerModifier.Set; headersToSet != nil { + if len(headersToSet) > 0 { + emptyFilterConfig = false + } + for _, setHeader := range headersToSet { + + if setHeader.Name == "" { + errs = errors.Join(errs, fmt.Errorf("EarlyRequestHeaders cannot set a header with an empty name")) + continue + } + // Per Gateway API specification on HTTPHeaderName, : and / are invalid characters in header names + if strings.ContainsAny(string(setHeader.Name), "/:") { + errs = errors.Join(errs, fmt.Errorf("EarlyRequestHeaders cannot set headers with a '/' or ':' character in them. Header: '%s'", string(setHeader.Name))) + continue + } + + // Check if the header to be set has already been configured + headerKey := string(setHeader.Name) + canAddHeader := true + for _, h := range AddRequestHeaders { + if strings.EqualFold(h.Name, headerKey) { + canAddHeader = false + break + } + } + if !canAddHeader { + continue + } + newHeader := ir.AddHeader{ + Name: string(setHeader.Name), + Append: false, + Value: strings.Split(setHeader.Value, ","), + } + + AddRequestHeaders = append(AddRequestHeaders, newHeader) + } + } + + // Remove request headers + // As far as Envoy is concerned, it is ok to configure a header to be added/set and also in the list of + // headers to remove. It will remove the original header if present and then add/set the header after. + if headersToRemove := headerModifier.Remove; headersToRemove != nil { + if len(headersToRemove) > 0 { + emptyFilterConfig = false + } + for _, removedHeader := range headersToRemove { + if removedHeader == "" { + errs = errors.Join(errs, fmt.Errorf("EarlyRequestHeaders cannot remove a header with an empty name")) + continue + } + + canRemHeader := true + for _, h := range RemoveRequestHeaders { + if strings.EqualFold(h, removedHeader) { + canRemHeader = false + break + } + } + if !canRemHeader { + continue + } + + RemoveRequestHeaders = append(RemoveRequestHeaders, removedHeader) + } + } + + // Update the status if the filter failed to configure any valid headers to add/remove + if len(AddRequestHeaders) == 0 && len(RemoveRequestHeaders) == 0 && !emptyFilterConfig { + errs = errors.Join(errs, fmt.Errorf("EarlyRequestHeaders did not provide valid configuration to add/set/remove any headers")) + } + + return AddRequestHeaders, RemoveRequestHeaders, errs +} diff --git a/internal/gatewayapi/clustersettings.go b/internal/gatewayapi/clustersettings.go new file mode 100644 index 00000000000..1d5c1a3d6f8 --- /dev/null +++ b/internal/gatewayapi/clustersettings.go @@ -0,0 +1,504 @@ +// 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 gatewayapi + +import ( + "errors" + "fmt" + "math" + "math/big" + "strings" + "time" + + perr "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/utils/ptr" + + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" + "github.com/envoyproxy/gateway/internal/ir" +) + +func translateTrafficFeatures(policy *egv1a1.ClusterSettings) (*ir.TrafficFeatures, error) { + if policy == nil { + return nil, nil + } + ret := &ir.TrafficFeatures{} + + if timeout, err := buildTimeout(*policy, nil); err != nil { + return nil, err + } else { + ret.Timeout = timeout + } + + if bc, err := buildBackendConnection(*policy); err != nil { + return nil, err + } else { + ret.BackendConnection = bc + } + + if ka, err := buildTCPKeepAlive(*policy); err != nil { + return nil, err + } else { + ret.TCPKeepalive = ka + } + + if cb, err := buildCircuitBreaker(*policy); err != nil { + return nil, err + } else { + ret.CircuitBreaker = cb + } + + if lb, err := buildLoadBalancer(*policy); err != nil { + return nil, err + } else { + ret.LoadBalancer = lb + } + + ret.ProxyProtocol = buildProxyProtocol(*policy) + + ret.HealthCheck = buildHealthCheck(*policy) + + ret.DNS = translateDNS(*policy) + + if h2, err := buildIRHTTP2Settings(policy.HTTP2); err != nil { + return nil, err + } else { + ret.HTTP2 = h2 + } + + // If nothing was set in any of the above calls, return nil instead of an empty + // container + var empty ir.TrafficFeatures + if empty == *ret { + ret = nil + } + + return ret, nil +} + +func buildTimeout(policy egv1a1.ClusterSettings, r *ir.HTTPRoute) (*ir.Timeout, error) { + if policy.Timeout == nil { + return nil, nil + } + var ( + tto *ir.TCPTimeout + hto *ir.HTTPTimeout + terr bool + errs error + ) + + pto := policy.Timeout + + if pto.TCP != nil && pto.TCP.ConnectTimeout != nil { + d, err := time.ParseDuration(string(*pto.TCP.ConnectTimeout)) + if err != nil { + terr = true + errs = errors.Join(errs, fmt.Errorf("invalid ConnectTimeout value %s", *pto.TCP.ConnectTimeout)) + } 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 { + terr = true + errs = errors.Join(errs, fmt.Errorf("invalid ConnectionIdleTimeout value %s", *pto.HTTP.ConnectionIdleTimeout)) + } else { + cit = ptr.To(metav1.Duration{Duration: d}) + } + } + + if pto.HTTP.MaxConnectionDuration != nil { + d, err := time.ParseDuration(string(*pto.HTTP.MaxConnectionDuration)) + if err != nil { + terr = true + errs = errors.Join(errs, fmt.Errorf("invalid MaxConnectionDuration value %s", *pto.HTTP.MaxConnectionDuration)) + } else { + mcd = ptr.To(metav1.Duration{Duration: d}) + } + } + + hto = &ir.HTTPTimeout{ + ConnectionIdleTimeout: cit, + MaxConnectionDuration: mcd, + } + } + + // http request timeout is translated during the gateway-api route resource translation + // merge route timeout setting with backendtrafficpolicy timeout settings + if terr { + if r != nil && r.Traffic != nil && r.Traffic.Timeout != nil { + return r.Traffic.Timeout.DeepCopy(), errs + } + } else { + // http request timeout is translated during the gateway-api route resource translation + // merge route timeout setting with backendtrafficpolicy timeout settings + if r != nil && + r.Traffic != nil && + r.Traffic.Timeout != nil && + r.Traffic.Timeout.HTTP != nil && + r.Traffic.Timeout.HTTP.RequestTimeout != nil { + if hto == nil { + hto = &ir.HTTPTimeout{ + RequestTimeout: r.Traffic.Timeout.HTTP.RequestTimeout, + } + } else { + hto.RequestTimeout = r.Traffic.Timeout.HTTP.RequestTimeout + } + } + + if hto != nil || tto != nil { + return &ir.Timeout{ + TCP: tto, + HTTP: hto, + }, nil + } + } + + return nil, errs +} + +func buildBackendConnection(policy egv1a1.ClusterSettings) (*ir.BackendConnection, error) { + if policy.Connection == nil { + return nil, nil + } + var ( + bcIR = &ir.BackendConnection{} + bc = &egv1a1.BackendConnection{} + ) + + if policy.Connection != nil { + bc = policy.Connection + + if bc.BufferLimit != nil { + bf, ok := bc.BufferLimit.AsInt64() + if !ok { + return nil, fmt.Errorf("invalid BufferLimit value %s", bc.BufferLimit.String()) + } + if bf < 0 || bf > math.MaxUint32 { + return nil, fmt.Errorf("BufferLimit value %s is out of range", bc.BufferLimit.String()) + } + + bcIR.BufferLimitBytes = ptr.To(uint32(bf)) + } + } + + return bcIR, nil +} + +func buildTCPKeepAlive(policy egv1a1.ClusterSettings) (*ir.TCPKeepalive, error) { + if policy.TCPKeepalive == nil { + return nil, nil + } + + pka := policy.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 { + return nil, fmt.Errorf("invalid IdleTime value %s", *pka.IdleTime) + } + ka.IdleTime = ptr.To(uint32(d.Seconds())) + } + + if pka.Interval != nil { + d, err := time.ParseDuration(string(*pka.Interval)) + if err != nil { + return nil, fmt.Errorf("invalid Interval value %s", *pka.Interval) + } + ka.Interval = ptr.To(uint32(d.Seconds())) + } + return ka, nil +} + +func buildCircuitBreaker(policy egv1a1.ClusterSettings) (*ir.CircuitBreaker, error) { + if policy.CircuitBreaker == nil { + return nil, nil + } + + var cb *ir.CircuitBreaker + pcb := policy.CircuitBreaker + + if pcb != nil { + cb = &ir.CircuitBreaker{} + + if pcb.MaxConnections != nil { + if ui32, ok := int64ToUint32(*pcb.MaxConnections); ok { + cb.MaxConnections = &ui32 + } else { + return nil, fmt.Errorf("invalid MaxConnections value %d", *pcb.MaxConnections) + } + } + + if pcb.MaxParallelRequests != nil { + if ui32, ok := int64ToUint32(*pcb.MaxParallelRequests); ok { + cb.MaxParallelRequests = &ui32 + } else { + return nil, fmt.Errorf("invalid MaxParallelRequests value %d", *pcb.MaxParallelRequests) + } + } + + if pcb.MaxPendingRequests != nil { + if ui32, ok := int64ToUint32(*pcb.MaxPendingRequests); ok { + cb.MaxPendingRequests = &ui32 + } else { + return nil, fmt.Errorf("invalid MaxPendingRequests value %d", *pcb.MaxPendingRequests) + } + } + + if pcb.MaxParallelRetries != nil { + if ui32, ok := int64ToUint32(*pcb.MaxParallelRetries); ok { + cb.MaxParallelRetries = &ui32 + } else { + return nil, fmt.Errorf("invalid MaxParallelRetries value %d", *pcb.MaxParallelRetries) + } + } + + if pcb.MaxRequestsPerConnection != nil { + if ui32, ok := int64ToUint32(*pcb.MaxRequestsPerConnection); ok { + cb.MaxRequestsPerConnection = &ui32 + } else { + return nil, fmt.Errorf("invalid MaxRequestsPerConnection value %d", *pcb.MaxRequestsPerConnection) + } + } + + } + + return cb, nil +} + +func buildLoadBalancer(policy egv1a1.ClusterSettings) (*ir.LoadBalancer, error) { + if policy.LoadBalancer == nil { + return nil, nil + } + var lb *ir.LoadBalancer + switch policy.LoadBalancer.Type { + case egv1a1.ConsistentHashLoadBalancerType: + consistentHash, err := buildConsistentHashLoadBalancer(*policy.LoadBalancer) + if err != nil { + return nil, perr.WithMessage(err, "ConsistentHash") + } + + lb = &ir.LoadBalancer{ + ConsistentHash: consistentHash, + } + case egv1a1.LeastRequestLoadBalancerType: + lb = &ir.LoadBalancer{} + if policy.LoadBalancer.SlowStart != nil { + if policy.LoadBalancer.SlowStart.Window != nil { + lb.LeastRequest = &ir.LeastRequest{ + SlowStart: &ir.SlowStart{ + Window: policy.LoadBalancer.SlowStart.Window, + }, + } + } + } + case egv1a1.RandomLoadBalancerType: + lb = &ir.LoadBalancer{ + Random: &ir.Random{}, + } + case egv1a1.RoundRobinLoadBalancerType: + lb = &ir.LoadBalancer{ + RoundRobin: &ir.RoundRobin{ + SlowStart: &ir.SlowStart{}, + }, + } + if policy.LoadBalancer.SlowStart != nil { + if policy.LoadBalancer.SlowStart.Window != nil { + lb.RoundRobin = &ir.RoundRobin{ + SlowStart: &ir.SlowStart{ + Window: policy.LoadBalancer.SlowStart.Window, + }, + } + } + } + } + + return lb, nil +} + +func buildConsistentHashLoadBalancer(policy egv1a1.LoadBalancer) (*ir.ConsistentHash, error) { + consistentHash := &ir.ConsistentHash{} + + if policy.ConsistentHash.TableSize != nil { + tableSize := policy.ConsistentHash.TableSize + + if *tableSize > MaxConsistentHashTableSize || !big.NewInt(int64(*tableSize)).ProbablyPrime(0) { + return nil, fmt.Errorf("invalid TableSize value %d", *tableSize) + } + + consistentHash.TableSize = tableSize + } + + switch policy.ConsistentHash.Type { + case egv1a1.SourceIPConsistentHashType: + consistentHash.SourceIP = ptr.To(true) + case egv1a1.HeaderConsistentHashType: + consistentHash.Header = &ir.Header{ + Name: policy.ConsistentHash.Header.Name, + } + case egv1a1.CookieConsistentHashType: + consistentHash.Cookie = policy.ConsistentHash.Cookie + } + + return consistentHash, nil +} + +func buildProxyProtocol(policy egv1a1.ClusterSettings) *ir.ProxyProtocol { + if policy.ProxyProtocol == nil { + return nil + } + var pp *ir.ProxyProtocol + switch policy.ProxyProtocol.Version { + case egv1a1.ProxyProtocolVersionV1: + pp = &ir.ProxyProtocol{ + Version: ir.ProxyProtocolVersionV1, + } + case egv1a1.ProxyProtocolVersionV2: + pp = &ir.ProxyProtocol{ + Version: ir.ProxyProtocolVersionV2, + } + } + + return pp +} + +func buildHealthCheck(policy egv1a1.ClusterSettings) *ir.HealthCheck { + if policy.HealthCheck == nil { + return nil + } + + irhc := &ir.HealthCheck{} + irhc.Passive = buildPassiveHealthCheck(*policy.HealthCheck) + irhc.Active = buildActiveHealthCheck(*policy.HealthCheck) + + return irhc +} + +func buildPassiveHealthCheck(policy egv1a1.HealthCheck) *ir.OutlierDetection { + if policy.Passive == nil { + return nil + } + + hc := policy.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 buildActiveHealthCheck(policy egv1a1.HealthCheck) *ir.ActiveHealthCheck { + if policy.Active == nil { + return nil + } + + hc := policy.Active + irHC := &ir.ActiveHealthCheck{ + Timeout: hc.Timeout, + Interval: hc.Interval, + UnhealthyThreshold: hc.UnhealthyThreshold, + HealthyThreshold: hc.HealthyThreshold, + } + switch hc.Type { + case egv1a1.ActiveHealthCheckerTypeHTTP: + irHC.HTTP = buildHTTPActiveHealthChecker(hc.HTTP) + case egv1a1.ActiveHealthCheckerTypeTCP: + irHC.TCP = buildTCPActiveHealthChecker(hc.TCP) + case egv1a1.ActiveHealthCheckerTypeGRPC: + irHC.GRPC = &ir.GRPCHealthChecker{ + Service: ptr.Deref(hc.GRPC, egv1a1.GRPCActiveHealthChecker{}).Service, + } + } + + return irHC +} + +func buildHTTPActiveHealthChecker(h *egv1a1.HTTPActiveHealthChecker) *ir.HTTPHealthChecker { + if h == nil { + return nil + } + + irHTTP := &ir.HTTPHealthChecker{ + Path: h.Path, + Method: h.Method, + } + if irHTTP.Method != nil { + *irHTTP.Method = strings.ToUpper(*irHTTP.Method) + } + + // deduplicate http statuses + statusSet := sets.NewInt() + for _, r := range h.ExpectedStatuses { + statusSet.Insert(int(r)) + } + irStatuses := make([]ir.HTTPStatus, 0, statusSet.Len()) + + for _, r := range statusSet.List() { + irStatuses = append(irStatuses, ir.HTTPStatus(r)) + } + irHTTP.ExpectedStatuses = irStatuses + + irHTTP.ExpectedResponse = translateActiveHealthCheckPayload(h.ExpectedResponse) + return irHTTP +} + +func buildTCPActiveHealthChecker(h *egv1a1.TCPActiveHealthChecker) *ir.TCPHealthChecker { + if h == nil { + return nil + } + + irTCP := &ir.TCPHealthChecker{ + Send: translateActiveHealthCheckPayload(h.Send), + Receive: translateActiveHealthCheckPayload(h.Receive), + } + return irTCP +} + +func translateActiveHealthCheckPayload(p *egv1a1.ActiveHealthCheckPayload) *ir.HealthCheckPayload { + if p == nil { + return nil + } + + irPayload := &ir.HealthCheckPayload{} + switch p.Type { + case egv1a1.ActiveHealthCheckPayloadTypeText: + irPayload.Text = p.Text + case egv1a1.ActiveHealthCheckPayloadTypeBinary: + irPayload.Binary = make([]byte, len(p.Binary)) + copy(irPayload.Binary, p.Binary) + } + + return irPayload +} + +func translateDNS(policy egv1a1.ClusterSettings) *ir.DNS { + if policy.DNS == nil { + return nil + } + return &ir.DNS{ + RespectDNSTTL: policy.DNS.RespectDNSTTL, + DNSRefreshRate: policy.DNS.DNSRefreshRate, + } +} diff --git a/internal/gatewayapi/conformance/suite.go b/internal/gatewayapi/conformance/suite.go index 4637e023779..4fafa008983 100644 --- a/internal/gatewayapi/conformance/suite.go +++ b/internal/gatewayapi/conformance/suite.go @@ -15,7 +15,6 @@ import ( // SkipTests is a list of tests that are skipped in the conformance suite. var SkipTests = []suite.ConformanceTest{ tests.GatewayStaticAddresses, - tests.GatewayHTTPListenerIsolation, // https://github.com/envoyproxy/gateway/issues/3352 } func skipTestsShortNames(skipTests []suite.ConformanceTest) []string { diff --git a/internal/gatewayapi/envoyextensionpolicy.go b/internal/gatewayapi/envoyextensionpolicy.go index 5f871a6f8c0..5cbe148db2c 100644 --- a/internal/gatewayapi/envoyextensionpolicy.go +++ b/internal/gatewayapi/envoyextensionpolicy.go @@ -439,7 +439,7 @@ func (t *Translator) buildExtProc( } ds, err = t.processExtServiceDestination( - &extProc.BackendRefs[i].BackendObjectReference, + &extProc.BackendRefs[i], policyNamespacedName, egv1a1.KindEnvoyExtensionPolicy, ir.GRPC, @@ -471,9 +471,15 @@ func (t *Translator) buildExtProc( NamespaceDerefOr(extProc.BackendRefs[0].Namespace, policyNamespacedName.Namespace)) } + traffic, err := translateTrafficFeatures(extProc.BackendCluster.BackendSettings) + if err != nil { + return nil, err + } + extProcIR := &ir.ExtProc{ Name: name, Destination: rd, + Traffic: traffic, Authority: authority, } diff --git a/internal/gatewayapi/envoypatchpolicy.go b/internal/gatewayapi/envoypatchpolicy.go index 9ea9102ac76..5d2480f5d23 100644 --- a/internal/gatewayapi/envoypatchpolicy.go +++ b/internal/gatewayapi/envoypatchpolicy.go @@ -114,6 +114,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.JSONPath = patch.Operation.JSONPath irPatch.Operation.From = patch.Operation.From irPatch.Operation.Value = patch.Operation.Value diff --git a/internal/gatewayapi/ext_service.go b/internal/gatewayapi/ext_service.go index d0c50e5f97e..65cf4c2cce8 100644 --- a/internal/gatewayapi/ext_service.go +++ b/internal/gatewayapi/ext_service.go @@ -21,7 +21,7 @@ import ( // TODO: zhaohuabing combine this function with the one in the route translator func (t *Translator) processExtServiceDestination( - backendRef *gwapiv1.BackendObjectReference, + backendRef *egv1a1.BackendRef, policyNamespacedName types.NamespacedName, policyKind string, protocol ir.AppProtocol, @@ -37,12 +37,12 @@ func (t *Translator) processExtServiceDestination( switch KindDerefOr(backendRef.Kind, KindService) { case KindService: - ds = t.processServiceDestinationSetting(*backendRef, backendNamespace, protocol, resources, envoyProxy) + ds = t.processServiceDestinationSetting(backendRef.BackendObjectReference, backendNamespace, protocol, resources, envoyProxy) case egv1a1.KindBackend: if !t.BackendEnabled { return nil, fmt.Errorf("resource %s of type Backend cannot be used since Backend is disabled in Envoy Gateway configuration", string(backendRef.Name)) } - ds = t.processBackendDestinationSetting(*backendRef, backendNamespace, resources) + ds = t.processBackendDestinationSetting(backendRef.BackendObjectReference, backendNamespace, resources) ds.Protocol = protocol } @@ -58,7 +58,7 @@ func (t *Translator) processExtServiceDestination( } backendTLS = t.applyBackendTLSSetting( - *backendRef, + backendRef.BackendObjectReference, backendNamespace, // Gateway is not the appropriate parent reference here because the owner // of the BackendRef is the policy, and there is no hierarchy @@ -78,7 +78,12 @@ func (t *Translator) processExtServiceDestination( // TODO: support weighted non-xRoute backends ds.Weight = ptr.To(uint32(1)) - + if backendRef.Failover != nil { + // set only the secondary priority, the backend defaults to a primary priority if unset. + if ptr.Deref(backendRef.Failover, false) { + ds.Priority = ptr.To(uint32(1)) + } + } return ds, nil } diff --git a/internal/gatewayapi/filters.go b/internal/gatewayapi/filters.go index b3d2ddb4074..aecc2e81131 100644 --- a/internal/gatewayapi/filters.go +++ b/internal/gatewayapi/filters.go @@ -445,7 +445,7 @@ func (t *Translator) processRequestHeaderModifierFilter( newHeader := ir.AddHeader{ Name: headerKey, Append: true, - Value: addHeader.Value, + Value: strings.Split(addHeader.Value, ","), } filterContext.AddRequestHeaders = append(filterContext.AddRequestHeaders, newHeader) @@ -500,7 +500,7 @@ func (t *Translator) processRequestHeaderModifierFilter( newHeader := ir.AddHeader{ Name: string(setHeader.Name), Append: false, - Value: setHeader.Value, + Value: strings.Split(setHeader.Value, ","), } filterContext.AddRequestHeaders = append(filterContext.AddRequestHeaders, newHeader) @@ -617,7 +617,7 @@ func (t *Translator) processResponseHeaderModifierFilter( newHeader := ir.AddHeader{ Name: headerKey, Append: true, - Value: addHeader.Value, + Value: strings.Split(addHeader.Value, ","), } filterContext.AddResponseHeaders = append(filterContext.AddResponseHeaders, newHeader) @@ -672,7 +672,7 @@ func (t *Translator) processResponseHeaderModifierFilter( newHeader := ir.AddHeader{ Name: string(setHeader.Name), Append: false, - Value: setHeader.Value, + Value: strings.Split(setHeader.Value, ","), } filterContext.AddResponseHeaders = append(filterContext.AddResponseHeaders, newHeader) diff --git a/internal/gatewayapi/helpers.go b/internal/gatewayapi/helpers.go index 22c81032ebb..52df40f4736 100644 --- a/internal/gatewayapi/helpers.go +++ b/internal/gatewayapi/helpers.go @@ -262,12 +262,12 @@ func servicePortToContainerPort(servicePort int32, envoyProxy *egv1a1.EnvoyProxy return servicePort } -// computeHosts returns a list of the intersecting hostnames between the route -// and the listener. -func computeHosts(routeHostnames []string, listenerHostname *gwapiv1.Hostname) []string { +// computeHosts returns a list of intersecting listener hostnames and route hostnames +// that don't intersect with other listener hostnames. +func computeHosts(routeHostnames []string, listenerContext *ListenerContext) []string { var listenerHostnameVal string - if listenerHostname != nil { - listenerHostnameVal = string(*listenerHostname) + if listenerContext != nil && listenerContext.Hostname != nil { + listenerHostnameVal = string(*listenerContext.Hostname) } // No route hostnames specified: use the listener hostname if specified, @@ -280,8 +280,9 @@ func computeHosts(routeHostnames []string, listenerHostname *gwapiv1.Hostname) [ return []string{"*"} } - var hostnames []string + hostnamesSet := sets.NewString() + // Find intersecting hostnames for i := range routeHostnames { routeHostname := routeHostnames[i] @@ -290,28 +291,47 @@ func computeHosts(routeHostnames []string, listenerHostname *gwapiv1.Hostname) [ switch { // No listener hostname: use the route hostname. case len(listenerHostnameVal) == 0: - hostnames = append(hostnames, routeHostname) + hostnamesSet.Insert(routeHostname) // Listener hostname matches the route hostname: use it. case listenerHostnameVal == routeHostname: - hostnames = append(hostnames, routeHostname) + hostnamesSet.Insert(routeHostname) // Listener has a wildcard hostname: check if the route hostname matches. case strings.HasPrefix(listenerHostnameVal, "*"): if hostnameMatchesWildcardHostname(routeHostname, listenerHostnameVal) { - hostnames = append(hostnames, routeHostname) + hostnamesSet.Insert(routeHostname) } // Route has a wildcard hostname: check if the listener hostname matches. case strings.HasPrefix(routeHostname, "*"): if hostnameMatchesWildcardHostname(listenerHostnameVal, routeHostname) { - hostnames = append(hostnames, listenerHostnameVal) + hostnamesSet.Insert(listenerHostnameVal) } } } - return hostnames + // Filter out route hostnames that intersect with other listener hostnames + var listeners []*ListenerContext + if listenerContext != nil && listenerContext.gateway != nil { + listeners = listenerContext.gateway.listeners + } + + for _, listener := range listeners { + if listenerContext == listener { + continue + } + if listenerContext != nil && listenerContext.Port != listener.Port { + continue + } + if listener.Hostname == nil { + continue + } + hostnamesSet.Delete(string(*listener.Hostname)) + } + + return hostnamesSet.List() } // hostnameMatchesWildcardHostname returns true if hostname has the non-wildcard @@ -560,3 +580,10 @@ func getPolicyTargetRefs[T client.Object](policy egv1a1.PolicyTargetReferences, return ret } + +// Sets *target to value if and only if *target is nil +func setIfNil[T any](target **T, value *T) { + if *target == nil { + *target = value + } +} diff --git a/internal/gatewayapi/helpers_test.go b/internal/gatewayapi/helpers_test.go index a6469715f4d..5698867c3ca 100644 --- a/internal/gatewayapi/helpers_test.go +++ b/internal/gatewayapi/helpers_test.go @@ -97,7 +97,6 @@ func TestValidateGRPCFilterRef(t *testing.T) { }, } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { err := ValidateGRPCRouteFilter(tc.filter, schema.GroupKind{Group: "example.io", Kind: "Foo"}) if tc.expected { @@ -189,7 +188,6 @@ func TestValidateHTTPFilterRef(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { err := ValidateHTTPRouteFilter(tc.filter, schema.GroupKind{Group: "example.io", Kind: "Foo"}) if tc.expected { @@ -479,7 +477,6 @@ func TestGetPolicyTargetRefs(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { results := getPolicyTargetRefs(tc.policy, tc.targets) require.ElementsMatch(t, results, tc.results) diff --git a/internal/gatewayapi/http.go b/internal/gatewayapi/http.go index 95b0cd6310e..e54b3f761d7 100644 --- a/internal/gatewayapi/http.go +++ b/internal/gatewayapi/http.go @@ -23,6 +23,9 @@ const ( ) func buildIRHTTP2Settings(http2Settings *egv1a1.HTTP2Settings) (*ir.HTTP2Settings, error) { + if http2Settings == nil { + return nil, nil + } var ( http2 = &ir.HTTP2Settings{} errs error diff --git a/internal/gatewayapi/listener.go b/internal/gatewayapi/listener.go index adbd302b957..b63645a85e1 100644 --- a/internal/gatewayapi/listener.go +++ b/internal/gatewayapi/listener.go @@ -313,7 +313,7 @@ func (t *Translator) processAccessLog(envoyproxy *egv1a1.EnvoyProxy, resources * } // TODO: how to get authority from the backendRefs? - ds, err := t.processBackendRefs(sink.ALS.BackendRefs, envoyproxy.Namespace, resources, envoyproxy) + ds, traffic, err := t.processBackendRefs(sink.ALS.BackendCluster, envoyproxy.Namespace, resources, envoyproxy) if err != nil { return nil, err } @@ -324,6 +324,7 @@ func (t *Translator) processAccessLog(envoyproxy *egv1a1.EnvoyProxy, resources * Name: fmt.Sprintf("accesslog_als_%d_%d", i, j), // TODO: rename this, so that we can share backend with tracing? Settings: ds, }, + Traffic: traffic, Type: sink.ALS.Type, CELMatches: validExprs, } @@ -350,20 +351,20 @@ func (t *Translator) processAccessLog(envoyproxy *egv1a1.EnvoyProxy, resources * continue } - // TODO: remove support for Host/Port in v1.2 - al := &ir.OpenTelemetryAccessLog{ - CELMatches: validExprs, - Resources: sink.OpenTelemetry.Resources, - } - // TODO: how to get authority from the backendRefs? - ds, err := t.processBackendRefs(sink.OpenTelemetry.BackendRefs, envoyproxy.Namespace, resources, envoyproxy) + ds, traffic, err := t.processBackendRefs(sink.OpenTelemetry.BackendCluster, envoyproxy.Namespace, resources, envoyproxy) if err != nil { return nil, err } - al.Destination = ir.RouteDestination{ - Name: fmt.Sprintf("accesslog_otel_%d_%d", i, j), // TODO: rename this, so that we can share backend with tracing? - Settings: ds, + // TODO: remove support for Host/Port in v1.2 + al := &ir.OpenTelemetryAccessLog{ + CELMatches: validExprs, + Resources: sink.OpenTelemetry.Resources, + Destination: ir.RouteDestination{ + Name: fmt.Sprintf("accesslog_otel_%d_%d", i, j), // TODO: rename this, so that we can share backend with tracing? + Settings: ds, + }, + Traffic: traffic, } if len(ds) == 0 { @@ -401,7 +402,7 @@ func (t *Translator) processTracing(gw *gwapiv1.Gateway, envoyproxy *egv1a1.Envo tracing := envoyproxy.Spec.Telemetry.Tracing // TODO: how to get authority from the backendRefs? - ds, err := t.processBackendRefs(tracing.Provider.BackendRefs, envoyproxy.Namespace, resources, envoyproxy) + ds, traffic, err := t.processBackendRefs(tracing.Provider.BackendCluster, envoyproxy.Namespace, resources, envoyproxy) if err != nil { return nil, err } @@ -440,6 +441,7 @@ func (t *Translator) processTracing(gw *gwapiv1.Gateway, envoyproxy *egv1a1.Envo Settings: ds, }, Provider: tracing.Provider, + Traffic: traffic, }, nil } @@ -455,7 +457,7 @@ func (t *Translator) processMetrics(envoyproxy *egv1a1.EnvoyProxy, resources *Re continue } - _, err := t.processBackendRefs(sink.OpenTelemetry.BackendRefs, envoyproxy.Namespace, resources, envoyproxy) + _, _, err := t.processBackendRefs(sink.OpenTelemetry.BackendCluster, envoyproxy.Namespace, resources, envoyproxy) if err != nil { return nil, err } @@ -467,25 +469,29 @@ func (t *Translator) processMetrics(envoyproxy *egv1a1.EnvoyProxy, resources *Re }, nil } -func (t *Translator) processBackendRefs(backendRefs []egv1a1.BackendRef, namespace string, resources *Resources, envoyProxy *egv1a1.EnvoyProxy) ([]*ir.DestinationSetting, error) { - result := make([]*ir.DestinationSetting, 0, len(backendRefs)) - for _, ref := range backendRefs { +func (t *Translator) processBackendRefs(backendCluster egv1a1.BackendCluster, namespace string, resources *Resources, envoyProxy *egv1a1.EnvoyProxy) ([]*ir.DestinationSetting, *ir.TrafficFeatures, error) { + traffic, err := translateTrafficFeatures(backendCluster.BackendSettings) + if err != nil { + return nil, nil, err + } + result := make([]*ir.DestinationSetting, 0, len(backendCluster.BackendRefs)) + for _, ref := range backendCluster.BackendRefs { ns := NamespaceDerefOr(ref.Namespace, namespace) kind := KindDerefOr(ref.Kind, KindService) if kind != KindService { - return nil, errors.New("only service kind is supported for backendRefs") + return nil, nil, errors.New("only service kind is supported for backendRefs") } if err := validateBackendService(ref.BackendObjectReference, resources, ns, corev1.ProtocolTCP); err != nil { - return nil, err + return nil, nil, err } ds := t.processServiceDestinationSetting(ref.BackendObjectReference, ns, ir.TCP, resources, envoyProxy) result = append(result, ds) } if len(result) == 0 { - return nil, nil + return nil, traffic, nil } - return result, nil + return result, traffic, nil } func destinationSettingFromHostAndPort(host string, port uint32) []*ir.DestinationSetting { diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index 336e931cfce..9325621468e 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -196,7 +196,6 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe dstAddrTypeMap := make(map[ir.DestinationAddressType]int) for _, backendRef := range rule.BackendRefs { - backendRef := backendRef ds := t.processDestination(backendRef, parentRef, httpRoute, resources) if !t.IsEnvoyServiceRouting(envoyProxy) && ds != nil && len(ds.Endpoints) > 0 && ds.AddressType != nil { @@ -314,12 +313,60 @@ func (t *Translator) processHTTPRouteRule(httpRoute *HTTPRouteContext, ruleIdx i ruleRoutes = append(ruleRoutes, irRoute) } + var sessionPersistence *ir.SessionPersistence + if rule.SessionPersistence != nil { + if rule.SessionPersistence.IdleTimeout != nil { + return nil, fmt.Errorf("idle timeout is not supported in envoy gateway") + } + + var sessionName string + if rule.SessionPersistence.SessionName == nil { + // SessionName is optional on the gateway-api, but envoy requires it + // so we generate the one here. + + // We generate a unique session name per route. + // `/` isn't allowed in the header key, so we just replace it with `-`. + sessionName = strings.ReplaceAll(irRouteDestinationName(httpRoute, ruleIdx), "/", "-") + } else { + sessionName = *rule.SessionPersistence.SessionName + } + + switch { + case rule.SessionPersistence.Type == nil || // Cookie-based session persistence is default. + *rule.SessionPersistence.Type == gwapiv1.CookieBasedSessionPersistence: + sessionPersistence = &ir.SessionPersistence{ + Cookie: &ir.CookieBasedSessionPersistence{ + Name: sessionName, + }, + } + if rule.SessionPersistence.AbsoluteTimeout != nil && + rule.SessionPersistence.CookieConfig != nil && rule.SessionPersistence.CookieConfig.LifetimeType != nil && + *rule.SessionPersistence.CookieConfig.LifetimeType == gwapiv1.PermanentCookieLifetimeType { + ttl, err := time.ParseDuration(string(*rule.SessionPersistence.AbsoluteTimeout)) + if err != nil { + return nil, err + } + sessionPersistence.Cookie.TTL = &metav1.Duration{Duration: ttl} + } + case *rule.SessionPersistence.Type == gwapiv1.HeaderBasedSessionPersistence: + sessionPersistence = &ir.SessionPersistence{ + Header: &ir.HeaderBasedSessionPersistence{ + Name: sessionName, + }, + } + default: + // Unknown session persistence type is specified. + return nil, fmt.Errorf("unknown session persistence type %s", *rule.SessionPersistence.Type) + } + } + // A rule is matched if any one of its matches // is satisfied (i.e. a logical "OR"), so generate // a unique Xds IR HTTPRoute per match. for matchIdx, match := range rule.Matches { irRoute := &ir.HTTPRoute{ - Name: irRouteName(httpRoute, ruleIdx, matchIdx), + Name: irRouteName(httpRoute, ruleIdx, matchIdx), + SessionPersistence: sessionPersistence, } processTimeout(irRoute, rule) @@ -504,7 +551,6 @@ func (t *Translator) processGRPCRouteRules(grpcRoute *GRPCRouteContext, parentRe } for _, backendRef := range rule.BackendRefs { - backendRef := backendRef ds := t.processDestination(backendRef, parentRef, grpcRoute, resources) if ds == nil { continue @@ -651,7 +697,7 @@ func (t *Translator) processHTTPRouteParentRefListener(route RouteContext, route var hasHostnameIntersection bool for _, listener := range parentRef.listeners { - hosts := computeHosts(GetHostnames(route), listener.Hostname) + hosts := computeHosts(GetHostnames(route), listener) if len(hosts) == 0 { continue } @@ -699,6 +745,7 @@ func (t *Translator) processHTTPRouteParentRefListener(route RouteContext, route Mirrors: routeRoute.Mirrors, ExtensionRefs: routeRoute.ExtensionRefs, IsHTTP2: routeRoute.IsHTTP2, + SessionPersistence: routeRoute.SessionPersistence, } if routeRoute.Traffic != nil { hostRoute.Traffic = &ir.TrafficFeatures{ @@ -784,7 +831,6 @@ func (t *Translator) processTLSRouteParentRefs(tlsRoute *TLSRouteContext, resour // compute backends for _, rule := range tlsRoute.Spec.Rules { for _, backendRef := range rule.BackendRefs { - backendRef := backendRef ds := t.processDestination(backendRef, parentRef, tlsRoute, resources) if ds != nil { destSettings = append(destSettings, ds) @@ -818,7 +864,7 @@ func (t *Translator) processTLSRouteParentRefs(tlsRoute *TLSRouteContext, resour var hasHostnameIntersection bool for _, listener := range parentRef.listeners { - hosts := computeHosts(GetHostnames(tlsRoute), listener.Hostname) + hosts := computeHosts(GetHostnames(tlsRoute), listener) if len(hosts) == 0 { continue } @@ -1058,7 +1104,6 @@ func (t *Translator) processTCPRouteParentRefs(tcpRoute *TCPRouteContext, resour } for _, backendRef := range tcpRoute.Spec.Rules[0].BackendRefs { - backendRef := backendRef ds := t.processDestination(backendRef, parentRef, tcpRoute, resources) if ds == nil { continue diff --git a/internal/gatewayapi/runner/runner.go b/internal/gatewayapi/runner/runner.go index 8b9b57fc839..c9bdead8236 100644 --- a/internal/gatewayapi/runner/runner.go +++ b/internal/gatewayapi/runner/runner.go @@ -227,7 +227,6 @@ func (r *Runner) subscribeAndTranslate(ctx context.Context) { // their target is not found (not relevant) for _, backendTLSPolicy := range result.BackendTLSPolicies { - backendTLSPolicy := backendTLSPolicy key := utils.NamespacedName(backendTLSPolicy) if !(reflect.ValueOf(backendTLSPolicy.Status).IsZero()) { r.ProviderResources.BackendTLSPolicyStatuses.Store(key, &backendTLSPolicy.Status) @@ -257,7 +256,6 @@ func (r *Runner) subscribeAndTranslate(ctx context.Context) { delete(statusesToDelete.SecurityPolicyStatusKeys, key) } for _, envoyExtensionPolicy := range result.EnvoyExtensionPolicies { - envoyExtensionPolicy := envoyExtensionPolicy key := utils.NamespacedName(envoyExtensionPolicy) if !(reflect.ValueOf(envoyExtensionPolicy.Status).IsZero()) { r.ProviderResources.EnvoyExtensionPolicyStatuses.Store(key, &envoyExtensionPolicy.Status) @@ -265,7 +263,6 @@ func (r *Runner) subscribeAndTranslate(ctx context.Context) { delete(statusesToDelete.EnvoyExtensionPolicyStatusKeys, key) } for _, extServerPolicy := range result.ExtensionServerPolicies { - extServerPolicy := extServerPolicy key := message.NamespacedNameAndGVK{ NamespacedName: utils.NamespacedName(&extServerPolicy), GroupVersionKind: extServerPolicy.GroupVersionKind(), diff --git a/internal/gatewayapi/runner/runner_test.go b/internal/gatewayapi/runner/runner_test.go index 5f3bc2a6544..502a96950fa 100644 --- a/internal/gatewayapi/runner/runner_test.go +++ b/internal/gatewayapi/runner/runner_test.go @@ -105,7 +105,6 @@ func TestGetIRKeysToDelete(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { assert.ElementsMatch(t, tc.delKeys, getIRKeysToDelete(tc.curKeys, tc.newKeys)) }) diff --git a/internal/gatewayapi/securitypolicy.go b/internal/gatewayapi/securitypolicy.go index d071e4ffdda..9940dbabefc 100644 --- a/internal/gatewayapi/securitypolicy.go +++ b/internal/gatewayapi/securitypolicy.go @@ -523,7 +523,6 @@ func (t *Translator) buildCORS(cors *egv1a1.CORS) *ir.CORS { var allowOrigins []*ir.StringMatch for _, origin := range cors.AllowOrigins { - origin := origin if isWildcard(string(origin)) { regexStr := wildcard2regex(string(origin)) allowOrigins = append(allowOrigins, &ir.StringMatch{ @@ -813,6 +812,8 @@ func (t *Translator) buildExtAuth(policy *egv1a1.SecurityPolicy, resources *Reso ds *ir.DestinationSetting authority string err error + traffic *ir.TrafficFeatures + failover *bool ) switch { @@ -824,14 +825,22 @@ func (t *Translator) buildExtAuth(policy *egv1a1.SecurityPolicy, resources *Reso backendRef = http.BackendRef if len(http.BackendRefs) != 0 { backendRef = egv1a1.ToBackendObjectReference(http.BackendRefs[0]) + failover = http.BackendRefs[0].Failover } protocol = ir.HTTP + if traffic, err = translateTrafficFeatures(http.BackendSettings); err != nil { + return nil, err + } case grpc != nil: backendRef = grpc.BackendRef if len(grpc.BackendRefs) != 0 { backendRef = egv1a1.ToBackendObjectReference(grpc.BackendRefs[0]) + failover = grpc.BackendRefs[0].Failover } protocol = ir.GRPC + if traffic, err = translateTrafficFeatures(grpc.BackendSettings); err != nil { + return nil, err + } // These are sanity checks, they should never happen because the API server // should have caught them default: // http == nil && grpc == nil: @@ -841,14 +850,11 @@ func (t *Translator) buildExtAuth(policy *egv1a1.SecurityPolicy, resources *Reso if err = t.validateExtServiceBackendReference(backendRef, policy.Namespace, policy.Kind, resources); err != nil { return nil, err } - authority = fmt.Sprintf("%s.%s:%d", - backendRef.Name, - NamespaceDerefOr(backendRef.Namespace, policy.Namespace), - *backendRef.Port) + authority = backendRefAuthority(resources, backendRef, policy) pnn := utils.NamespacedName(policy) if ds, err = t.processExtServiceDestination( - backendRef, + &egv1a1.BackendRef{BackendObjectReference: *backendRef, Failover: failover}, pnn, KindSecurityPolicy, protocol, @@ -866,6 +872,7 @@ func (t *Translator) buildExtAuth(policy *egv1a1.SecurityPolicy, resources *Reso Name: irConfigName(policy), HeadersToExtAuth: policy.Spec.ExtAuth.HeadersToExtAuth, FailOpen: policy.Spec.ExtAuth.FailOpen, + Traffic: traffic, } if http != nil { @@ -884,6 +891,31 @@ func (t *Translator) buildExtAuth(policy *egv1a1.SecurityPolicy, resources *Reso return extAuth, nil } +func backendRefAuthority(resources *Resources, backendRef *gwapiv1.BackendObjectReference, policy *egv1a1.SecurityPolicy) string { + if backendRef == nil { + return "" + } + + backendNamespace := NamespaceDerefOr(backendRef.Namespace, policy.Namespace) + backendKind := KindDerefOr(backendRef.Kind, KindService) + if backendKind == egv1a1.KindBackend { + backend := resources.GetBackend(backendNamespace, string(backendRef.Name)) + if backend != nil { + // TODO: exists multi FQDN endpoints? + for _, ep := range backend.Spec.Endpoints { + if ep.FQDN != nil { + return fmt.Sprintf("%s:%d", ep.FQDN.Hostname, ep.FQDN.Port) + } + } + } + } + + return fmt.Sprintf("%s.%s:%d", + backendRef.Name, + backendNamespace, + *backendRef.Port) +} + func irExtServiceDestinationName(policy *egv1a1.SecurityPolicy, backendRef *gwapiv1.BackendObjectReference) string { nn := types.NamespacedName{ Name: string(backendRef.Name), diff --git a/internal/gatewayapi/status/gateway_test.go b/internal/gatewayapi/status/gateway_test.go index 0be99b7d4bf..8c87c16190a 100644 --- a/internal/gatewayapi/status/gateway_test.go +++ b/internal/gatewayapi/status/gateway_test.go @@ -250,7 +250,6 @@ func TestUpdateGatewayProgrammedCondition(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { t.Parallel() gtw := &gwapiv1.Gateway{} diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-dns-settings.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-dns-settings.out.yaml index 89d9902328f..12bbf12dbe7 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-dns-settings.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-dns-settings.out.yaml @@ -342,9 +342,6 @@ xdsIR: port: 8080 protocol: HTTP weight: 1 - dns: - dnsRefreshRate: 10s - respectDnsTtl: true hostname: gateway.envoyproxy.io isHTTP2: false metadata: @@ -356,7 +353,10 @@ xdsIR: distinct: false name: "" prefix: /v3 - traffic: {} + traffic: + dns: + dnsRefreshRate: 10s + respectDnsTtl: true envoy-gateway/gateway-2: accessLog: text: @@ -386,9 +386,6 @@ xdsIR: port: 8080 protocol: HTTP weight: 1 - dns: - dnsRefreshRate: 5s - respectDnsTtl: false hostname: gateway.envoyproxy.io isHTTP2: false metadata: @@ -400,7 +397,10 @@ xdsIR: distinct: false name: "" prefix: /v2 - traffic: {} + traffic: + dns: + dnsRefreshRate: 5s + respectDnsTtl: false - destination: name: httproute/default/httproute-1/rule/0 settings: @@ -410,9 +410,6 @@ xdsIR: port: 8080 protocol: HTTP weight: 1 - dns: - dnsRefreshRate: 1s - respectDnsTtl: true hostname: gateway.envoyproxy.io isHTTP2: false metadata: @@ -424,4 +421,7 @@ xdsIR: distinct: false name: "" prefix: / - traffic: {} + traffic: + dns: + dnsRefreshRate: 1s + respectDnsTtl: true diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.in.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.in.yaml index 5cb832646b3..0ea537711d9 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.in.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.in.yaml @@ -42,6 +42,34 @@ grpcRoutes: - backendRefs: - name: service-1 port: 8080 +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: GRPCRoute + metadata: + namespace: default + name: grpcroute-3 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - backendRefs: + - name: service-3 + port: 8080 +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: GRPCRoute + metadata: + namespace: default + name: grpcroute-2 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - backendRefs: + - name: service-2 + port: 8080 httpRoutes: - apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute @@ -233,3 +261,40 @@ backendTrafficPolicies: consecutiveGatewayErrors: 0 consecutiveLocalOriginFailures: 5 splitExternalLocalOriginErrors: false +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + namespace: default + name: policy-for-grpc-route + spec: + targetRef: + group: gateway.networking.k8s.io + kind: GRPCRoute + name: grpcroute-2 + healthCheck: + active: + timeout: 1s + interval: 3s + unhealthyThreshold: 3 + healthyThreshold: 1 + type: GRPC +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + namespace: default + name: policy-for-grpc-route-3 + spec: + targetRef: + group: gateway.networking.k8s.io + kind: GRPCRoute + name: grpcroute-3 + healthCheck: + active: + timeout: 1s + interval: 3s + unhealthyThreshold: 3 + healthyThreshold: 1 + type: GRPC + grpc: + service: foo-service + diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml index 447a7df485e..4d1cc89bc55 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml @@ -145,6 +145,74 @@ backendTrafficPolicies: status: "True" type: Accepted controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + creationTimestamp: null + name: policy-for-grpc-route + namespace: default + spec: + healthCheck: + active: + healthyThreshold: 1 + interval: 3s + timeout: 1s + type: GRPC + unhealthyThreshold: 3 + targetRef: + group: gateway.networking.k8s.io + kind: GRPCRoute + name: grpcroute-2 + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + creationTimestamp: null + name: policy-for-grpc-route-3 + namespace: default + spec: + healthCheck: + active: + grpc: + service: foo-service + healthyThreshold: 1 + interval: 3s + timeout: 1s + type: GRPC + unhealthyThreshold: 3 + targetRef: + group: gateway.networking.k8s.io + kind: GRPCRoute + name: grpcroute-3 + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller - apiVersion: gateway.envoyproxy.io/v1alpha1 kind: BackendTrafficPolicy metadata: @@ -193,6 +261,12 @@ backendTrafficPolicies: reason: Accepted status: "True" type: Accepted + - lastTransitionTime: null + message: 'This policy is being overridden by other backendTrafficPolicies + for these routes: [default/grpcroute-2 default/grpcroute-3]' + reason: Overridden + status: "True" + type: Overridden controllerName: gateway.envoyproxy.io/gatewayclass-controller gateways: - apiVersion: gateway.networking.k8s.io/v1 @@ -212,7 +286,7 @@ gateways: protocol: HTTP status: listeners: - - attachedRoutes: 1 + - attachedRoutes: 3 conditions: - lastTransitionTime: null message: Sending translated listener configuration to the data plane @@ -309,6 +383,72 @@ grpcRoutes: name: gateway-1 namespace: envoy-gateway sectionName: http +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: GRPCRoute + metadata: + creationTimestamp: null + name: grpcroute-3 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-3 + 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 +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: GRPCRoute + metadata: + creationTimestamp: null + name: grpcroute-2 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-2 + 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 @@ -516,6 +656,55 @@ xdsIR: interval: 2s maxEjectionPercent: 100 splitExternalLocalOriginErrors: false + - destination: + name: grpcroute/default/grpcroute-3/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: GRPC + weight: 1 + hostname: '*' + isHTTP2: true + metadata: + kind: GRPCRoute + name: grpcroute-3 + namespace: default + name: grpcroute/default/grpcroute-3/rule/0/match/-1/* + traffic: + healthCheck: + active: + grpc: + service: foo-service + healthyThreshold: 1 + interval: 3s + timeout: 1s + unhealthyThreshold: 3 + - destination: + name: grpcroute/default/grpcroute-2/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: GRPC + weight: 1 + hostname: '*' + isHTTP2: true + metadata: + kind: GRPCRoute + name: grpcroute-2 + namespace: default + name: grpcroute/default/grpcroute-2/rule/0/match/-1/* + traffic: + healthCheck: + active: + grpc: {} + healthyThreshold: 1 + interval: 3s + timeout: 1s + unhealthyThreshold: 3 envoy-gateway/gateway-2: accessLog: text: diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-headers-error.in.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-headers-error.in.yaml new file mode 100644 index 00000000000..3b2331bba7f --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-headers-error.in.yaml @@ -0,0 +1,43 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: envoy-gateway + name: target-gateway-1 + spec: + headers: + enableEnvoyHeaders: true + withUnderscoresAction: Allow + preserveXRequestID: true + earlyRequestHeaders: + add: + - name: "" + value: "empty" + - name: "invalid" + value: ":/" + set: + - name: "" + value: "empty" + - name: "invalid" + value: ":/" + remove: + - "" + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 +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 diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-headers-error.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-headers-error.out.yaml new file mode 100644 index 00000000000..9eee58d7df7 --- /dev/null +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-headers-error.out.yaml @@ -0,0 +1,127 @@ +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway-1 + namespace: envoy-gateway + spec: + headers: + earlyRequestHeaders: + add: + - name: "" + value: empty + - name: invalid + value: :/ + remove: + - "" + set: + - name: "" + value: empty + - name: invalid + value: :/ + enableEnvoyHeaders: true + preserveXRequestID: true + withUnderscoresAction: Allow + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + conditions: + - lastTransitionTime: null + message: |- + Headers: EarlyRequestHeaders cannot add a header with an empty name + EarlyRequestHeaders cannot set a header with an empty name + EarlyRequestHeaders cannot remove a header with an empty name. + reason: Invalid + status: "False" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: Same + name: http-1 + 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-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: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-1 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + headers: + enableEnvoyHeaders: true + preserveXRequestID: true + withUnderscoresAction: Allow + hostnames: + - '*' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http-1 + name: envoy-gateway/gateway-1/http-1 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-headers.in.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-headers.in.yaml index 6d73bee1a16..3234aed7da8 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-headers.in.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-headers.in.yaml @@ -9,6 +9,20 @@ clientTrafficPolicies: enableEnvoyHeaders: true withUnderscoresAction: Allow preserveXRequestID: true + earlyRequestHeaders: + add: + - name: "my-added-header" + value: "my-added-header-value" + - name: "my-added-header" + value: "my-added-header-value" + set: + - name: "my-set-header" + value: "my-set-header-value" + - name: "my-set-header" + value: "my-set-header-value" + remove: + - "my-removed-header" + - "my-removed-header" targetRef: group: gateway.networking.k8s.io kind: Gateway diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-headers.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-headers.out.yaml index 8b32bb192da..4e66bd91c64 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-headers.out.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-headers.out.yaml @@ -7,6 +7,20 @@ clientTrafficPolicies: namespace: envoy-gateway spec: headers: + earlyRequestHeaders: + add: + - name: my-added-header + value: my-added-header-value + - name: my-added-header + value: my-added-header-value + remove: + - my-removed-header + - my-removed-header + set: + - name: my-set-header + value: my-set-header-value + - name: my-set-header + value: my-set-header-value enableEnvoyHeaders: true preserveXRequestID: true withUnderscoresAction: Allow @@ -129,6 +143,17 @@ xdsIR: http: - address: 0.0.0.0 headers: + earlyAddRequestHeaders: + - append: true + name: my-added-header + value: + - my-added-header-value + - append: false + name: my-set-header + value: + - my-set-header-value + earlyRemoveRequestHeaders: + - my-removed-header enableEnvoyHeaders: true preserveXRequestID: true withUnderscoresAction: Allow @@ -147,6 +172,17 @@ xdsIR: port: 10080 - address: 0.0.0.0 headers: + earlyAddRequestHeaders: + - append: true + name: my-added-header + value: + - my-added-header-value + - append: false + name: my-set-header + value: + - my-set-header-value + earlyRemoveRequestHeaders: + - my-removed-header enableEnvoyHeaders: true preserveXRequestID: true withUnderscoresAction: Allow diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-traffic-features.in.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-traffic-features.in.yaml new file mode 100644 index 00000000000..1f25d8f7e0b --- /dev/null +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-traffic-features.in.yaml @@ -0,0 +1,262 @@ +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: grpc-backend + spec: + ports: + - port: 8000 + name: grpc + protocol: TCP +- apiVersion: v1 + kind: Service + metadata: + namespace: default + name: grpc-backend-2 + spec: + ports: + - port: 9000 + name: grpc + protocol: TCP +endpointSlices: +- apiVersion: discovery.k8s.io/v1 + kind: EndpointSlice + metadata: + name: endpointslice-grpc-backend + namespace: envoy-gateway + labels: + kubernetes.io/service-name: grpc-backend + addressType: IPv4 + ports: + - name: http + protocol: TCP + port: 8000 + endpoints: + - addresses: + - 7.7.7.7 + conditions: + ready: true +- apiVersion: discovery.k8s.io/v1 + kind: EndpointSlice + metadata: + name: endpointslice-grpc-backend-2 + namespace: default + labels: + kubernetes.io/service-name: grpc-backend-2 + 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: EnvoyExtensionPolicy + namespace: default + to: + - group: '' + kind: Service + - group: gateway.envoyproxy.io + kind: Backend +configMaps: +- apiVersion: v1 + kind: ConfigMap + metadata: + name: ca-cmap + namespace: default + data: + ca.crt: | + -----BEGIN CERTIFICATE----- + MIIDJzCCAg+gAwIBAgIUAl6UKIuKmzte81cllz5PfdN2IlIwDQYJKoZIhvcNAQEL + BQAwIzEQMA4GA1UEAwwHbXljaWVudDEPMA0GA1UECgwGa3ViZWRiMB4XDTIzMTAw + MjA1NDE1N1oXDTI0MTAwMTA1NDE1N1owIzEQMA4GA1UEAwwHbXljaWVudDEPMA0G + A1UECgwGa3ViZWRiMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwSTc + 1yj8HW62nynkFbXo4VXKv2jC0PM7dPVky87FweZcTKLoWQVPQE2p2kLDK6OEszmM + yyr+xxWtyiveremrWqnKkNTYhLfYPhgQkczib7eUalmFjUbhWdLvHakbEgCodn3b + kz57mInX2VpiDOKg4kyHfiuXWpiBqrCx0KNLpxo3DEQcFcsQTeTHzh4752GV04RU + Ti/GEWyzIsl4Rg7tGtAwmcIPgUNUfY2Q390FGqdH4ahn+mw/6aFbW31W63d9YJVq + ioyOVcaMIpM5B/c7Qc8SuhCI1YGhUyg4cRHLEw5VtikioyE3X04kna3jQAj54YbR + bpEhc35apKLB21HOUQIDAQABo1MwUTAdBgNVHQ4EFgQUyvl0VI5vJVSuYFXu7B48 + 6PbMEAowHwYDVR0jBBgwFoAUyvl0VI5vJVSuYFXu7B486PbMEAowDwYDVR0TAQH/ + BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAMLxrgFVMuNRq2wAwcBt7SnNR5Cfz + 2MvXq5EUmuawIUi9kaYjwdViDREGSjk7JW17vl576HjDkdfRwi4E28SydRInZf6J + i8HZcZ7caH6DxR335fgHVzLi5NiTce/OjNBQzQ2MJXVDd8DBmG5fyatJiOJQ4bWE + A7FlP0RdP3CO3GWE0M5iXOB2m1qWkE2eyO4UHvwTqNQLdrdAXgDQlbam9e4BG3Gg + d/6thAkWDbt/QNT+EJHDCvhDRKh1RuGHyg+Y+/nebTWWrFWsktRrbOoHCZiCpXI1 + 3eXE6nt0YkgtDxG22KqnhpAg9gUSs2hlhoxyvkzyF0mu6NhPlwAgnq7+/Q== + -----END CERTIFICATE----- +backendTLSPolicies: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + name: policy-btls-grpc + namespace: envoy-gateway + spec: + targetRefs: + - group: '' + kind: Service + name: grpc-backend + sectionName: "8000" + validation: + caCertificateRefs: + - name: ca-cmap + group: '' + kind: ConfigMap + hostname: grpc-backend +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + name: policy-btls-backend-ip + namespace: envoy-gateway + spec: + targetRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip-tls + validation: + caCertificateRefs: + - name: ca-cmap + group: '' + kind: ConfigMap + hostname: ip-backend +envoyExtensionPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyExtensionPolicy + metadata: + namespace: default + name: policy-for-http-route + spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + extProc: + - backendRefs: + - Name: grpc-backend + Namespace: envoy-gateway + Port: 8000 + - Name: grpc-backend-2 + Port: 9000 + - Name: backend-ip + Kind: Backend + Group: gateway.envoyproxy.io + - Name: backend-ip-tls + Namespace: envoy-gateway + Kind: Backend + Group: gateway.envoyproxy.io + backendSettings: + dns: + respectDnsTtl: true + http2: + initialStreamWindowSize: 128Ki + initialConnectionWindowSize: 2Mi + maxConcurrentStreams: 200 + onInvalidMessage: TerminateStream + loadBalancer: + type: ConsistentHash + consistentHash: + type: Header + header: + name: X-some-header + proxyProtocol: + version: V2 + tcpKeepalive: + probes: 7 + healthCheck: + passive: + consecutiveGatewayErrors: 4 + interval: 5s + circuitBreaker: + maxConnections: 2048 + timeout: + tcp: + connectTimeout: 15s + connection: + bufferLimit: 20Mi +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-ip-tls + namespace: envoy-gateway + spec: + endpoints: + - ip: + address: 2.2.2.2 + port: 3443 diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-traffic-features.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-traffic-features.out.yaml new file mode 100644 index 00000000000..17f9e8c15a6 --- /dev/null +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-traffic-features.out.yaml @@ -0,0 +1,431 @@ +backendTLSPolicies: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + creationTimestamp: null + name: policy-btls-grpc + namespace: envoy-gateway + spec: + targetRefs: + - group: "" + kind: Service + name: grpc-backend + sectionName: "8000" + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + name: ca-cmap + hostname: grpc-backend + status: + ancestors: + - ancestorRef: + group: gateway.envoyproxy.io + kind: EnvoyExtensionPolicy + name: policy-for-http-route + namespace: default + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + creationTimestamp: null + name: policy-btls-backend-ip + namespace: envoy-gateway + spec: + targetRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip-tls + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + name: ca-cmap + hostname: ip-backend + status: + ancestors: + - ancestorRef: + group: gateway.envoyproxy.io + kind: EnvoyExtensionPolicy + name: policy-for-http-route + namespace: default + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-ip-tls + namespace: envoy-gateway + spec: + endpoints: + - ip: + address: 2.2.2.2 + port: 3443 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +envoyExtensionPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyExtensionPolicy + metadata: + creationTimestamp: null + name: policy-for-http-route + namespace: default + spec: + extProc: + - backendRefs: + - name: grpc-backend + namespace: envoy-gateway + port: 8000 + - name: grpc-backend-2 + port: 9000 + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip-tls + namespace: envoy-gateway + backendSettings: + circuitBreaker: + maxConnections: 2048 + connection: + bufferLimit: 20Mi + dns: + respectDnsTtl: true + healthCheck: + passive: + consecutiveGatewayErrors: 4 + interval: 5s + http2: + initialConnectionWindowSize: 2Mi + initialStreamWindowSize: 128Ki + maxConcurrentStreams: 200 + onInvalidMessage: TerminateStream + loadBalancer: + consistentHash: + header: + name: X-some-header + type: Header + type: ConsistentHash + proxyProtocol: + version: V2 + tcpKeepalive: + probes: 7 + timeout: + tcp: + connectTimeout: 15s + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: default + sectionName: http + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-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-80 + 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 +xdsIR: + default/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-1 + namespace: default + sectionName: http + name: default/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + envoyExtensions: + extProcs: + - authority: grpc-backend.envoy-gateway:8000 + destination: + name: envoyextensionpolicy/default/policy-for-http-route/0 + settings: + - addressType: IP + protocol: GRPC + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + name: policy-btls-grpc/envoy-gateway-ca + sni: grpc-backend + weight: 1 + - addressType: IP + endpoints: + - host: 8.8.8.8 + port: 9000 + protocol: GRPC + weight: 1 + - addressType: IP + endpoints: + - host: 1.1.1.1 + port: 3001 + protocol: GRPC + weight: 1 + - addressType: IP + endpoints: + - host: 2.2.2.2 + port: 3443 + protocol: GRPC + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + name: policy-btls-backend-ip/envoy-gateway-ca + sni: ip-backend + weight: 1 + name: envoyextensionpolicy/default/policy-for-http-route/extproc/0 + traffic: + backendConnection: + bufferLimit: 20971520 + circuitBreaker: + maxConnections: 2048 + dns: + respectDnsTtl: true + healthCheck: + passive: + consecutiveGatewayErrors: 4 + interval: 5s + http2: + initialConnectionWindowSize: 131072 + initialStreamWindowSize: 2097152 + maxConcurrentStreams: 200 + resetStreamOnError: true + loadBalancer: + consistentHash: + header: + name: X-some-header + proxyProtocol: + version: V2 + tcpKeepalive: + probes: 7 + timeout: + tcp: + connectTimeout: 15s + hostname: www.foo.com + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0/match/0/www_foo_com + pathMatch: + distinct: false + name: "" + prefix: /foo + - destination: + name: httproute/default/httproute-2/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: www.bar.com + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-2 + namespace: default + name: httproute/default/httproute-2/rule/0/match/0/www_bar_com + pathMatch: + distinct: false + name: "" + prefix: /bar diff --git a/internal/gatewayapi/testdata/envoyproxy-accesslog-with-traffic.in.yaml b/internal/gatewayapi/testdata/envoyproxy-accesslog-with-traffic.in.yaml new file mode 100644 index 00000000000..72d40451a1f --- /dev/null +++ b/internal/gatewayapi/testdata/envoyproxy-accesslog-with-traffic.in.yaml @@ -0,0 +1,196 @@ +envoyProxyForGatewayClass: + apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyProxy + metadata: + namespace: envoy-gateway-system + name: test + spec: + telemetry: + accessLog: + settings: + - format: + type: Text + text: | + [%START_TIME%] "%REQ(:METHOD)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"\n + sinks: + - type: File + file: + path: /dev/stdout + - type: ALS + als: + logName: accesslog + backendSettings: + http2: + initialStreamWindowSize: 128Ki + initialConnectionWindowSize: 2Mi + maxConcurrentStreams: 200 + onInvalidMessage: TerminateStream + loadBalancer: + type: ConsistentHash + consistentHash: + type: Header + header: + name: X-some-header + proxyProtocol: + version: V2 + tcpKeepalive: + probes: 7 + healthCheck: + passive: + consecutiveGatewayErrors: 4 + interval: 5s + circuitBreaker: + maxConnections: 2048 + timeout: + tcp: + connectTimeout: 15s + connection: + bufferLimit: 20Mi + backendRefs: + - name: envoy-als + namespace: monitoring + port: 9000 + http: + requestHeaders: + - x-client-ip-address + responseHeaders: + - cache-control + responseTrailers: + - expires + type: HTTP + - type: ALS + als: + backendRefs: + - name: envoy-als + namespace: monitoring + port: 9000 + type: TCP + - type: OpenTelemetry + openTelemetry: + backendSettings: + http2: + initialStreamWindowSize: 128Ki + initialConnectionWindowSize: 2Mi + maxConcurrentStreams: 200 + onInvalidMessage: TerminateStream + loadBalancer: + type: ConsistentHash + consistentHash: + type: Header + header: + name: X-some-header + proxyProtocol: + version: V2 + tcpKeepalive: + probes: 7 + healthCheck: + passive: + consecutiveGatewayErrors: 4 + interval: 5s + circuitBreaker: + maxConnections: 2048 + timeout: + tcp: + connectTimeout: 15s + connection: + bufferLimit: 20Mi + host: otel-collector.monitoring.svc.cluster.local + port: 4317 + resources: + k8s.cluster.name: "cluster-1" + provider: + type: Kubernetes + kubernetes: + envoyService: + type: LoadBalancer + envoyDeployment: + replicas: 2 + container: + env: + - name: env_a + value: env_a_value + - name: env_b + value: env_b_name + image: "envoyproxy/envoy:distroless-dev" + resources: + requests: + cpu: 100m + memory: 512Mi + securityContext: + runAsUser: 2000 + allowPrivilegeEscalation: false + pod: + annotations: + key1: val1 + key2: val2 + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: cloud.google.com/gke-nodepool + operator: In + values: + - router-node + tolerations: + - effect: NoSchedule + key: node-type + operator: Exists + value: "router" + securityContext: + runAsUser: 1000 + runAsGroup: 3000 + fsGroup: 2000 + fsGroupChangePolicy: "OnRootMismatch" + volumes: + - name: certs + secret: + secretName: envoy-cert +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 +services: +- apiVersion: v1 + kind: Service + metadata: + name: envoy-als + namespace: monitoring + spec: + type: ClusterIP + ports: + - name: grpc + port: 9000 + appProtocol: grpc + protocol: TCP + targetPort: 9000 +endpointSlices: +- apiVersion: discovery.k8s.io/v1 + kind: EndpointSlice + metadata: + name: endpointslice-envoy-als + namespace: monitoring + labels: + kubernetes.io/service-name: envoy-als + addressType: IPv4 + ports: + - name: grpc + protocol: TCP + appProtocol: grpc + port: 9090 + endpoints: + - addresses: + - "10.240.0.10" + conditions: + ready: true diff --git a/internal/gatewayapi/testdata/envoyproxy-accesslog-with-traffic.out.yaml b/internal/gatewayapi/testdata/envoyproxy-accesslog-with-traffic.out.yaml new file mode 100644 index 00000000000..28ef831b03a --- /dev/null +++ b/internal/gatewayapi/testdata/envoyproxy-accesslog-with-traffic.out.yaml @@ -0,0 +1,326 @@ +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/gateway-1: + proxy: + config: + apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyProxy + metadata: + creationTimestamp: null + name: test + namespace: envoy-gateway-system + spec: + logging: {} + provider: + kubernetes: + envoyDeployment: + container: + env: + - name: env_a + value: env_a_value + - name: env_b + value: env_b_name + image: envoyproxy/envoy:distroless-dev + resources: + requests: + cpu: 100m + memory: 512Mi + securityContext: + allowPrivilegeEscalation: false + runAsUser: 2000 + pod: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: cloud.google.com/gke-nodepool + operator: In + values: + - router-node + annotations: + key1: val1 + key2: val2 + securityContext: + fsGroup: 2000 + fsGroupChangePolicy: OnRootMismatch + runAsGroup: 3000 + runAsUser: 1000 + tolerations: + - effect: NoSchedule + key: node-type + operator: Exists + value: router + volumes: + - name: certs + secret: + secretName: envoy-cert + replicas: 2 + envoyService: + type: LoadBalancer + type: Kubernetes + telemetry: + accessLog: + settings: + - format: + text: | + [%START_TIME%] "%REQ(:METHOD)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"\n + type: Text + sinks: + - file: + path: /dev/stdout + type: File + - als: + backendRefs: + - name: envoy-als + namespace: monitoring + port: 9000 + backendSettings: + circuitBreaker: + maxConnections: 2048 + connection: + bufferLimit: 20Mi + healthCheck: + passive: + consecutiveGatewayErrors: 4 + interval: 5s + http2: + initialConnectionWindowSize: 2Mi + initialStreamWindowSize: 128Ki + maxConcurrentStreams: 200 + onInvalidMessage: TerminateStream + loadBalancer: + consistentHash: + header: + name: X-some-header + type: Header + type: ConsistentHash + proxyProtocol: + version: V2 + tcpKeepalive: + probes: 7 + timeout: + tcp: + connectTimeout: 15s + http: + requestHeaders: + - x-client-ip-address + responseHeaders: + - cache-control + responseTrailers: + - expires + logName: accesslog + type: HTTP + type: ALS + - als: + backendRefs: + - name: envoy-als + namespace: monitoring + port: 9000 + type: TCP + type: ALS + - openTelemetry: + backendSettings: + circuitBreaker: + maxConnections: 2048 + connection: + bufferLimit: 20Mi + healthCheck: + passive: + consecutiveGatewayErrors: 4 + interval: 5s + http2: + initialConnectionWindowSize: 2Mi + initialStreamWindowSize: 128Ki + maxConcurrentStreams: 200 + onInvalidMessage: TerminateStream + loadBalancer: + consistentHash: + header: + name: X-some-header + type: Header + type: ConsistentHash + proxyProtocol: + version: V2 + tcpKeepalive: + probes: 7 + timeout: + tcp: + connectTimeout: 15s + host: otel-collector.monitoring.svc.cluster.local + port: 4317 + resources: + k8s.cluster.name: cluster-1 + type: OpenTelemetry + status: {} + listeners: + - address: null + name: envoy-gateway/gateway-1/http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-1 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + als: + - destination: + name: accesslog_als_0_1 + settings: + - addressType: IP + endpoints: + - host: 10.240.0.10 + port: 9090 + protocol: GRPC + http: + requestHeaders: + - x-client-ip-address + responseHeaders: + - cache-control + responseTrailers: + - expires + name: accesslog + text: | + [%START_TIME%] "%REQ(:METHOD)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"\n + traffic: + backendConnection: + bufferLimit: 20971520 + circuitBreaker: + maxConnections: 2048 + healthCheck: + passive: + consecutiveGatewayErrors: 4 + interval: 5s + http2: + initialConnectionWindowSize: 131072 + initialStreamWindowSize: 2097152 + maxConcurrentStreams: 200 + resetStreamOnError: true + loadBalancer: + consistentHash: + header: + name: X-some-header + proxyProtocol: + version: V2 + tcpKeepalive: + probes: 7 + timeout: + tcp: + connectTimeout: 15s + type: HTTP + - destination: + name: accesslog_als_0_2 + settings: + - addressType: IP + endpoints: + - host: 10.240.0.10 + port: 9090 + protocol: GRPC + name: envoy-gateway-system/test + text: | + [%START_TIME%] "%REQ(:METHOD)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"\n + type: TCP + openTelemetry: + - authority: otel-collector.monitoring.svc.cluster.local + destination: + name: accesslog_otel_0_3 + settings: + - endpoints: + - host: otel-collector.monitoring.svc.cluster.local + port: 4317 + protocol: GRPC + weight: 1 + resources: + k8s.cluster.name: cluster-1 + text: | + [%START_TIME%] "%REQ(:METHOD)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"\n + traffic: + backendConnection: + bufferLimit: 20971520 + circuitBreaker: + maxConnections: 2048 + healthCheck: + passive: + consecutiveGatewayErrors: 4 + interval: 5s + http2: + initialConnectionWindowSize: 131072 + initialStreamWindowSize: 2097152 + maxConcurrentStreams: 200 + resetStreamOnError: true + loadBalancer: + consistentHash: + header: + name: X-some-header + proxyProtocol: + version: V2 + tcpKeepalive: + probes: 7 + timeout: + tcp: + connectTimeout: 15s + text: + - format: | + [%START_TIME%] "%REQ(:METHOD)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"\n + path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 diff --git a/internal/gatewayapi/testdata/envoyproxy-priority-backend.in.yaml b/internal/gatewayapi/testdata/envoyproxy-priority-backend.in.yaml new file mode 100644 index 00000000000..f44174b6d62 --- /dev/null +++ b/internal/gatewayapi/testdata/envoyproxy-priority-backend.in.yaml @@ -0,0 +1,236 @@ +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: grpc-backend + spec: + ports: + - port: 8000 + name: grpc + protocol: TCP + - apiVersion: v1 + kind: Service + metadata: + namespace: default + name: grpc-backend-2 + spec: + ports: + - port: 9000 + name: grpc + protocol: TCP +endpointSlices: + - apiVersion: discovery.k8s.io/v1 + kind: EndpointSlice + metadata: + name: endpointslice-grpc-backend + namespace: envoy-gateway + labels: + kubernetes.io/service-name: grpc-backend + addressType: IPv4 + ports: + - name: http + protocol: TCP + port: 8000 + endpoints: + - addresses: + - 7.7.7.7 + conditions: + ready: true + - apiVersion: discovery.k8s.io/v1 + kind: EndpointSlice + metadata: + name: endpointslice-grpc-backend-2 + namespace: default + labels: + kubernetes.io/service-name: grpc-backend-2 + 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: EnvoyExtensionPolicy + namespace: default + to: + - group: '' + kind: Service + - group: gateway.envoyproxy.io + kind: Backend +configMaps: + - apiVersion: v1 + kind: ConfigMap + metadata: + name: ca-cmap + namespace: default + data: + ca.crt: | + -----BEGIN CERTIFICATE----- + MIIDJzCCAg+gAwIBAgIUAl6UKIuKmzte81cllz5PfdN2IlIwDQYJKoZIhvcNAQEL + BQAwIzEQMA4GA1UEAwwHbXljaWVudDEPMA0GA1UECgwGa3ViZWRiMB4XDTIzMTAw + MjA1NDE1N1oXDTI0MTAwMTA1NDE1N1owIzEQMA4GA1UEAwwHbXljaWVudDEPMA0G + A1UECgwGa3ViZWRiMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwSTc + 1yj8HW62nynkFbXo4VXKv2jC0PM7dPVky87FweZcTKLoWQVPQE2p2kLDK6OEszmM + yyr+xxWtyiveremrWqnKkNTYhLfYPhgQkczib7eUalmFjUbhWdLvHakbEgCodn3b + kz57mInX2VpiDOKg4kyHfiuXWpiBqrCx0KNLpxo3DEQcFcsQTeTHzh4752GV04RU + Ti/GEWyzIsl4Rg7tGtAwmcIPgUNUfY2Q390FGqdH4ahn+mw/6aFbW31W63d9YJVq + ioyOVcaMIpM5B/c7Qc8SuhCI1YGhUyg4cRHLEw5VtikioyE3X04kna3jQAj54YbR + bpEhc35apKLB21HOUQIDAQABo1MwUTAdBgNVHQ4EFgQUyvl0VI5vJVSuYFXu7B48 + 6PbMEAowHwYDVR0jBBgwFoAUyvl0VI5vJVSuYFXu7B486PbMEAowDwYDVR0TAQH/ + BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAMLxrgFVMuNRq2wAwcBt7SnNR5Cfz + 2MvXq5EUmuawIUi9kaYjwdViDREGSjk7JW17vl576HjDkdfRwi4E28SydRInZf6J + i8HZcZ7caH6DxR335fgHVzLi5NiTce/OjNBQzQ2MJXVDd8DBmG5fyatJiOJQ4bWE + A7FlP0RdP3CO3GWE0M5iXOB2m1qWkE2eyO4UHvwTqNQLdrdAXgDQlbam9e4BG3Gg + d/6thAkWDbt/QNT+EJHDCvhDRKh1RuGHyg+Y+/nebTWWrFWsktRrbOoHCZiCpXI1 + 3eXE6nt0YkgtDxG22KqnhpAg9gUSs2hlhoxyvkzyF0mu6NhPlwAgnq7+/Q== + -----END CERTIFICATE----- +backendTLSPolicies: + - apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + name: policy-btls-grpc + namespace: envoy-gateway + spec: + targetRefs: + - group: '' + kind: Service + name: grpc-backend + sectionName: "8000" + validation: + caCertificateRefs: + - name: ca-cmap + group: '' + kind: ConfigMap + hostname: grpc-backend + - apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + name: policy-btls-backend-ip + namespace: envoy-gateway + spec: + targetRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip-tls + validation: + caCertificateRefs: + - name: ca-cmap + group: '' + kind: ConfigMap + hostname: ip-backend +envoyExtensionPolicies: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyExtensionPolicy + metadata: + namespace: default + name: policy-for-http-route + spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + extProc: + - backendRefs: + - Name: grpc-backend + Namespace: envoy-gateway + Port: 8000 + - Name: grpc-backend-2 + Port: 9000 + failover: true + - Name: backend-ip + Kind: Backend + Group: gateway.envoyproxy.io + failover: true + - Name: backend-ip-tls + Namespace: envoy-gateway + Kind: Backend + Group: gateway.envoyproxy.io + failover: true +backends: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-ip-tls + namespace: envoy-gateway + spec: + endpoints: + - ip: + address: 2.2.2.2 + port: 3443 diff --git a/internal/gatewayapi/testdata/envoyproxy-priority-backend.out.yaml b/internal/gatewayapi/testdata/envoyproxy-priority-backend.out.yaml new file mode 100644 index 00000000000..9933d77c563 --- /dev/null +++ b/internal/gatewayapi/testdata/envoyproxy-priority-backend.out.yaml @@ -0,0 +1,381 @@ +backendTLSPolicies: +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + creationTimestamp: null + name: policy-btls-grpc + namespace: envoy-gateway + spec: + targetRefs: + - group: "" + kind: Service + name: grpc-backend + sectionName: "8000" + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + name: ca-cmap + hostname: grpc-backend + status: + ancestors: + - ancestorRef: + group: gateway.envoyproxy.io + kind: EnvoyExtensionPolicy + name: policy-for-http-route + namespace: default + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + creationTimestamp: null + name: policy-btls-backend-ip + namespace: envoy-gateway + spec: + targetRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip-tls + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + name: ca-cmap + hostname: ip-backend + status: + ancestors: + - ancestorRef: + group: gateway.envoyproxy.io + kind: EnvoyExtensionPolicy + name: policy-for-http-route + namespace: default + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-ip + namespace: default + spec: + endpoints: + - ip: + address: 1.1.1.1 + port: 3001 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-ip-tls + namespace: envoy-gateway + spec: + endpoints: + - ip: + address: 2.2.2.2 + port: 3443 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +envoyExtensionPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyExtensionPolicy + metadata: + creationTimestamp: null + name: policy-for-http-route + namespace: default + spec: + extProc: + - backendRefs: + - name: grpc-backend + namespace: envoy-gateway + port: 8000 + - failover: true + name: grpc-backend-2 + port: 9000 + - failover: true + group: gateway.envoyproxy.io + kind: Backend + name: backend-ip + - failover: true + group: gateway.envoyproxy.io + kind: Backend + name: backend-ip-tls + namespace: envoy-gateway + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: default + sectionName: http + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-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-80 + 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 +xdsIR: + default/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-1 + namespace: default + sectionName: http + name: default/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + envoyExtensions: + extProcs: + - authority: grpc-backend.envoy-gateway:8000 + destination: + name: envoyextensionpolicy/default/policy-for-http-route/0 + settings: + - addressType: IP + protocol: GRPC + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + name: policy-btls-grpc/envoy-gateway-ca + sni: grpc-backend + weight: 1 + - addressType: IP + endpoints: + - host: 8.8.8.8 + port: 9000 + priority: 1 + protocol: GRPC + weight: 1 + - addressType: IP + endpoints: + - host: 1.1.1.1 + port: 3001 + priority: 1 + protocol: GRPC + weight: 1 + - addressType: IP + endpoints: + - host: 2.2.2.2 + port: 3443 + priority: 1 + protocol: GRPC + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + name: policy-btls-backend-ip/envoy-gateway-ca + sni: ip-backend + weight: 1 + name: envoyextensionpolicy/default/policy-for-http-route/extproc/0 + hostname: www.foo.com + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0/match/0/www_foo_com + pathMatch: + distinct: false + name: "" + prefix: /foo + - destination: + name: httproute/default/httproute-2/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: www.bar.com + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-2 + namespace: default + name: httproute/default/httproute-2/rule/0/match/0/www_bar_com + pathMatch: + distinct: false + name: "" + prefix: /bar diff --git a/internal/gatewayapi/testdata/envoyproxy-tracing-backend.in.yaml b/internal/gatewayapi/testdata/envoyproxy-tracing-backend.in.yaml index 9cd3485cec3..4c06c534135 100644 --- a/internal/gatewayapi/testdata/envoyproxy-tracing-backend.in.yaml +++ b/internal/gatewayapi/testdata/envoyproxy-tracing-backend.in.yaml @@ -9,6 +9,33 @@ envoyProxyForGatewayClass: tracing: samplingRate: 100 provider: + backendSettings: + http2: + initialStreamWindowSize: 128Ki + initialConnectionWindowSize: 2Mi + maxConcurrentStreams: 200 + onInvalidMessage: TerminateStream + loadBalancer: + type: ConsistentHash + consistentHash: + type: Header + header: + name: X-some-header + proxyProtocol: + version: V2 + tcpKeepalive: + probes: 7 + healthCheck: + passive: + consecutiveGatewayErrors: 4 + interval: 5s + circuitBreaker: + maxConnections: 2048 + timeout: + tcp: + connectTimeout: 15s + connection: + bufferLimit: 20Mi backendRefs: - name: otel-collector namespace: monitoring diff --git a/internal/gatewayapi/testdata/envoyproxy-tracing-backend.out.yaml b/internal/gatewayapi/testdata/envoyproxy-tracing-backend.out.yaml index 70e07bd18f2..b3a44d78fdc 100644 --- a/internal/gatewayapi/testdata/envoyproxy-tracing-backend.out.yaml +++ b/internal/gatewayapi/testdata/envoyproxy-tracing-backend.out.yaml @@ -106,6 +106,33 @@ infraIR: - name: otel-collector namespace: monitoring port: 4317 + backendSettings: + circuitBreaker: + maxConnections: 2048 + connection: + bufferLimit: 20Mi + healthCheck: + passive: + consecutiveGatewayErrors: 4 + interval: 5s + http2: + initialConnectionWindowSize: 2Mi + initialStreamWindowSize: 128Ki + maxConcurrentStreams: 200 + onInvalidMessage: TerminateStream + loadBalancer: + consistentHash: + header: + name: X-some-header + type: Header + type: ConsistentHash + proxyProtocol: + version: V2 + tcpKeepalive: + probes: 7 + timeout: + tcp: + connectTimeout: 15s type: OpenTelemetry samplingRate: 100 status: {} @@ -156,6 +183,58 @@ xdsIR: - name: otel-collector namespace: monitoring port: 4317 + backendSettings: + circuitBreaker: + maxConnections: 2048 + connection: + bufferLimit: 20Mi + healthCheck: + passive: + consecutiveGatewayErrors: 4 + interval: 5s + http2: + initialConnectionWindowSize: 2Mi + initialStreamWindowSize: 128Ki + maxConcurrentStreams: 200 + onInvalidMessage: TerminateStream + loadBalancer: + consistentHash: + header: + name: X-some-header + type: Header + type: ConsistentHash + proxyProtocol: + version: V2 + tcpKeepalive: + probes: 7 + timeout: + tcp: + connectTimeout: 15s type: OpenTelemetry samplingRate: 100 serviceName: gateway-1.envoy-gateway + traffic: + backendConnection: + bufferLimit: 20971520 + circuitBreaker: + maxConnections: 2048 + healthCheck: + passive: + consecutiveGatewayErrors: 4 + interval: 5s + http2: + initialConnectionWindowSize: 131072 + initialStreamWindowSize: 2097152 + maxConcurrentStreams: 200 + resetStreamOnError: true + loadBalancer: + consistentHash: + header: + name: X-some-header + proxyProtocol: + version: V2 + tcpKeepalive: + probes: 7 + timeout: + tcp: + connectTimeout: 15s diff --git a/internal/gatewayapi/testdata/gateway-http-listener-with-hostname-intersection.in.yaml b/internal/gatewayapi/testdata/gateway-http-listener-with-hostname-intersection.in.yaml new file mode 100644 index 00000000000..8fba772492e --- /dev/null +++ b/internal/gatewayapi/testdata/gateway-http-listener-with-hostname-intersection.in.yaml @@ -0,0 +1,65 @@ +gateways: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: empty-hostname + port: 80 + protocol: HTTP + allowedRoutes: + namespaces: + from: All + - name: wildcard-example-com + port: 80 + protocol: HTTP + hostname: "*.example.com" + allowedRoutes: + namespaces: + from: All +httpRoutes: + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + name: httproute-1 + namespace: envoy-gateway + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: empty-hostname + hostnames: + - "bar.com" + - "*.example.com" # request matching is prevented by the isolation wildcard-example-com listener + rules: + - matches: + - path: + type: PathPrefix + value: /empty-hostname + backendRefs: + - name: service-1 + port: 8080 + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + name: httproute-2 + namespace: envoy-gateway + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: wildcard-example-com + hostnames: + - "bar.com" # doesn't match wildcard-example-com listener + - "*.example.com" + rules: + - matches: + - path: + type: PathPrefix + value: /wildcard-example-com + backendRefs: + - name: service-1 + port: 8080 diff --git a/internal/gatewayapi/testdata/gateway-http-listener-with-hostname-intersection.out.yaml b/internal/gatewayapi/testdata/gateway-http-listener-with-hostname-intersection.out.yaml new file mode 100644 index 00000000000..cb47542a1c7 --- /dev/null +++ b/internal/gatewayapi/testdata/gateway-http-listener-with-hostname-intersection.out.yaml @@ -0,0 +1,238 @@ +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: empty-hostname + port: 80 + protocol: HTTP + - allowedRoutes: + namespaces: + from: All + hostname: '*.example.com' + name: wildcard-example-com + 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: empty-hostname + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute + - 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: wildcard-example-com + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-1 + namespace: envoy-gateway + spec: + hostnames: + - bar.com + - '*.example.com' + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: empty-hostname + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + type: PathPrefix + value: /empty-hostname + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Service envoy-gateway/service-1 not found + reason: BackendNotFound + status: "False" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: empty-hostname +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-2 + namespace: envoy-gateway + spec: + hostnames: + - bar.com + - '*.example.com' + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: wildcard-example-com + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + type: PathPrefix + value: /wildcard-example-com + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Service envoy-gateway/service-1 not found + reason: BackendNotFound + status: "False" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: wildcard-example-com +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-1/empty-hostname + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-1 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: empty-hostname + name: envoy-gateway/gateway-1/empty-hostname + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/envoy-gateway/httproute-1/rule/0 + settings: + - weight: 1 + directResponse: + statusCode: 500 + hostname: bar.com + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: envoy-gateway + name: httproute/envoy-gateway/httproute-1/rule/0/match/0/bar_com + pathMatch: + distinct: false + name: "" + prefix: /empty-hostname + - address: 0.0.0.0 + hostnames: + - '*.example.com' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: wildcard-example-com + name: envoy-gateway/gateway-1/wildcard-example-com + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/envoy-gateway/httproute-2/rule/0 + settings: + - weight: 1 + directResponse: + statusCode: 500 + hostname: '*.example.com' + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-2 + namespace: envoy-gateway + name: httproute/envoy-gateway/httproute-2/rule/0/match/0/*_example_com + pathMatch: + distinct: false + name: "" + prefix: /wildcard-example-com diff --git a/internal/gatewayapi/testdata/grpcroute-with-request-header-modifier.in.yaml b/internal/gatewayapi/testdata/grpcroute-with-request-header-modifier.in.yaml index 2c48dad582e..29fcb5a75a1 100644 --- a/internal/gatewayapi/testdata/grpcroute-with-request-header-modifier.in.yaml +++ b/internal/gatewayapi/testdata/grpcroute-with-request-header-modifier.in.yaml @@ -26,6 +26,11 @@ grpcRoutes: sectionName: http rules: - filters: + - type: "RequestHeaderModifier" + requestHeaderModifier: + add: + - name: "my-header-multi-value" + value: "foo,bar" - type: "RequestHeaderModifier" requestHeaderModifier: add: diff --git a/internal/gatewayapi/testdata/grpcroute-with-request-header-modifier.out.yaml b/internal/gatewayapi/testdata/grpcroute-with-request-header-modifier.out.yaml index f36c9c969cc..110d404c44f 100644 --- a/internal/gatewayapi/testdata/grpcroute-with-request-header-modifier.out.yaml +++ b/internal/gatewayapi/testdata/grpcroute-with-request-header-modifier.out.yaml @@ -56,6 +56,11 @@ grpcRoutes: - name: service-1 port: 8080 filters: + - requestHeaderModifier: + add: + - name: my-header-multi-value + value: foo,bar + type: RequestHeaderModifier - requestHeaderModifier: add: - name: my-header @@ -117,9 +122,15 @@ xdsIR: port: 10080 routes: - addRequestHeaders: + - append: true + name: my-header-multi-value + value: + - foo + - bar - append: true name: my-header - value: foo + value: + - foo destination: name: grpcroute/default/grpcroute-1/rule/0 settings: diff --git a/internal/gatewayapi/testdata/httproute-with-backendref-add-multiple-filters.out.yaml b/internal/gatewayapi/testdata/httproute-with-backendref-add-multiple-filters.out.yaml index 78655fc8476..122d09efdeb 100644 --- a/internal/gatewayapi/testdata/httproute-with-backendref-add-multiple-filters.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-backendref-add-multiple-filters.out.yaml @@ -147,7 +147,8 @@ xdsIR: addRequestHeaders: - append: false name: add-header-3 - value: some-value + value: + - some-value protocol: HTTP weight: 1 hostname: '*' @@ -172,10 +173,12 @@ xdsIR: addRequestHeaders: - append: true name: add-header-1 - value: some-value + value: + - some-value - append: true name: add-header-2 - value: some-value + value: + - some-value protocol: HTTP weight: 8 - addressType: IP diff --git a/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-add-multiple-filters.out.yaml b/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-add-multiple-filters.out.yaml index a86e71b4534..605aa384f3e 100644 --- a/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-add-multiple-filters.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-add-multiple-filters.out.yaml @@ -134,13 +134,16 @@ xdsIR: - addRequestHeaders: - append: true name: add-header-1 - value: some-value + value: + - some-value - append: true name: add-header-2 - value: some-value + value: + - some-value - append: true name: add-header-3 - value: some-value + value: + - some-value destination: name: httproute/default/httproute-1/rule/0 settings: diff --git a/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-adds.out.yaml b/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-adds.out.yaml index 39cc44429f6..f122fc17d5b 100644 --- a/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-adds.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-adds.out.yaml @@ -144,19 +144,24 @@ xdsIR: - addRequestHeaders: - append: true name: Set-Header-1 - value: some-value + value: + - some-value - append: true name: set-header-2 - value: some-value + value: + - some-value - append: true name: set-header-3 - value: some-value + value: + - some-value - append: true name: set-header-5 - value: some-value + value: + - some-value - append: false name: set-header-4 - value: some-value + value: + - some-value destination: name: httproute/default/httproute-1/rule/0 settings: diff --git a/internal/gatewayapi/testdata/httproute-with-header-filter-empty-header-values.out.yaml b/internal/gatewayapi/testdata/httproute-with-header-filter-empty-header-values.out.yaml index b3814e2d41d..67c14e133a7 100644 --- a/internal/gatewayapi/testdata/httproute-with-header-filter-empty-header-values.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-header-filter-empty-header-values.out.yaml @@ -128,10 +128,12 @@ xdsIR: - addRequestHeaders: - append: true name: example-header-2 - value: "" + value: + - "" - append: false name: example-header-1 - value: "" + value: + - "" destination: name: httproute/default/httproute-1/rule/0 settings: diff --git a/internal/gatewayapi/testdata/httproute-with-mirror-filter-multiple.out.yaml b/internal/gatewayapi/testdata/httproute-with-mirror-filter-multiple.out.yaml index 9aa6f0bf23b..c6e534c9c63 100644 --- a/internal/gatewayapi/testdata/httproute-with-mirror-filter-multiple.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-mirror-filter-multiple.out.yaml @@ -144,13 +144,16 @@ xdsIR: - addRequestHeaders: - append: true name: X-Header-Add - value: header-val-1 + value: + - header-val-1 - append: true name: X-Header-Add-Append - value: header-val-2 + value: + - header-val-2 - append: false name: X-Header-Set - value: set-overwrites-values + value: + - set-overwrites-values destination: name: httproute/default/httproute-1/rule/0 settings: diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-adds.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-adds.out.yaml index 7b53542bdfa..6dcb4b28779 100644 --- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-adds.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-adds.out.yaml @@ -140,19 +140,24 @@ xdsIR: - addResponseHeaders: - append: true name: Set-Header-1 - value: some-value + value: + - some-value - append: true name: set-header-2 - value: some-value + value: + - some-value - append: true name: set-header-3 - value: some-value + value: + - some-value - append: true name: set-header-5 - value: some-value + value: + - some-value - append: false name: set-header-4 - value: some-value + value: + - some-value destination: name: httproute/default/httproute-1/rule/0 settings: diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-add-multiple-filters.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-add-multiple-filters.out.yaml index 459c4264740..47d61c9fcfa 100644 --- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-add-multiple-filters.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-add-multiple-filters.out.yaml @@ -134,13 +134,16 @@ xdsIR: - addResponseHeaders: - append: true name: add-header-1 - value: some-value + value: + - some-value - append: true name: add-header-2 - value: some-value + value: + - some-value - append: true name: add-header-3 - value: some-value + value: + - some-value destination: name: httproute/default/httproute-1/rule/0 settings: diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-adds.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-adds.out.yaml index d2b4ffbe3f2..1d2f4f7124c 100644 --- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-adds.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-adds.out.yaml @@ -144,19 +144,24 @@ xdsIR: - addResponseHeaders: - append: true name: Set-Header-1 - value: some-value + value: + - some-value - append: true name: set-header-2 - value: some-value + value: + - some-value - append: true name: set-header-3 - value: some-value + value: + - some-value - append: true name: set-header-5 - value: some-value + value: + - some-value - append: false name: set-header-4 - value: some-value + value: + - some-value destination: name: httproute/default/httproute-1/rule/0 settings: diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-empty-header-values.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-empty-header-values.out.yaml index 9d188a03dc0..723cabbe6f7 100644 --- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-empty-header-values.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-empty-header-values.out.yaml @@ -128,10 +128,12 @@ xdsIR: - addResponseHeaders: - append: true name: example-header-2 - value: "" + value: + - "" - append: false name: example-header-1 - value: "" + value: + - "" destination: name: httproute/default/httproute-1/rule/0 settings: diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-backend.in.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-backend.in.yaml new file mode 100644 index 00000000000..e1f50e75b2d --- /dev/null +++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-backend.in.yaml @@ -0,0 +1,107 @@ +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: /foo1 + backendRefs: + - name: service-1 + port: 8080 + - matches: + - path: + value: /foo2 + backendRefs: + - name: service-2 + 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-3 + port: 8080 +backends: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-fqdn + namespace: default + spec: + endpoints: + - fqdn: + hostname: 'primary.foo.com' + port: 3000 +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-http-route-1 + spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + extAuth: + failOpen: true + headersToExtAuth: + - header1 + - header2 + grpc: + backendRefs: + - name: backend-fqdn + kind: Backend + group: gateway.envoyproxy.io + port: 3000 diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-backend.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-backend.out.yaml new file mode 100644 index 00000000000..a89bf53a8cf --- /dev/null +++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-backend.out.yaml @@ -0,0 +1,314 @@ +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-fqdn + namespace: default + spec: + endpoints: + - fqdn: + hostname: primary.foo.com + port: 3000 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Invalid +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: /foo1 + - backendRefs: + - name: service-2 + port: 8080 + matches: + - path: + value: /foo2 + 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-3 + 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-80 + 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-1 + namespace: default + spec: + extAuth: + failOpen: true + grpc: + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-fqdn + port: 3000 + headersToExtAuth: + - header1 + - header2 + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: default + sectionName: http + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +xdsIR: + default/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-1 + namespace: default + sectionName: http + name: default/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: www.foo.com + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0/match/0/www_foo_com + pathMatch: + distinct: false + name: "" + prefix: /foo1 + security: + extAuth: + failOpen: true + grpc: + authority: primary.foo.com:3000 + destination: + name: securitypolicy/default/policy-for-http-route-1/default/backend-fqdn + settings: + - addressType: FQDN + endpoints: + - host: primary.foo.com + port: 3000 + protocol: GRPC + weight: 1 + headersToExtAuth: + - header1 + - header2 + name: securitypolicy/default/policy-for-http-route-1 + - destination: + name: httproute/default/httproute-1/rule/1 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: www.foo.com + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/1/match/0/www_foo_com + pathMatch: + distinct: false + name: "" + prefix: /foo2 + security: + extAuth: + failOpen: true + grpc: + authority: primary.foo.com:3000 + destination: + name: securitypolicy/default/policy-for-http-route-1/default/backend-fqdn + settings: + - addressType: FQDN + endpoints: + - host: primary.foo.com + port: 3000 + protocol: GRPC + weight: 1 + headersToExtAuth: + - header1 + - header2 + name: securitypolicy/default/policy-for-http-route-1 + - destination: + name: httproute/default/httproute-2/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: www.bar.com + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-2 + namespace: default + name: httproute/default/httproute-2/rule/0/match/0/www_bar_com + pathMatch: + distinct: false + name: "" + prefix: /bar diff --git a/internal/gatewayapi/tls.go b/internal/gatewayapi/tls.go index 1d38897ed26..acde9bed339 100644 --- a/internal/gatewayapi/tls.go +++ b/internal/gatewayapi/tls.go @@ -88,10 +88,13 @@ func validateTLSSecretsData(secrets []*corev1.Secret, host *gwapiv1.Hostname) er func verifyHostname(cert *x509.Certificate, host *gwapiv1.Hostname) ([]string, error) { var matchedHosts []string + listenerContext := ListenerContext{ + Listener: &gwapiv1.Listener{Hostname: host}, + } if len(cert.DNSNames) > 0 { - matchedHosts = computeHosts(cert.DNSNames, host) + matchedHosts = computeHosts(cert.DNSNames, &listenerContext) } else { - matchedHosts = computeHosts([]string{cert.Subject.CommonName}, host) + matchedHosts = computeHosts([]string{cert.Subject.CommonName}, &listenerContext) } if len(matchedHosts) > 0 { diff --git a/internal/gatewayapi/tls_test.go b/internal/gatewayapi/tls_test.go index d97824382ce..87e8b27cad6 100644 --- a/internal/gatewayapi/tls_test.go +++ b/internal/gatewayapi/tls_test.go @@ -159,7 +159,6 @@ func TestValidateTLSSecretsData(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.Name, func(t *testing.T) { secrets := createTestSecrets(t, tc.CertFile, tc.KeyFile) require.NotNil(t, secrets) @@ -204,7 +203,6 @@ func TestValidateCertificate(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.Name, func(t *testing.T) { certData, err := os.ReadFile(filepath.Join("testdata", "tls", tc.CertFile)) require.NoError(t, err) diff --git a/internal/gatewayapi/translator_test.go b/internal/gatewayapi/translator_test.go index 357f6586bee..42bb1ca37b7 100644 --- a/internal/gatewayapi/translator_test.go +++ b/internal/gatewayapi/translator_test.go @@ -64,7 +64,6 @@ func TestTranslate(t *testing.T) { require.NoError(t, err) for _, inputFile := range inputFiles { - inputFile := inputFile t.Run(testName(inputFile), func(t *testing.T) { input, err := os.ReadFile(inputFile) require.NoError(t, err) @@ -331,7 +330,6 @@ func TestTranslateWithExtensionKinds(t *testing.T) { require.NoError(t, err) for _, inputFile := range inputFiles { - inputFile := inputFile t.Run(testName(inputFile), func(t *testing.T) { input, err := os.ReadFile(inputFile) require.NoError(t, err) @@ -625,7 +623,6 @@ func TestIsValidHostname(t *testing.T) { } for _, tc := range testcases { - tc := tc t.Run(tc.name, func(t *testing.T) { err := translator.validateHostname(tc.hostname) if tc.err == "" { @@ -745,7 +742,6 @@ func TestIsValidCrossNamespaceRef(t *testing.T) { testcases = append(testcases, modified) for _, tc := range testcases { - tc := tc t.Run(tc.name, func(t *testing.T) { var referenceGrants []*gwapiv1b1.ReferenceGrant if tc.referenceGrant != nil { diff --git a/internal/globalratelimit/runner/runner_test.go b/internal/globalratelimit/runner/runner_test.go index e25f714792b..80598f7906e 100644 --- a/internal/globalratelimit/runner/runner_test.go +++ b/internal/globalratelimit/runner/runner_test.go @@ -202,7 +202,6 @@ func Test_subscribeAndTranslate(t *testing.T) { } for _, tt := range testCases { - tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() diff --git a/internal/infrastructure/kubernetes/infra_resource.go b/internal/infrastructure/kubernetes/infra_resource.go index fc471f8af33..bf32ecfd127 100644 --- a/internal/infrastructure/kubernetes/infra_resource.go +++ b/internal/infrastructure/kubernetes/infra_resource.go @@ -7,13 +7,18 @@ package kubernetes import ( "context" + "fmt" "time" appsv1 "k8s.io/api/apps/v1" autoscalingv2 "k8s.io/api/autoscaling/v2" corev1 "k8s.io/api/core/v1" policyv1 "k8s.io/api/policy/v1" + "k8s.io/apimachinery/pkg/api/equality" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/types" "github.com/envoyproxy/gateway/internal/metrics" ) @@ -116,6 +121,45 @@ func (i *Infra) createOrUpdateDeployment(ctx context.Context, r ResourceRender) } }() + old := &appsv1.Deployment{} + err = i.Client.Get(ctx, types.NamespacedName{Name: deployment.Name, Namespace: deployment.Namespace}, old) + if err != nil { + if apierrors.IsNotFound(err) { + // It's the deployment creation. + return i.Client.ServerSideApply(ctx, deployment) + } + return err + } + + if !equality.Semantic.DeepEqual(old.Spec.Selector, deployment.Spec.Selector) { + // Note: Deployment created by the old gateway controller may have a different selector generated based on a custom label feature, + // and it caused the issue that the gateway controller cannot update the deployment when users change the custom labels. + // Therefore, we changed the gateway to always use the same selector, independent of the custom labels - + // https://github.com/envoyproxy/gateway/issues/1818 + // + // But, the change could break an existing deployment with custom labels initiated by the old gateway controller + // because the selector would be different. + // + // Here, as a workaround, we always copy the selector from the old deployment to the new deployment + // so that the update can be always applied successfully. + deployment.Spec.Selector = old.Spec.Selector + + match, err := isSelectorMatch(deployment.Spec.Selector, deployment.Spec.Template.Labels) + if err != nil { + return err + } + if !match { + // If the selector now doesn't match with labels of the pod template, return an error. + // It could happen, for example, when users changed the custom label from {"foo": "bar"} to {"foo": "barv2"} + // because the pod's labels have {"foo": "barv2"} while the selector keeps {"foo": "bar"}. + // We cannot help this case, and just error it out. + // In this case, users should recreate the envoy proxy with the new custom label, instead of upgrading it. + // Once they recreate the envoy proxy, the envoy gateway of this version doesn't generate the selector based on the custom label, + // and the issue won't happen again, even if they have to the custom label again. + return fmt.Errorf("an illegal change in a custom label of EnvoyProxy is detected when updating %s/%s. The custom label config of deployment in EnvoyProxy, which is initiated with the envoy gateway of v1.1 or earlier, is immutable. Please recreate an envoy proxy with a new custom label if you need to change the custom label. This issue won't happen with the envoy proxy resource initialized by the envoygateway v1.2 or later", deployment.Namespace, deployment.Name) + } + } + return i.Client.ServerSideApply(ctx, deployment) } @@ -153,9 +197,56 @@ func (i *Infra) createOrUpdateDaemonSet(ctx context.Context, r ResourceRender) ( } }() + old := &appsv1.DaemonSet{} + err = i.Client.Get(ctx, types.NamespacedName{Name: daemonSet.Name, Namespace: daemonSet.Namespace}, old) + if err != nil { + if apierrors.IsNotFound(err) { + // It's the daemonset creation. + return i.Client.ServerSideApply(ctx, daemonSet) + } + return err + } + + if !equality.Semantic.DeepEqual(old.Spec.Selector, daemonSet.Spec.Selector) { + // Note: Daemonset created by the old gateway controller may have a different selector generated based on a custom label feature, + // and it caused the issue that the gateway controller cannot update the daemonset when users change the custom labels. + // Therefore, we changed the gateway to always use the same selector, independent of the custom labels - + // https://github.com/envoyproxy/gateway/issues/1818 + // + // But, the change could break an existing daemonset with custom labels initiated by the old gateway controller + // because the selector would be different. + // + // Here, as a workaround, we always copy the selector from the old daemonset to the new daemonset + // so that the update can be always applied successfully. + daemonSet.Spec.Selector = old.Spec.Selector + match, err := isSelectorMatch(daemonSet.Spec.Selector, daemonSet.Spec.Template.Labels) + if err != nil { + return err + } + if !match { + // If the selector now doesn't match with labels of the pod template, return an error. + // It could happen, for example, when users changed the custom label from {"foo": "bar"} to {"foo": "barv2"} + // because the pod's labels have {"foo": "barv2"} while the selector keeps {"foo": "bar"}. + // We cannot help this case, and just error it out. + // In this case, users should recreate the envoy proxy with the new custom label, instead of upgrading it. + // Once they recreate the envoy proxy, the envoy gateway of this version doesn't generate the selector based on the custom label, + // and the issue won't happen again, even if they have to the custom label again. + return fmt.Errorf("an illegal change in a custom label of EnvoyProxy is detected when updating %s/%s. The custom label config of daemonset in EnvoyProxy, which is initiated with the envoy gateway of v1.1 or earlier, is immutable. Please recreate an envoy proxy with a new custom label if you need to change the custom label. This issue won't happen with the envoy proxy resource initialized by the envoygateway v1.2 or later", daemonSet.Namespace, daemonSet.Name) + } + } + return i.Client.ServerSideApply(ctx, daemonSet) } +func isSelectorMatch(labelselector *metav1.LabelSelector, l map[string]string) (bool, error) { + selector, err := metav1.LabelSelectorAsSelector(labelselector) + if err != nil { + return false, fmt.Errorf("invalid label selector is generated: %w", err) + } + + return selector.Matches(labels.Set(l)), nil +} + func (i *Infra) createOrUpdatePodDisruptionBudget(ctx context.Context, r ResourceRender) (err error) { var ( pdb *policyv1.PodDisruptionBudget diff --git a/internal/infrastructure/kubernetes/proxy/resource.go b/internal/infrastructure/kubernetes/proxy/resource.go index 5045de6390a..406694be9bb 100644 --- a/internal/infrastructure/kubernetes/proxy/resource.go +++ b/internal/infrastructure/kubernetes/proxy/resource.go @@ -226,9 +226,9 @@ func expectedProxyContainers(infra *ir.ProxyInfra, }, }, TimeoutSeconds: 1, - PeriodSeconds: 10, + PeriodSeconds: 5, SuccessThreshold: 1, - FailureThreshold: 3, + FailureThreshold: 1, }, Lifecycle: &corev1.Lifecycle{ PreStop: &corev1.LifecycleHandler{ diff --git a/internal/infrastructure/kubernetes/proxy/resource_provider.go b/internal/infrastructure/kubernetes/proxy/resource_provider.go index e48122b62ea..dd5907b7d9b 100644 --- a/internal/infrastructure/kubernetes/proxy/resource_provider.go +++ b/internal/infrastructure/kubernetes/proxy/resource_provider.go @@ -192,6 +192,19 @@ func (r *ResourceRender) ConfigMap() (*corev1.ConfigMap, error) { }, nil } +// stableSelector returns a stable selector based on the owning gateway labels. +// "stable" here means the selector doesn't change when the infra is updated. +func (r *ResourceRender) stableSelector() *metav1.LabelSelector { + labels := map[string]string{} + for k, v := range r.infra.GetProxyMetadata().Labels { + if k == gatewayapi.OwningGatewayNameLabel || k == gatewayapi.OwningGatewayNamespaceLabel || k == gatewayapi.OwningGatewayClassLabel { + labels[k] = v + } + } + + return resource.GetSelector(envoyLabels(labels)) +} + // Deployment returns the expected Deployment based on the provided infra. func (r *ResourceRender) Deployment() (*appsv1.Deployment, error) { proxyConfig := r.infra.GetProxyConfig() @@ -222,8 +235,6 @@ func (r *ResourceRender) Deployment() (*appsv1.Deployment, error) { if err != nil { return nil, err } - podLabels := r.getPodLabels(deploymentConfig.Pod) - selector := resource.GetSelector(podLabels) deployment := &appsv1.Deployment{ TypeMeta: metav1.TypeMeta{ @@ -238,10 +249,11 @@ func (r *ResourceRender) Deployment() (*appsv1.Deployment, error) { Spec: appsv1.DeploymentSpec{ Replicas: deploymentConfig.Replicas, Strategy: *deploymentConfig.Strategy, - Selector: selector, + // Deployment's selector is immutable. + Selector: r.stableSelector(), Template: corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Labels: selector.MatchLabels, + Labels: r.getPodLabels(deploymentConfig.Pod), Annotations: podAnnotations, }, Spec: corev1.PodSpec{ @@ -317,8 +329,6 @@ func (r *ResourceRender) DaemonSet() (*appsv1.DaemonSet, error) { if err != nil { return nil, err } - podLabels := r.getPodLabels(daemonSetConfig.Pod) - selector := resource.GetSelector(podLabels) daemonSet := &appsv1.DaemonSet{ TypeMeta: metav1.TypeMeta{ @@ -331,11 +341,12 @@ func (r *ResourceRender) DaemonSet() (*appsv1.DaemonSet, error) { Annotations: dsAnnotations, }, Spec: appsv1.DaemonSetSpec{ - Selector: selector, + // Daemonset's selector is immutable. + Selector: r.stableSelector(), UpdateStrategy: *daemonSetConfig.Strategy, Template: corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Labels: selector.MatchLabels, + Labels: r.getPodLabels(daemonSetConfig.Pod), Annotations: podAnnotations, }, Spec: r.getPodSpec(containers, nil, daemonSetConfig.Pod, proxyConfig), @@ -369,11 +380,6 @@ func (r *ResourceRender) PodDisruptionBudget() (*policyv1.PodDisruptionBudget, e return nil, nil } - labels, err := r.getLabels() - if err != nil { - return nil, err - } - return &policyv1.PodDisruptionBudget{ ObjectMeta: metav1.ObjectMeta{ Name: r.Name(), @@ -385,9 +391,7 @@ func (r *ResourceRender) PodDisruptionBudget() (*policyv1.PodDisruptionBudget, e }, Spec: policyv1.PodDisruptionBudgetSpec{ MinAvailable: &intstr.IntOrString{IntVal: ptr.Deref(podDisruptionBudget.MinAvailable, 0)}, - Selector: &metav1.LabelSelector{ - MatchLabels: labels, - }, + Selector: r.stableSelector(), }, }, nil } diff --git a/internal/infrastructure/kubernetes/proxy/resource_test.go b/internal/infrastructure/kubernetes/proxy/resource_test.go index 3cf71f2aea2..31054b1ef1d 100644 --- a/internal/infrastructure/kubernetes/proxy/resource_test.go +++ b/internal/infrastructure/kubernetes/proxy/resource_test.go @@ -30,7 +30,6 @@ func TestEnvoyPodSelector(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run("", func(t *testing.T) { got := envoyLabels(tc.in) require.Equal(t, tc.expected, got) diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/component-level.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/component-level.yaml index 0622977315d..7f1bc6c41ab 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/component-level.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/component-level.yaml @@ -74,12 +74,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/custom.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/custom.yaml index 8f2752be07c..72c5d026b9b 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/custom.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/custom.yaml @@ -16,7 +16,6 @@ spec: app.kubernetes.io/component: proxy app.kubernetes.io/managed-by: envoy-gateway app.kubernetes.io/name: envoy - foo.bar: custom-label gateway.envoyproxy.io/owning-gateway-name: default gateway.envoyproxy.io/owning-gateway-namespace: default template: @@ -258,12 +257,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default-env.yaml index 1d5a93c5ba2..b59b07a086c 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default-env.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default-env.yaml @@ -256,12 +256,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml index 7ee2909f896..0808d5c0180 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml @@ -241,12 +241,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml index 7190df8f86f..73bc606336c 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml @@ -212,12 +212,12 @@ spec: name: EnvoyHTTPSPort protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/extension-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/extension-env.yaml index 3ceb7cee0ea..4f2f396b763 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/extension-env.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/extension-env.yaml @@ -260,12 +260,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml index 9b8a0fcaf4b..2088c4cb3ce 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml @@ -23,8 +23,6 @@ spec: app.kubernetes.io/name: envoy gateway.envoyproxy.io/owning-gateway-name: default gateway.envoyproxy.io/owning-gateway-namespace: default - label1: value1-override - label2: value2 template: metadata: annotations: @@ -252,12 +250,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml index 970f58ba1ab..169eeb59394 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml @@ -241,12 +241,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/shutdown-manager.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/shutdown-manager.yaml index 3bb5ccbe620..725055a9f4d 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/shutdown-manager.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/shutdown-manager.yaml @@ -242,12 +242,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/volumes.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/volumes.yaml index 060e0d42b92..b993f3bfbc1 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/volumes.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/volumes.yaml @@ -260,12 +260,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml index ffc184f3fd8..c43c64302f3 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml @@ -246,12 +246,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-concurrency.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-concurrency.yaml index 850b8a2510e..568aa4164ad 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-concurrency.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-concurrency.yaml @@ -74,12 +74,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml index e75a89be5bc..612363ca2e6 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml @@ -243,12 +243,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml index 424eae5f2a3..a0324cb54e4 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml @@ -241,12 +241,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml index fb4fc761bb2..c31ea245056 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml @@ -241,12 +241,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml index 96a1e21f963..a0ebcf2e918 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml @@ -241,12 +241,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml index 7436383cc8e..e1d7c76a069 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml @@ -241,12 +241,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml index e98fd731131..b985e8d0f02 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml @@ -77,12 +77,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml index edcfa7b5322..445bf70d28c 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml @@ -78,12 +78,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml index 88983936f25..7628caffe1d 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml @@ -19,7 +19,6 @@ spec: app.kubernetes.io/component: proxy app.kubernetes.io/managed-by: envoy-gateway app.kubernetes.io/name: envoy - foo.bar: custom-label gateway.envoyproxy.io/owning-gateway-name: default gateway.envoyproxy.io/owning-gateway-namespace: default strategy: @@ -263,12 +262,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: 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 07ceadcfb6d..f017b2d26ed 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml @@ -19,7 +19,6 @@ spec: app.kubernetes.io/component: proxy app.kubernetes.io/managed-by: envoy-gateway app.kubernetes.io/name: envoy - foo.bar: custom-label gateway.envoyproxy.io/owning-gateway-name: default gateway.envoyproxy.io/owning-gateway-namespace: default strategy: @@ -263,12 +262,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml index 4000dacbda3..992d976f40e 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml @@ -261,12 +261,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml index 44777d51a52..3bd69459a53 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml @@ -245,12 +245,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml index bee1b53938a..fa7078ae684 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml @@ -216,12 +216,12 @@ spec: name: EnvoyHTTPSPort protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml index e84fd418ead..21ddbb9e6fc 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml @@ -265,12 +265,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: 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 460de06f269..0fb0d414016 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 @@ -25,8 +25,6 @@ spec: app.kubernetes.io/name: envoy gateway.envoyproxy.io/owning-gateway-name: default gateway.envoyproxy.io/owning-gateway-namespace: default - label1: value1-override - label2: value2 strategy: type: RollingUpdate template: @@ -256,12 +254,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml index 5fe7b493015..8d70d4d85cd 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml @@ -245,12 +245,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/shutdown-manager.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/shutdown-manager.yaml index 9ab5e2cc0dd..9f70f8bb642 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/shutdown-manager.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/shutdown-manager.yaml @@ -246,12 +246,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml index 51f0ccc3a8a..1395e60cba7 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml @@ -265,12 +265,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml index cfc2685d49d..1bb027eacc5 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml @@ -250,12 +250,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml index c01d19873f1..44e6370811c 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml @@ -78,12 +78,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml index ef9f75cc636..397b43b9753 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml @@ -245,12 +245,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml index 81d0cbac111..a1aa0917bfd 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml @@ -247,12 +247,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: 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 83f2881be23..57258870015 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 @@ -245,12 +245,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml index f1dc2a9bc6f..2dd83e8e3d6 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml @@ -245,12 +245,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: 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 cc8f66c7e33..72d297ca12a 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml @@ -245,12 +245,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: 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 4083f99d3fe..20fcb8589a2 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 @@ -245,12 +245,12 @@ spec: name: metrics protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /ready port: 19001 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/proxy_configmap_test.go b/internal/infrastructure/kubernetes/proxy_configmap_test.go index b16a0f61bbf..a761b569498 100644 --- a/internal/infrastructure/kubernetes/proxy_configmap_test.go +++ b/internal/infrastructure/kubernetes/proxy_configmap_test.go @@ -95,7 +95,6 @@ func TestCreateOrUpdateProxyConfigMap(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { var cli client.Client if tc.current != nil { @@ -162,7 +161,6 @@ func TestDeleteConfigProxyMap(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { cli := fakeclient.NewClientBuilder().WithScheme(envoygateway.GetScheme()).WithObjects(tc.current).Build() kube := NewInfra(cli, cfg) diff --git a/internal/infrastructure/kubernetes/proxy_daemonset_test.go b/internal/infrastructure/kubernetes/proxy_daemonset_test.go new file mode 100644 index 00000000000..e9fef86470c --- /dev/null +++ b/internal/infrastructure/kubernetes/proxy_daemonset_test.go @@ -0,0 +1,266 @@ +// 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" + "testing" + + "github.com/stretchr/testify/require" + appsv1 "k8s.io/api/apps/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/client" + fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake" + + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" + "github.com/envoyproxy/gateway/internal/envoygateway" + "github.com/envoyproxy/gateway/internal/envoygateway/config" + "github.com/envoyproxy/gateway/internal/gatewayapi" + "github.com/envoyproxy/gateway/internal/infrastructure/kubernetes/proxy" + resource2 "github.com/envoyproxy/gateway/internal/infrastructure/kubernetes/resource" + "github.com/envoyproxy/gateway/internal/ir" +) + +func daemonsetWithImage(ds *appsv1.DaemonSet, image string) *appsv1.DaemonSet { + dCopy := ds.DeepCopy() + for i, c := range dCopy.Spec.Template.Spec.Containers { + if c.Name == envoyContainerName { + dCopy.Spec.Template.Spec.Containers[i].Image = image + } + } + return dCopy +} + +func daemonsetWithSelectorAndLabel(ds *appsv1.DaemonSet, selector *metav1.LabelSelector, additionalLabel map[string]string) *appsv1.DaemonSet { + dCopy := ds.DeepCopy() + if selector != nil { + dCopy.Spec.Selector = selector + } + for k, v := range additionalLabel { + dCopy.Spec.Template.Labels[k] = v + } + return dCopy +} + +func TestCreateOrUpdateProxyDaemonSet(t *testing.T) { + cfg, err := config.New() + require.NoError(t, err) + + infra := ir.NewInfra() + infra.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNamespaceLabel] = "default" + infra.Proxy.GetProxyMetadata().Labels[gatewayapi.OwningGatewayNameLabel] = infra.Proxy.Name + infra.Proxy.Config = &egv1a1.EnvoyProxy{ + Spec: egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + // Use daemonset, instead of deployment. + EnvoyDaemonSet: egv1a1.DefaultKubernetesDaemonSet(egv1a1.DefaultEnvoyProxyImage), + EnvoyService: egv1a1.DefaultKubernetesService(), + }, + }, + }, + } + + r := proxy.NewResourceRender(cfg.Namespace, infra.GetProxyInfra(), cfg.EnvoyGateway) + ds, err := r.DaemonSet() + require.NoError(t, err) + + testCases := []struct { + name string + in *ir.Infra + current *appsv1.DaemonSet + want *appsv1.DaemonSet + wantErr bool + }{ + { + name: "create daemonset", + in: infra, + want: ds, + }, + { + name: "daemonset exists", + in: infra, + current: ds, + want: ds, + }, + { + name: "update daemonset image", + in: &ir.Infra{ + Proxy: &ir.ProxyInfra{ + Metadata: &ir.InfraMetadata{ + Labels: map[string]string{ + gatewayapi.OwningGatewayNamespaceLabel: "default", + gatewayapi.OwningGatewayNameLabel: infra.Proxy.Name, + }, + }, + Config: &egv1a1.EnvoyProxy{ + Spec: egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + EnvoyDaemonSet: &egv1a1.KubernetesDaemonSetSpec{ + Container: &egv1a1.KubernetesContainerSpec{ + Image: ptr.To("envoyproxy/envoy-dev:v1.2.3"), + }, + }, + }, + }, + }, + }, + Name: ir.DefaultProxyName, + Listeners: ir.NewProxyListeners(), + }, + }, + current: ds, + want: daemonsetWithImage(ds, "envoyproxy/envoy-dev:v1.2.3"), + }, + { + name: "update daemonset label", + in: &ir.Infra{ + Proxy: &ir.ProxyInfra{ + Metadata: &ir.InfraMetadata{ + Labels: map[string]string{ + gatewayapi.OwningGatewayNamespaceLabel: "default", + gatewayapi.OwningGatewayNameLabel: infra.Proxy.Name, + }, + }, + Config: &egv1a1.EnvoyProxy{ + Spec: egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + EnvoyDaemonSet: &egv1a1.KubernetesDaemonSetSpec{ + Pod: &egv1a1.KubernetesPodSpec{ + Labels: map[string]string{ + // Add a new label to the custom label config. + // It wouldn't break the daemonset because the selector would still match after this label update. + "custom-label": "version1", + }, + }, + }, + }, + }, + }, + }, + Name: ir.DefaultProxyName, + Listeners: ir.NewProxyListeners(), + }, + }, + current: ds, + // Selector is not updated with a custom label, only pod's label is updated. + want: daemonsetWithSelectorAndLabel(ds, nil, map[string]string{"custom-label": "version1"}), + }, + { + name: "the daemonset originally has a selector and label, and an user add a new label to the custom label config", + in: &ir.Infra{ + Proxy: &ir.ProxyInfra{ + Metadata: &ir.InfraMetadata{ + Labels: map[string]string{ + gatewayapi.OwningGatewayNamespaceLabel: "default", + gatewayapi.OwningGatewayNameLabel: infra.Proxy.Name, + }, + }, + Config: &egv1a1.EnvoyProxy{ + Spec: egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + EnvoyDaemonSet: &egv1a1.KubernetesDaemonSetSpec{ + Pod: &egv1a1.KubernetesPodSpec{ + Labels: map[string]string{ + "custom-label": "version1", + "another-custom-label": "version1", // added. + }, + }, + }, + }, + }, + }, + }, + Name: ir.DefaultProxyName, + Listeners: ir.NewProxyListeners(), + }, + }, + current: daemonsetWithSelectorAndLabel(ds, resource2.GetSelector(map[string]string{"custom-label": "version1"}), map[string]string{"custom-label": "version1"}), + // Only label is updated, selector is not updated. + want: daemonsetWithSelectorAndLabel(ds, resource2.GetSelector(map[string]string{"custom-label": "version1"}), map[string]string{"custom-label": "version1", "another-custom-label": "version1"}), + }, + { + name: "the daemonset originally has a selector and label, and an user update an existing custom label", + in: &ir.Infra{ + Proxy: &ir.ProxyInfra{ + Metadata: &ir.InfraMetadata{ + Labels: map[string]string{ + gatewayapi.OwningGatewayNamespaceLabel: "default", + gatewayapi.OwningGatewayNameLabel: infra.Proxy.Name, + }, + }, + Config: &egv1a1.EnvoyProxy{ + Spec: egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + EnvoyDaemonSet: &egv1a1.KubernetesDaemonSetSpec{ + Pod: &egv1a1.KubernetesPodSpec{ + Labels: map[string]string{ + // Update the label value which will break the daemonset + // because the selector cannot be updated while the user wants to update the label value. + // We cannot help this case, just emit an error and let the user recreate the envoy proxy by themselves. + "custom-label": "version2", + }, + }, + }, + }, + }, + }, + }, + Name: ir.DefaultProxyName, + Listeners: ir.NewProxyListeners(), + }, + }, + current: daemonsetWithSelectorAndLabel(ds, resource2.GetSelector(map[string]string{"custom-label": "version1"}), map[string]string{"custom-label": "version1"}), + wantErr: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + var cli client.Client + if tc.current != nil { + cli = fakeclient.NewClientBuilder(). + WithScheme(envoygateway.GetScheme()). + WithObjects(tc.current). + WithInterceptorFuncs(interceptorFunc). + Build() + } else { + cli = fakeclient.NewClientBuilder(). + WithScheme(envoygateway.GetScheme()). + WithInterceptorFuncs(interceptorFunc). + Build() + } + + kube := NewInfra(cli, cfg) + r := proxy.NewResourceRender(kube.Namespace, tc.in.GetProxyInfra(), cfg.EnvoyGateway) + err := kube.createOrUpdateDaemonSet(context.Background(), r) + if tc.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + + actual := &appsv1.DaemonSet{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: kube.Namespace, + Name: proxy.ExpectedResourceHashedName(tc.in.Proxy.Name), + }, + } + require.NoError(t, kube.Client.Get(context.Background(), client.ObjectKeyFromObject(actual), actual)) + require.Equal(t, tc.want.Spec, actual.Spec) + }) + } +} diff --git a/internal/infrastructure/kubernetes/proxy_deployment_test.go b/internal/infrastructure/kubernetes/proxy_deployment_test.go index a1d595b750d..616101e18a2 100644 --- a/internal/infrastructure/kubernetes/proxy_deployment_test.go +++ b/internal/infrastructure/kubernetes/proxy_deployment_test.go @@ -21,6 +21,7 @@ import ( "github.com/envoyproxy/gateway/internal/envoygateway/config" "github.com/envoyproxy/gateway/internal/gatewayapi" "github.com/envoyproxy/gateway/internal/infrastructure/kubernetes/proxy" + resource2 "github.com/envoyproxy/gateway/internal/infrastructure/kubernetes/resource" "github.com/envoyproxy/gateway/internal/ir" ) @@ -39,6 +40,17 @@ func deploymentWithImage(deploy *appsv1.Deployment, image string) *appsv1.Deploy return dCopy } +func deploymentWithSelectorAndLabel(deploy *appsv1.Deployment, selector *metav1.LabelSelector, additionalLabel map[string]string) *appsv1.Deployment { + dCopy := deploy.DeepCopy() + if selector != nil { + dCopy.Spec.Selector = selector + } + for k, v := range additionalLabel { + dCopy.Spec.Template.Labels[k] = v + } + return dCopy +} + func TestCreateOrUpdateProxyDeployment(t *testing.T) { cfg, err := config.New() require.NoError(t, err) @@ -56,6 +68,7 @@ func TestCreateOrUpdateProxyDeployment(t *testing.T) { in *ir.Infra current *appsv1.Deployment want *appsv1.Deployment + wantErr bool }{ { name: "create deployment", @@ -99,10 +112,116 @@ func TestCreateOrUpdateProxyDeployment(t *testing.T) { current: deploy, want: deploymentWithImage(deploy, "envoyproxy/envoy-dev:v1.2.3"), }, + { + name: "update deployment label", + in: &ir.Infra{ + Proxy: &ir.ProxyInfra{ + Metadata: &ir.InfraMetadata{ + Labels: map[string]string{ + gatewayapi.OwningGatewayNamespaceLabel: "default", + gatewayapi.OwningGatewayNameLabel: infra.Proxy.Name, + }, + }, + Config: &egv1a1.EnvoyProxy{ + Spec: egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + EnvoyDeployment: &egv1a1.KubernetesDeploymentSpec{ + Pod: &egv1a1.KubernetesPodSpec{ + Labels: map[string]string{ + "custom-label": "version1", // added. + }, + }, + }, + }, + }, + }, + }, + Name: ir.DefaultProxyName, + Listeners: ir.NewProxyListeners(), + }, + }, + current: deploy, + // Selector is not updated with a custom label, only pod's label is updated. + want: deploymentWithSelectorAndLabel(deploy, nil, map[string]string{"custom-label": "version1"}), + }, + { + name: "the daemonset originally has a selector and label, and an user add a new label to the custom label config", + in: &ir.Infra{ + Proxy: &ir.ProxyInfra{ + Metadata: &ir.InfraMetadata{ + Labels: map[string]string{ + gatewayapi.OwningGatewayNamespaceLabel: "default", + gatewayapi.OwningGatewayNameLabel: infra.Proxy.Name, + }, + }, + Config: &egv1a1.EnvoyProxy{ + Spec: egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + EnvoyDeployment: &egv1a1.KubernetesDeploymentSpec{ + Pod: &egv1a1.KubernetesPodSpec{ + Labels: map[string]string{ + "custom-label": "version1", + // Add a new label to the custom label config. + // It wouldn't break the deployment because the selector would still match after this label update. + "another-custom-label": "version1", // added. + }, + }, + }, + }, + }, + }, + }, + Name: ir.DefaultProxyName, + Listeners: ir.NewProxyListeners(), + }, + }, + current: deploymentWithSelectorAndLabel(deploy, resource2.GetSelector(map[string]string{"custom-label": "version1"}), map[string]string{"custom-label": "version1"}), + // Only label is updated, selector is not updated. + want: deploymentWithSelectorAndLabel(deploy, resource2.GetSelector(map[string]string{"custom-label": "version1"}), map[string]string{"custom-label": "version1", "another-custom-label": "version1"}), + }, + { + name: "the deployment originally has a selector and label, and an user update an existing custom label", + in: &ir.Infra{ + Proxy: &ir.ProxyInfra{ + Metadata: &ir.InfraMetadata{ + Labels: map[string]string{ + gatewayapi.OwningGatewayNamespaceLabel: "default", + gatewayapi.OwningGatewayNameLabel: infra.Proxy.Name, + }, + }, + Config: &egv1a1.EnvoyProxy{ + Spec: egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + EnvoyDeployment: &egv1a1.KubernetesDeploymentSpec{ + Pod: &egv1a1.KubernetesPodSpec{ + Labels: map[string]string{ + // Update the label value which will break the deployment + // because the selector cannot be updated while the user wants to update the label value. + // We cannot help this case, just emit an error and let the user recreate the envoy proxy by themselves. + "custom-label": "version2", + }, + }, + }, + }, + }, + }, + }, + Name: ir.DefaultProxyName, + Listeners: ir.NewProxyListeners(), + }, + }, + current: deploymentWithSelectorAndLabel(deploy, resource2.GetSelector(map[string]string{"custom-label": "version1"}), map[string]string{"custom-label": "version1"}), + wantErr: true, + }, } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { var cli client.Client if tc.current != nil { @@ -121,6 +240,10 @@ func TestCreateOrUpdateProxyDeployment(t *testing.T) { kube := NewInfra(cli, cfg) r := proxy.NewResourceRender(kube.Namespace, tc.in.GetProxyInfra(), cfg.EnvoyGateway) err := kube.createOrUpdateDeployment(context.Background(), r) + if tc.wantErr { + require.Error(t, err) + return + } require.NoError(t, err) actual := &appsv1.Deployment{ @@ -155,7 +278,6 @@ func TestDeleteProxyDeployment(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { kube := NewInfra(cli, cfg) diff --git a/internal/infrastructure/kubernetes/proxy_infra_test.go b/internal/infrastructure/kubernetes/proxy_infra_test.go index 5c8a8d34695..de0690e82c8 100644 --- a/internal/infrastructure/kubernetes/proxy_infra_test.go +++ b/internal/infrastructure/kubernetes/proxy_infra_test.go @@ -143,7 +143,6 @@ func TestCreateProxyInfra(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { t.Parallel() kube := newTestInfra(t) @@ -210,7 +209,6 @@ func TestDeleteProxyInfra(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { t.Parallel() kube := newTestInfra(t) diff --git a/internal/infrastructure/kubernetes/proxy_service_test.go b/internal/infrastructure/kubernetes/proxy_service_test.go index 0c1c0cc6b89..ffc8e4912e6 100644 --- a/internal/infrastructure/kubernetes/proxy_service_test.go +++ b/internal/infrastructure/kubernetes/proxy_service_test.go @@ -26,7 +26,6 @@ func TestDeleteProxyService(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { kube := newTestInfra(t) infra := ir.NewInfra() diff --git a/internal/infrastructure/kubernetes/proxy_serviceaccount_test.go b/internal/infrastructure/kubernetes/proxy_serviceaccount_test.go index 2b92fc53417..9aed62b6e6b 100644 --- a/internal/infrastructure/kubernetes/proxy_serviceaccount_test.go +++ b/internal/infrastructure/kubernetes/proxy_serviceaccount_test.go @@ -166,7 +166,6 @@ func TestCreateOrUpdateProxyServiceAccount(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { cfg, err := config.New() require.NoError(t, err) diff --git a/internal/infrastructure/kubernetes/ratelimit/resource.go b/internal/infrastructure/kubernetes/ratelimit/resource.go index 162396f62db..9747be33b52 100644 --- a/internal/infrastructure/kubernetes/ratelimit/resource.go +++ b/internal/infrastructure/kubernetes/ratelimit/resource.go @@ -184,9 +184,9 @@ func expectedRateLimitContainers(rateLimit *egv1a1.RateLimit, rateLimitDeploymen }, }, TimeoutSeconds: 1, - PeriodSeconds: 10, + PeriodSeconds: 5, SuccessThreshold: 1, - FailureThreshold: 3, + FailureThreshold: 1, }, }, } @@ -329,7 +329,11 @@ func expectedRateLimitContainerEnv(rateLimit *egv1a1.RateLimit, rateLimitDeploym }, { Name: UseStatsdEnvVar, - Value: "false", + Value: "true", + }, + { + Name: "STATSD_PORT", + Value: "9125", }, { Name: ConfigTypeEnvVar, diff --git a/internal/infrastructure/kubernetes/ratelimit/resource_provider_test.go b/internal/infrastructure/kubernetes/ratelimit/resource_provider_test.go index 4ee3a144bd9..47c4901e198 100644 --- a/internal/infrastructure/kubernetes/ratelimit/resource_provider_test.go +++ b/internal/infrastructure/kubernetes/ratelimit/resource_provider_test.go @@ -56,7 +56,6 @@ func TestRateLimitLabelSelector(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { got := LabelSelector() require.ElementsMatch(t, tc.expected, got) @@ -80,7 +79,6 @@ func TestRateLimitLabels(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run(tc.name, func(t *testing.T) { got := rateLimitLabels() require.Equal(t, tc.expected, got) diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/custom.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/custom.yaml index c750b09a0b9..c6c0bb1a696 100644 --- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/custom.yaml +++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/custom.yaml @@ -50,7 +50,9 @@ spec: - name: LOG_LEVEL value: info - name: USE_STATSD - value: "false" + value: "true" + - name: STATSD_PORT + value: "9125" - name: CONFIG_TYPE value: GRPC_XDS_SOTW - name: CONFIG_GRPC_XDS_SERVER_URL @@ -87,12 +89,12 @@ spec: name: grpc protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /healthcheck port: 8080 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/default-env.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/default-env.yaml index c750b09a0b9..c6c0bb1a696 100644 --- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/default-env.yaml +++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/default-env.yaml @@ -50,7 +50,9 @@ spec: - name: LOG_LEVEL value: info - name: USE_STATSD - value: "false" + value: "true" + - name: STATSD_PORT + value: "9125" - name: CONFIG_TYPE value: GRPC_XDS_SOTW - name: CONFIG_GRPC_XDS_SERVER_URL @@ -87,12 +89,12 @@ spec: name: grpc protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /healthcheck port: 8080 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/default.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/default.yaml index 277d5e649d9..26c21e23653 100644 --- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/default.yaml +++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/default.yaml @@ -51,7 +51,9 @@ spec: - name: LOG_LEVEL value: info - name: USE_STATSD - value: "false" + value: "true" + - name: STATSD_PORT + value: "9125" - name: CONFIG_TYPE value: GRPC_XDS_SOTW - name: CONFIG_GRPC_XDS_SERVER_URL @@ -88,12 +90,12 @@ spec: name: grpc protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /healthcheck port: 8080 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/disable-prometheus.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/disable-prometheus.yaml index 0cbbd6dbbb8..0dcbfb3f209 100644 --- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/disable-prometheus.yaml +++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/disable-prometheus.yaml @@ -47,7 +47,9 @@ spec: - name: LOG_LEVEL value: info - name: USE_STATSD - value: "false" + value: "true" + - name: STATSD_PORT + value: "9125" - name: CONFIG_TYPE value: GRPC_XDS_SOTW - name: CONFIG_GRPC_XDS_SERVER_URL @@ -84,12 +86,12 @@ spec: name: grpc protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /healthcheck port: 8080 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing-custom.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing-custom.yaml index 1d53f34a9bc..78cdd0c784d 100644 --- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing-custom.yaml +++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing-custom.yaml @@ -51,7 +51,9 @@ spec: - name: LOG_LEVEL value: info - name: USE_STATSD - value: "false" + value: "true" + - name: STATSD_PORT + value: "9125" - name: CONFIG_TYPE value: GRPC_XDS_SOTW - name: CONFIG_GRPC_XDS_SERVER_URL @@ -103,12 +105,12 @@ spec: name: grpc protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /healthcheck port: 8080 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing.yaml index 56bd0a7dfe3..f0396c5aa44 100644 --- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing.yaml +++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing.yaml @@ -51,7 +51,9 @@ spec: - name: LOG_LEVEL value: info - name: USE_STATSD - value: "false" + value: "true" + - name: STATSD_PORT + value: "9125" - name: CONFIG_TYPE value: GRPC_XDS_SOTW - name: CONFIG_GRPC_XDS_SERVER_URL @@ -103,12 +105,12 @@ spec: name: grpc protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /healthcheck port: 8080 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/extension-env.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/extension-env.yaml index 4468e0df0e4..9bf03106f2d 100644 --- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/extension-env.yaml +++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/extension-env.yaml @@ -50,7 +50,9 @@ spec: - name: LOG_LEVEL value: info - name: USE_STATSD - value: "false" + value: "true" + - name: STATSD_PORT + value: "9125" - name: CONFIG_TYPE value: GRPC_XDS_SOTW - name: CONFIG_GRPC_XDS_SERVER_URL @@ -91,12 +93,12 @@ spec: name: grpc protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /healthcheck port: 8080 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/override-env.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/override-env.yaml index 826deab69ba..c6c0bb1a696 100644 --- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/override-env.yaml +++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/override-env.yaml @@ -51,6 +51,8 @@ spec: value: info - name: USE_STATSD value: "true" + - name: STATSD_PORT + value: "9125" - name: CONFIG_TYPE value: GRPC_XDS_SOTW - name: CONFIG_GRPC_XDS_SERVER_URL @@ -87,12 +89,12 @@ spec: name: grpc protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /healthcheck port: 8080 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/patch-deployment.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/patch-deployment.yaml index 790de9e159a..8482050ec25 100644 --- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/patch-deployment.yaml +++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/patch-deployment.yaml @@ -51,7 +51,9 @@ spec: - name: LOG_LEVEL value: info - name: USE_STATSD - value: "false" + value: "true" + - name: STATSD_PORT + value: "9125" - name: CONFIG_TYPE value: GRPC_XDS_SOTW - name: CONFIG_GRPC_XDS_SERVER_URL @@ -88,12 +90,12 @@ spec: name: grpc protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /healthcheck port: 8080 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/redis-tls-settings.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/redis-tls-settings.yaml index e3e723c1d40..2e223af79c4 100644 --- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/redis-tls-settings.yaml +++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/redis-tls-settings.yaml @@ -51,6 +51,8 @@ spec: value: info - name: USE_STATSD value: "true" + - name: STATSD_PORT + value: "9125" - name: CONFIG_TYPE value: GRPC_XDS_SOTW - name: CONFIG_GRPC_XDS_SERVER_URL @@ -95,12 +97,12 @@ spec: name: grpc protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /healthcheck port: 8080 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/tolerations.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/tolerations.yaml index 5cbedb98853..525c2b1f75d 100644 --- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/tolerations.yaml +++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/tolerations.yaml @@ -51,6 +51,8 @@ spec: value: info - name: USE_STATSD value: "true" + - name: STATSD_PORT + value: "9125" - name: CONFIG_TYPE value: GRPC_XDS_SOTW - name: CONFIG_GRPC_XDS_SERVER_URL @@ -95,12 +97,12 @@ spec: name: grpc protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /healthcheck port: 8080 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/volumes.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/volumes.yaml index fcee6df457d..165a6819288 100644 --- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/volumes.yaml +++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/volumes.yaml @@ -51,6 +51,8 @@ spec: value: info - name: USE_STATSD value: "true" + - name: STATSD_PORT + value: "9125" - name: CONFIG_TYPE value: GRPC_XDS_SOTW - name: CONFIG_GRPC_XDS_SERVER_URL @@ -95,12 +97,12 @@ spec: name: grpc protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /healthcheck port: 8080 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-node-selector.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-node-selector.yaml index 1365ac63f8f..44ea2f4b856 100644 --- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-node-selector.yaml +++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-node-selector.yaml @@ -51,7 +51,9 @@ spec: - name: LOG_LEVEL value: info - name: USE_STATSD - value: "false" + value: "true" + - name: STATSD_PORT + value: "9125" - name: CONFIG_TYPE value: GRPC_XDS_SOTW - name: CONFIG_GRPC_XDS_SERVER_URL @@ -88,12 +90,12 @@ spec: name: grpc protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /healthcheck port: 8080 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-topology-spread-constraints.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-topology-spread-constraints.yaml index 1558a925c33..9ca2c8e53e9 100644 --- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-topology-spread-constraints.yaml +++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-topology-spread-constraints.yaml @@ -51,7 +51,9 @@ spec: - name: LOG_LEVEL value: info - name: USE_STATSD - value: "false" + value: "true" + - name: STATSD_PORT + value: "9125" - name: CONFIG_TYPE value: GRPC_XDS_SOTW - name: CONFIG_GRPC_XDS_SERVER_URL @@ -88,12 +90,12 @@ spec: name: grpc protocol: TCP readinessProbe: - failureThreshold: 3 + failureThreshold: 1 httpGet: path: /healthcheck port: 8080 scheme: HTTP - periodSeconds: 10 + periodSeconds: 5 successThreshold: 1 timeoutSeconds: 1 resources: diff --git a/internal/infrastructure/kubernetes/ratelimit_deployment_test.go b/internal/infrastructure/kubernetes/ratelimit_deployment_test.go index d57e003d383..ea0e5017fd3 100644 --- a/internal/infrastructure/kubernetes/ratelimit_deployment_test.go +++ b/internal/infrastructure/kubernetes/ratelimit_deployment_test.go @@ -64,7 +64,6 @@ func TestCreateOrUpdateRateLimitDeployment(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { var cli client.Client if tc.current != nil { @@ -120,7 +119,6 @@ func TestDeleteRateLimitDeployment(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { kube := newTestInfra(t) kube.EnvoyGateway.RateLimit = rl diff --git a/internal/infrastructure/kubernetes/ratelimit_infra_test.go b/internal/infrastructure/kubernetes/ratelimit_infra_test.go index a5934b12086..1b4976ac361 100644 --- a/internal/infrastructure/kubernetes/ratelimit_infra_test.go +++ b/internal/infrastructure/kubernetes/ratelimit_infra_test.go @@ -127,7 +127,6 @@ func TestCreateRateLimitInfra(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { t.Parallel() kube := newTestInfra(t) @@ -193,7 +192,6 @@ func TestDeleteRateLimitInfra(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { t.Parallel() kube := newTestInfra(t) diff --git a/internal/infrastructure/kubernetes/ratelimit_service_test.go b/internal/infrastructure/kubernetes/ratelimit_service_test.go index d117d9d57bf..db6578e2a31 100644 --- a/internal/infrastructure/kubernetes/ratelimit_service_test.go +++ b/internal/infrastructure/kubernetes/ratelimit_service_test.go @@ -34,7 +34,6 @@ func TestDeleteRateLimitService(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { kube := newTestInfra(t) diff --git a/internal/infrastructure/kubernetes/ratelimit_serviceaccount_test.go b/internal/infrastructure/kubernetes/ratelimit_serviceaccount_test.go index 53084f6620d..630fa2e330a 100644 --- a/internal/infrastructure/kubernetes/ratelimit_serviceaccount_test.go +++ b/internal/infrastructure/kubernetes/ratelimit_serviceaccount_test.go @@ -88,7 +88,6 @@ func TestCreateOrUpdateRateLimitServiceAccount(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { var cli client.Client if tc.current != nil { diff --git a/internal/infrastructure/kubernetes/resource/resource.go b/internal/infrastructure/kubernetes/resource/resource.go index dbdc289eec3..dcbbadadb40 100644 --- a/internal/infrastructure/kubernetes/resource/resource.go +++ b/internal/infrastructure/kubernetes/resource/resource.go @@ -38,7 +38,7 @@ func ExpectedServiceSpec(service *egv1a1.KubernetesServiceSpec) corev1.ServiceSp if service.AllocateLoadBalancerNodePorts != nil { serviceSpec.AllocateLoadBalancerNodePorts = service.AllocateLoadBalancerNodePorts } - if service.LoadBalancerSourceRanges != nil && len(service.LoadBalancerSourceRanges) > 0 { + if len(service.LoadBalancerSourceRanges) > 0 { serviceSpec.LoadBalancerSourceRanges = service.LoadBalancerSourceRanges } if service.LoadBalancerIP != nil { diff --git a/internal/infrastructure/kubernetes/resource/resource_test.go b/internal/infrastructure/kubernetes/resource/resource_test.go index b65549911c7..52c1d73f6da 100644 --- a/internal/infrastructure/kubernetes/resource/resource_test.go +++ b/internal/infrastructure/kubernetes/resource/resource_test.go @@ -156,7 +156,6 @@ func TestGetSelector(t *testing.T) { } for _, tc := range cases { - tc := tc t.Run("", func(t *testing.T) { got := GetSelector(tc.in) require.Equal(t, tc.expected, got.MatchLabels) diff --git a/internal/ir/infra_test.go b/internal/ir/infra_test.go index dcc1e0324d5..92781e06c61 100644 --- a/internal/ir/infra_test.go +++ b/internal/ir/infra_test.go @@ -116,7 +116,6 @@ func TestValidateInfra(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { err := tc.infra.Validate() if !tc.expect { @@ -142,7 +141,6 @@ func TestNewInfra(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { actual := NewInfra() require.Equal(t, tc.expected, actual) @@ -165,7 +163,6 @@ func TestNewProxyInfra(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { actual := NewProxyInfra() require.Equal(t, tc.expected, actual) @@ -205,7 +202,6 @@ func TestObjectName(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { actual := tc.infra.Proxy.ObjectName() require.Equal(t, tc.expected, actual) diff --git a/internal/ir/xds.go b/internal/ir/xds.go index 7cc5ed8f354..c698bea626d 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -25,6 +25,10 @@ import ( egv1a1validation "github.com/envoyproxy/gateway/api/v1alpha1/validation" ) +const ( + EmptyPath = "" +) + var ( ErrListenerNameEmpty = errors.New("field Name must be specified") ErrListenerAddressInvalid = errors.New("field Address must be a valid IP address") @@ -490,6 +494,12 @@ type HeaderSettings struct { // (Edge request is the request from external clients to front Envoy) and not reset it, which is the current Envoy behaviour. // It defaults to false. PreserveXRequestID bool `json:"preserveXRequestID,omitempty" yaml:"preserveXRequestID,omitempty"` + + // EarlyAddRequestHeaders defines headers that would be added before envoy request processing. + EarlyAddRequestHeaders []AddHeader `json:"earlyAddRequestHeaders,omitempty" yaml:"earlyAddRequestHeaders,omitempty"` + + // EarlyRemoveRequestHeaders defines headers that would be removed before envoy request processing. + EarlyRemoveRequestHeaders []string `json:"earlyRemoveRequestHeaders,omitempty" yaml:"earlyRemoveRequestHeaders,omitempty"` } // ClientTimeout sets the timeout configuration for downstream connections @@ -565,8 +575,8 @@ type HTTPRoute struct { UseClientProtocol *bool `json:"useClientProtocol,omitempty" yaml:"useClientProtocol,omitempty"` // Metadata is used to enrich envoy route metadata with user and provider-specific information Metadata *ResourceMetadata `json:"metadata,omitempty" yaml:"metadata,omitempty"` - // DNS is used to configure how DNS resolution is handled for the route - DNS *DNS `json:"dns,omitempty" yaml:"dns,omitempty"` + // SessionPersistence holds the configuration for session persistence. + SessionPersistence *SessionPersistence `json:"sessionPersistence,omitempty" yaml:"sessionPersistence,omitempty"` } // DNS contains configuration options for DNS resolution. @@ -578,6 +588,33 @@ type DNS struct { RespectDNSTTL *bool `json:"respectDnsTtl,omitempty"` } +// SessionPersistence defines the desired state of SessionPersistence. +// +k8s:deepcopy-gen=true +type SessionPersistence struct { + // Cookie defines the configuration for cookie-based session persistence. + // Either Cookie or Header must be non-empty. + Cookie *CookieBasedSessionPersistence `json:"cookie,omitempty" yaml:"cookie,omitempty"` + // Header defines the configuration for header-based session persistence. + // Either Cookie or Header must be non-empty. + Header *HeaderBasedSessionPersistence `json:"header,omitempty" yaml:"header,omitempty"` +} + +// CookieBasedSessionPersistence defines the configuration for cookie-based session persistence. +// +k8s:deepcopy-gen=true +type CookieBasedSessionPersistence struct { + // Name defines the name of the persistent session token. + Name string `json:"name"` + + TTL *metav1.Duration `json:"ttl,omitempty" yaml:"ttl,omitempty"` +} + +// HeaderBasedSessionPersistence defines the configuration for header-based session persistence. +// +k8s:deepcopy-gen=true +type HeaderBasedSessionPersistence struct { + // Name defines the name of the persistent session token. + Name string `json:"name"` +} + // TrafficFeatures holds the information associated with the Backend Traffic Policy. // +k8s:deepcopy-gen=true type TrafficFeatures struct { @@ -605,6 +642,8 @@ type TrafficFeatures struct { // HTTP2 provides HTTP/2 configuration for clusters // +optional HTTP2 *HTTP2Settings `json:"http2,omitempty" yaml:"http2,omitempty"` + // DNS is used to configure how DNS resolution is handled by the Envoy Proxy cluster + DNS *DNS `json:"dns,omitempty" yaml:"dns,omitempty"` } func (b *TrafficFeatures) Validate() error { @@ -817,6 +856,9 @@ type ExtAuth struct { // Only one of GRPCService or HTTPService may be specified. HTTP *HTTPExtAuthService `json:"http,omitempty"` + // Traffic contains configuration for traffic features for the ExtAuth service + Traffic *TrafficFeatures `json:"traffic,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 @@ -1113,6 +1155,10 @@ type DestinationSetting struct { // invalid endpoints are represents with a // non-zero weight with an empty endpoints list Weight *uint32 `json:"weight,omitempty" yaml:"weight,omitempty"` + // Priority default to priority 0, the highest level. + // If multiple destinations share the same priority, they will all be utilized. + // Lower priority endpoints will be used only if higher priority levels are unavailable. + Priority *uint32 `json:"priority,omitempty"` // Protocol associated with this destination/port. Protocol AppProtocol `json:"protocol,omitempty" yaml:"protocol,omitempty"` Endpoints []*DestinationEndpoint `json:"endpoints,omitempty" yaml:"endpoints,omitempty"` @@ -1194,9 +1240,9 @@ func NewDestEndpoint(host string, port uint32) *DestinationEndpoint { // AddHeader configures a header to be added to a request or response. // +k8s:deepcopy-gen=true type AddHeader struct { - Name string `json:"name" yaml:"name"` - Value string `json:"value" yaml:"value"` - Append bool `json:"append" yaml:"append"` + Name string `json:"name" yaml:"name"` + Value []string `json:"value" yaml:"value"` + Append bool `json:"append" yaml:"append"` } // Validate the fields within the AddHeader structure @@ -1514,7 +1560,8 @@ type UDPRoute struct { Timeout *Timeout `json:"timeout,omitempty" yaml:"timeout,omitempty"` // settings of upstream connection BackendConnection *BackendConnection `json:"backendConnection,omitempty" yaml:"backendConnection,omitempty"` - DNS *DNS `json:"dns,omitempty" yaml:"dns,omitempty"` + // DNS is used to configure how DNS resolution is handled by the Envoy Proxy cluster + DNS *DNS `json:"dns,omitempty" yaml:"dns,omitempty"` } // Validate the fields within the UDPListener structure @@ -1653,6 +1700,7 @@ type ALSAccessLog struct { CELMatches []string `json:"celMatches,omitempty" yaml:"celMatches,omitempty"` LogName string `json:"name" yaml:"name"` Destination RouteDestination `json:"destination,omitempty" yaml:"destination,omitempty"` + Traffic *TrafficFeatures `json:"traffic,omitempty" yaml:"traffic,omitempty"` Type egv1a1.ALSEnvoyProxyAccessLogType `json:"type" yaml:"type"` Text *string `json:"text,omitempty" yaml:"text,omitempty"` Attributes map[string]string `json:"attributes,omitempty" yaml:"attributes,omitempty"` @@ -1676,6 +1724,7 @@ type OpenTelemetryAccessLog struct { Attributes map[string]string `json:"attributes,omitempty" yaml:"attributes,omitempty"` Resources map[string]string `json:"resources,omitempty" yaml:"resources,omitempty"` Destination RouteDestination `json:"destination,omitempty" yaml:"destination,omitempty"` + Traffic *TrafficFeatures `json:"traffic,omitempty" yaml:"traffic,omitempty"` } // EnvoyPatchPolicy defines the intermediate representation of the EnvoyPatchPolicy resource. @@ -1716,7 +1765,12 @@ type JSONPatchOperation struct { Op string `json:"op" yaml:"op"` // 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"` + // +optional + Path *string `json:"path,omitempty" yaml:"path,omitempty"` + // JSONPath specifies the locations of the target document/field where the operation will be performed + // Refer to https://datatracker.ietf.org/doc/rfc9535/ for more details. + // +optional + JSONPath *string `json:"jsonPath,omitempty" yaml:"jsonPath,omitempty"` // 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. @@ -1726,6 +1780,14 @@ type JSONPatchOperation struct { Value *apiextensionsv1.JSON `json:"value,omitempty" yaml:"value,omitempty"` } +func (o *JSONPatchOperation) IsPathNilOrEmpty() bool { + return o.Path == nil || *o.Path == EmptyPath +} + +func (o *JSONPatchOperation) IsJSONPathNilOrEmpty() bool { + return o.JSONPath == nil || *o.JSONPath == EmptyPath +} + // Tracing defines the configuration for tracing a Envoy xDS Resource // +k8s:deepcopy-gen=true type Tracing struct { @@ -1734,6 +1796,7 @@ type Tracing struct { SamplingRate float64 `json:"samplingRate,omitempty"` CustomTags map[string]egv1a1.CustomTag `json:"customTags,omitempty"` Destination RouteDestination `json:"destination,omitempty"` + Traffic *TrafficFeatures `json:"traffic,omitempty"` Provider egv1a1.TracingProvider `json:"provider"` } @@ -1915,6 +1978,8 @@ type ActiveHealthCheck struct { HTTP *HTTPHealthChecker `json:"http,omitempty" yaml:"http,omitempty"` // TCP defines the configuration of tcp health checker. TCP *TCPHealthChecker `json:"tcp,omitempty" yaml:"tcp,omitempty"` + // GRPC defines if the GRPC healthcheck service should be used + GRPC *GRPCHealthChecker `json:"grpc,omitempty" yaml:"grpc,omitempty"` } func (h *HealthCheck) SetHTTPHostIfAbsent(host string) { @@ -1947,6 +2012,9 @@ func (h *HealthCheck) Validate() error { if h.Active.TCP != nil { matchCount++ } + if h.Active.GRPC != nil { + matchCount++ + } if matchCount > 1 { errs = errors.Join(errs, ErrHealthCheckerInvalid) } @@ -2041,6 +2109,15 @@ func (h HTTPStatus) Validate() error { return nil } +// GRPCHealthChecker defines the settings of the gRPC health check. +// +k8s:deepcopy-gen=true +type GRPCHealthChecker struct { + // Service is the name of a specific service hosted by the server for + // which the health check should be requested. If not specified, then the default + // is to send a health check request for the entire server. + Service *string `json:"service,omitempty" yaml:"service,omitempty"` +} + // TCPHealthChecker defines the settings of tcp health check. // +k8s:deepcopy-gen=true type TCPHealthChecker struct { @@ -2230,6 +2307,9 @@ type ExtProc struct { // Destination defines the destination for the gRPC External Processing service. Destination RouteDestination `json:"destination" yaml:"destination"` + // Traffic holds the features associated with traffic management + Traffic *TrafficFeatures `json:"traffic,omitempty" yaml:"traffic,omitempty"` + // Authority is the hostname:port of the HTTP External Processing service. Authority string `json:"authority" yaml:"authority"` diff --git a/internal/ir/xds_test.go b/internal/ir/xds_test.go index 9492c378344..876e37f9e13 100644 --- a/internal/ir/xds_test.go +++ b/internal/ir/xds_test.go @@ -338,17 +338,16 @@ var ( AddRequestHeaders: []AddHeader{ { Name: "example-header", - Value: "example-value", + Value: []string{"example-value"}, Append: true, }, { Name: "example-header-2", - Value: "example-value-2", + Value: []string{"example-value-2"}, Append: false, }, { Name: "empty-header", - Value: "", Append: false, }, }, @@ -376,12 +375,12 @@ var ( AddRequestHeaders: []AddHeader{ { Name: "example-header", - Value: "example-value", + Value: []string{"example-value"}, Append: true, }, { Name: "example-header", - Value: "example-value-2", + Value: []string{"example-value-2"}, Append: false, }, }, @@ -401,7 +400,7 @@ var ( AddRequestHeaders: []AddHeader{ { Name: "", - Value: "example-value", + Value: []string{"example-value"}, Append: true, }, }, @@ -416,17 +415,16 @@ var ( AddResponseHeaders: []AddHeader{ { Name: "example-header", - Value: "example-value", + Value: []string{"example-value"}, Append: true, }, { Name: "example-header-2", - Value: "example-value-2", + Value: []string{"example-value-2"}, Append: false, }, { Name: "empty-header", - Value: "", Append: false, }, }, @@ -454,12 +452,12 @@ var ( AddResponseHeaders: []AddHeader{ { Name: "example-header", - Value: "example-value", + Value: []string{"example-value"}, Append: true, }, { Name: "example-header", - Value: "example-value-2", + Value: []string{"example-value-2"}, Append: false, }, }, @@ -479,7 +477,7 @@ var ( AddResponseHeaders: []AddHeader{ { Name: "", - Value: "example-value", + Value: []string{"example-value"}, Append: true, }, }, @@ -579,7 +577,6 @@ func TestValidateXds(t *testing.T) { }, } for _, test := range tests { - test := test t.Run(test.name, func(t *testing.T) { if test.want == nil { require.NoError(t, test.input.Validate()) @@ -634,7 +631,6 @@ func TestValidateHTTPListener(t *testing.T) { }, } for _, test := range tests { - test := test t.Run(test.name, func(t *testing.T) { if test.want == nil { require.NoError(t, test.input.Validate()) @@ -686,7 +682,6 @@ func TestValidateTCPListener(t *testing.T) { }, } for _, test := range tests { - test := test t.Run(test.name, func(t *testing.T) { if test.want == nil { require.NoError(t, test.input.Validate()) @@ -736,7 +731,6 @@ func TestValidateTLSListenerConfig(t *testing.T) { }, } for _, test := range tests { - test := test t.Run(test.name, func(t *testing.T) { if test.want == nil { require.NoError(t, test.input.Validate()) @@ -849,7 +843,6 @@ func TestValidateUDPListener(t *testing.T) { }, } for _, test := range tests { - test := test t.Run(test.name, func(t *testing.T) { if test.want == nil { require.NoError(t, test.input.Validate()) @@ -1001,7 +994,6 @@ func TestValidateHTTPRoute(t *testing.T) { }, } for _, test := range tests { - test := test t.Run(test.name, func(t *testing.T) { if test.want == nil { require.NoError(t, test.input.Validate()) @@ -1043,7 +1035,6 @@ func TestValidateTCPRoute(t *testing.T) { }, } for _, test := range tests { - test := test t.Run(test.name, func(t *testing.T) { if test.want == nil { require.NoError(t, test.input.Validate()) @@ -1169,7 +1160,6 @@ func TestValidateRouteDestination(t *testing.T) { }, } for _, test := range tests { - test := test t.Run(test.name, func(t *testing.T) { if test.want == nil { require.NoError(t, test.input.Validate()) @@ -1209,7 +1199,6 @@ func TestValidateStringMatch(t *testing.T) { }, } for _, test := range tests { - test := test t.Run(test.name, func(t *testing.T) { if test.want == nil { require.NoError(t, test.input.Validate()) @@ -1347,7 +1336,6 @@ func TestPrintable(t *testing.T) { }, } for _, test := range tests { - test := test t.Run(test.name, func(t *testing.T) { assert.Equal(t, *test.want, *test.input.Printable()) }) diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go index dabb7af5afd..4423f71ba0c 100644 --- a/internal/ir/zz_generated.deepcopy.go +++ b/internal/ir/zz_generated.deepcopy.go @@ -25,6 +25,11 @@ func (in *ALSAccessLog) DeepCopyInto(out *ALSAccessLog) { copy(*out, *in) } in.Destination.DeepCopyInto(&out.Destination) + if in.Traffic != nil { + in, out := &in.Traffic, &out.Traffic + *out = new(TrafficFeatures) + (*in).DeepCopyInto(*out) + } if in.Text != nil { in, out := &in.Text, &out.Text *out = new(string) @@ -176,6 +181,11 @@ func (in *ActiveHealthCheck) DeepCopyInto(out *ActiveHealthCheck) { *out = new(TCPHealthChecker) (*in).DeepCopyInto(*out) } + if in.GRPC != nil { + in, out := &in.GRPC, &out.GRPC + *out = new(GRPCHealthChecker) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveHealthCheck. @@ -191,6 +201,11 @@ func (in *ActiveHealthCheck) DeepCopy() *ActiveHealthCheck { // 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 + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddHeader. @@ -531,6 +546,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 *CookieBasedSessionPersistence) DeepCopyInto(out *CookieBasedSessionPersistence) { + *out = *in + if in.TTL != nil { + in, out := &in.TTL, &out.TTL + *out = new(v1.Duration) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CookieBasedSessionPersistence. +func (in *CookieBasedSessionPersistence) DeepCopy() *CookieBasedSessionPersistence { + if in == nil { + return nil + } + out := new(CookieBasedSessionPersistence) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CoreListenerDetails) DeepCopyInto(out *CoreListenerDetails) { *out = *in @@ -613,7 +648,9 @@ func (in *DestinationFilters) DeepCopyInto(out *DestinationFilters) { if in.AddRequestHeaders != nil { in, out := &in.AddRequestHeaders, &out.AddRequestHeaders *out = make([]AddHeader, len(*in)) - copy(*out, *in) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } if in.RemoveRequestHeaders != nil { in, out := &in.RemoveRequestHeaders, &out.RemoveRequestHeaders @@ -623,7 +660,9 @@ func (in *DestinationFilters) DeepCopyInto(out *DestinationFilters) { if in.AddResponseHeaders != nil { in, out := &in.AddResponseHeaders, &out.AddResponseHeaders *out = make([]AddHeader, len(*in)) - copy(*out, *in) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } if in.RemoveResponseHeaders != nil { in, out := &in.RemoveResponseHeaders, &out.RemoveResponseHeaders @@ -650,6 +689,11 @@ func (in *DestinationSetting) DeepCopyInto(out *DestinationSetting) { *out = new(uint32) **out = **in } + if in.Priority != nil { + in, out := &in.Priority, &out.Priority + *out = new(uint32) + **out = **in + } if in.Endpoints != nil { in, out := &in.Endpoints, &out.Endpoints *out = make([]*DestinationEndpoint, len(*in)) @@ -792,6 +836,11 @@ func (in *ExtAuth) DeepCopyInto(out *ExtAuth) { *out = new(HTTPExtAuthService) (*in).DeepCopyInto(*out) } + if in.Traffic != nil { + in, out := &in.Traffic, &out.Traffic + *out = new(TrafficFeatures) + (*in).DeepCopyInto(*out) + } if in.HeadersToExtAuth != nil { in, out := &in.HeadersToExtAuth, &out.HeadersToExtAuth *out = make([]string, len(*in)) @@ -818,6 +867,11 @@ func (in *ExtAuth) DeepCopy() *ExtAuth { func (in *ExtProc) DeepCopyInto(out *ExtProc) { *out = *in in.Destination.DeepCopyInto(&out.Destination) + if in.Traffic != nil { + in, out := &in.Traffic, &out.Traffic + *out = new(TrafficFeatures) + (*in).DeepCopyInto(*out) + } if in.MessageTimeout != nil { in, out := &in.MessageTimeout, &out.MessageTimeout *out = new(v1.Duration) @@ -946,6 +1000,26 @@ func (in *GRPCExtAuthService) DeepCopy() *GRPCExtAuthService { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GRPCHealthChecker) DeepCopyInto(out *GRPCHealthChecker) { + *out = *in + if in.Service != nil { + in, out := &in.Service, &out.Service + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCHealthChecker. +func (in *GRPCHealthChecker) DeepCopy() *GRPCHealthChecker { + if in == nil { + return nil + } + out := new(GRPCHealthChecker) + 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 @@ -1264,7 +1338,9 @@ func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) { if in.AddRequestHeaders != nil { in, out := &in.AddRequestHeaders, &out.AddRequestHeaders *out = make([]AddHeader, len(*in)) - copy(*out, *in) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } if in.RemoveRequestHeaders != nil { in, out := &in.RemoveRequestHeaders, &out.RemoveRequestHeaders @@ -1274,7 +1350,9 @@ func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) { if in.AddResponseHeaders != nil { in, out := &in.AddResponseHeaders, &out.AddResponseHeaders *out = make([]AddHeader, len(*in)) - copy(*out, *in) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } if in.RemoveResponseHeaders != nil { in, out := &in.RemoveResponseHeaders, &out.RemoveResponseHeaders @@ -1348,9 +1426,9 @@ func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) { *out = new(ResourceMetadata) (*in).DeepCopyInto(*out) } - if in.DNS != nil { - in, out := &in.DNS, &out.DNS - *out = new(DNS) + if in.SessionPersistence != nil { + in, out := &in.SessionPersistence, &out.SessionPersistence + *out = new(SessionPersistence) (*in).DeepCopyInto(*out) } } @@ -1410,6 +1488,21 @@ func (in *HTTPWasmCode) DeepCopy() *HTTPWasmCode { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HeaderBasedSessionPersistence) DeepCopyInto(out *HeaderBasedSessionPersistence) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HeaderBasedSessionPersistence. +func (in *HeaderBasedSessionPersistence) DeepCopy() *HeaderBasedSessionPersistence { + if in == nil { + return nil + } + out := new(HeaderBasedSessionPersistence) + 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 @@ -1418,6 +1511,18 @@ func (in *HeaderSettings) DeepCopyInto(out *HeaderSettings) { *out = new(XForwardedClientCert) (*in).DeepCopyInto(*out) } + if in.EarlyAddRequestHeaders != nil { + in, out := &in.EarlyAddRequestHeaders, &out.EarlyAddRequestHeaders + *out = make([]AddHeader, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.EarlyRemoveRequestHeaders != nil { + in, out := &in.EarlyRemoveRequestHeaders, &out.EarlyRemoveRequestHeaders + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HeaderSettings. @@ -1590,6 +1695,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 + if in.Path != nil { + in, out := &in.Path, &out.Path + *out = new(string) + **out = **in + } + if in.JSONPath != nil { + in, out := &in.JSONPath, &out.JSONPath + *out = new(string) + **out = **in + } if in.From != nil { in, out := &in.From, &out.From *out = new(string) @@ -1825,6 +1940,11 @@ func (in *OpenTelemetryAccessLog) DeepCopyInto(out *OpenTelemetryAccessLog) { } } in.Destination.DeepCopyInto(&out.Destination) + if in.Traffic != nil { + in, out := &in.Traffic, &out.Traffic + *out = new(TrafficFeatures) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenTelemetryAccessLog. @@ -2334,6 +2454,31 @@ func (in *SecurityFeatures) DeepCopy() *SecurityFeatures { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SessionPersistence) DeepCopyInto(out *SessionPersistence) { + *out = *in + if in.Cookie != nil { + in, out := &in.Cookie, &out.Cookie + *out = new(CookieBasedSessionPersistence) + (*in).DeepCopyInto(*out) + } + if in.Header != nil { + in, out := &in.Header, &out.Header + *out = new(HeaderBasedSessionPersistence) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SessionPersistence. +func (in *SessionPersistence) DeepCopy() *SessionPersistence { + if in == nil { + return nil + } + out := new(SessionPersistence) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SlowStart) DeepCopyInto(out *SlowStart) { *out = *in @@ -2832,6 +2977,11 @@ func (in *Tracing) DeepCopyInto(out *Tracing) { } } in.Destination.DeepCopyInto(&out.Destination) + if in.Traffic != nil { + in, out := &in.Traffic, &out.Traffic + *out = new(TrafficFeatures) + (*in).DeepCopyInto(*out) + } in.Provider.DeepCopyInto(&out.Provider) } @@ -2903,6 +3053,11 @@ func (in *TrafficFeatures) DeepCopyInto(out *TrafficFeatures) { *out = new(HTTP2Settings) (*in).DeepCopyInto(*out) } + if in.DNS != nil { + in, out := &in.DNS, &out.DNS + *out = new(DNS) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficFeatures. diff --git a/internal/metrics/otel_label.go b/internal/metrics/otel_label.go index bcf4c472209..8c4c54c339c 100644 --- a/internal/metrics/otel_label.go +++ b/internal/metrics/otel_label.go @@ -58,8 +58,7 @@ func mergeLabelValues(attrs []attribute.KeyValue, labelValues []LabelValue) ([]a mergedAttrs := make([]attribute.KeyValue, 0, len(attrs)+len(labelValues)) mergedAttrs = append(mergedAttrs, attrs...) for _, v := range labelValues { - kv := v - mergedAttrs = append(mergedAttrs, kv.keyValue) + mergedAttrs = append(mergedAttrs, v.keyValue) } return mergedAttrs, attribute.NewSet(mergedAttrs...) diff --git a/internal/metrics/otel_metric_gauge.go b/internal/metrics/otel_metric_gauge.go index 49e02395b67..7fe0ac3dc5d 100644 --- a/internal/metrics/otel_metric_gauge.go +++ b/internal/metrics/otel_metric_gauge.go @@ -29,15 +29,19 @@ type GaugeValues struct { func (f *Gauge) Record(value float64) { f.mutex.Lock() + defer f.mutex.Unlock() + if f.current == nil { f.current = &GaugeValues{} f.stores[attribute.NewSet()] = f.current } f.current.val = value - f.mutex.Unlock() } func (f *Gauge) With(labelValues ...LabelValue) *Gauge { + f.mutex.Lock() + defer f.mutex.Unlock() + attrs, set := mergeLabelValues(f.attrs, labelValues) m := &Gauge{ g: f.g, diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go index f7e88da222d..8078e767f8a 100644 --- a/internal/provider/kubernetes/controller.go +++ b/internal/provider/kubernetes/controller.go @@ -190,7 +190,6 @@ func (r *gatewayAPIReconciler) Reconcile(ctx context.Context, _ reconcile.Reques gwcResources := make(gatewayapi.ControllerResources, 0, len(managedGCs)) for _, managedGC := range managedGCs { // Initialize resource types. - managedGC := managedGC gwcResource := gatewayapi.NewResources() gwcResource.GatewayClass = managedGC gwcResources = append(gwcResources, gwcResource) @@ -348,7 +347,6 @@ func (r *gatewayAPIReconciler) managedGatewayClasses(ctx context.Context) ([]*gw var cc controlledClasses for _, gwClass := range gatewayClasses.Items { - gwClass := gwClass if gwClass.Spec.ControllerName == r.classController { // The gatewayclass was marked for deletion and the finalizer removed, // so clean-up dependents. @@ -435,7 +433,7 @@ func (r *gatewayAPIReconciler) processBackendRefs(ctx context.Context, gwcResour backendRefKind, string(backendRef.Name)) } else { for _, endpointSlice := range endpointSliceList.Items { - endpointSlice := endpointSlice + endpointSlice := endpointSlice //nolint:copyloopvar r.log.Info("added EndpointSlice to resource tree", "namespace", endpointSlice.Namespace, "name", endpointSlice.Name) gwcResource.EndpointSlices = append(gwcResource.EndpointSlices, &endpointSlice) @@ -756,7 +754,6 @@ func (r *gatewayAPIReconciler) findReferenceGrant(ctx context.Context, from, to if r.namespaceLabel != nil { var rgs []gwapiv1b1.ReferenceGrant for _, refGrant := range refGrants { - 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 @@ -769,13 +766,35 @@ func (r *gatewayAPIReconciler) findReferenceGrant(ctx context.Context, from, to } for _, refGrant := range refGrants { - if refGrant.Namespace == to.namespace { - for _, src := range refGrant.Spec.From { - if src.Kind == gwapiv1a2.Kind(from.kind) && string(src.Namespace) == from.namespace { - return &refGrant, nil - } + if refGrant.Namespace != to.namespace { + continue + } + + var fromAllowed bool + for _, refGrantFrom := range refGrant.Spec.From { + if string(refGrantFrom.Kind) == from.kind && string(refGrantFrom.Namespace) == from.namespace { + fromAllowed = true + break + } + } + + if !fromAllowed { + continue + } + + var toAllowed bool + for _, refGrantTo := range refGrant.Spec.To { + if string(refGrantTo.Kind) == to.kind && (refGrantTo.Name == nil || *refGrantTo.Name == "" || string(*refGrantTo.Name) == to.name) { + toAllowed = true + break } } + + if !toAllowed { + continue + } + + return &refGrant, nil } // No ReferenceGrant found. @@ -794,7 +813,7 @@ func (r *gatewayAPIReconciler) processGateways(ctx context.Context, managedGC *g } for _, gtw := range gatewayList.Items { - gtw := gtw + gtw := gtw //nolint:copyloopvar 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()) @@ -811,11 +830,9 @@ func (r *gatewayAPIReconciler) processGateways(ctx context.Context, managedGC *g } for _, listener := range gtw.Spec.Listeners { - listener := listener // Get Secret for gateway if it exists. if terminatesTLS(&listener) { for _, certRef := range listener.TLS.CertificateRefs { - certRef := certRef if refsSecret(&certRef) { if err := r.processSecretRef( ctx, @@ -877,7 +894,7 @@ func (r *gatewayAPIReconciler) processEnvoyPatchPolicies(ctx context.Context, re } for _, policy := range envoyPatchPolicies.Items { - policy := policy + policy := policy //nolint:copyloopvar // Discard Status to reduce memory consumption in watchable // It will be recomputed by the gateway-api layer policy.Status = gwapiv1a2.PolicyStatus{} @@ -897,7 +914,7 @@ func (r *gatewayAPIReconciler) processClientTrafficPolicies( } for _, policy := range clientTrafficPolicies.Items { - policy := policy + policy := policy //nolint:copyloopvar // Discard Status to reduce memory consumption in watchable // It will be recomputed by the gateway-api layer policy.Status = gwapiv1a2.PolicyStatus{} @@ -917,7 +934,7 @@ func (r *gatewayAPIReconciler) processBackendTrafficPolicies(ctx context.Context } for _, policy := range backendTrafficPolicies.Items { - policy := policy + policy := policy //nolint:copyloopvar // Discard Status to reduce memory consumption in watchable // It will be recomputed by the gateway-api layer policy.Status = gwapiv1a2.PolicyStatus{} @@ -936,7 +953,7 @@ func (r *gatewayAPIReconciler) processSecurityPolicies( } for _, policy := range securityPolicies.Items { - policy := policy + policy := policy //nolint:copyloopvar // Discard Status to reduce memory consumption in watchable // It will be recomputed by the gateway-api layer policy.Status = gwapiv1a2.PolicyStatus{} @@ -961,7 +978,7 @@ func (r *gatewayAPIReconciler) processBackendTLSPolicies( } for _, policy := range backendTLSPolicies.Items { - policy := policy + policy := policy //nolint:copyloopvar // Discard Status to reduce memory consumption in watchable // It will be recomputed by the gateway-api layer policy.Status = gwapiv1a2.PolicyStatus{} @@ -981,7 +998,7 @@ func (r *gatewayAPIReconciler) processBackends(ctx context.Context, resourceTree } for _, backend := range backends.Items { - backend := backend + backend := backend //nolint:copyloopvar // Discard Status to reduce memory consumption in watchable // It will be recomputed by the gateway-api layer backend.Status = egv1a1.BackendStatus{} @@ -1767,7 +1784,7 @@ func (r *gatewayAPIReconciler) processEnvoyExtensionPolicies( } for _, policy := range envoyExtensionPolicies.Items { - policy := policy + policy := policy //nolint:copyloopvar // Discard Status to reduce memory consumption in watchable // It will be recomputed by the gateway-api layer policy.Status = gwapiv1a2.PolicyStatus{} @@ -1794,8 +1811,6 @@ func (r *gatewayAPIReconciler) processExtensionServerPolicies( } for _, policy := range polList.Items { - policy := policy - policySpec, found := policy.Object["spec"].(map[string]any) if !found { return fmt.Errorf("no spec found in %s.%s %s", policy.GetAPIVersion(), policy.GetKind(), policy.GetName()) diff --git a/internal/provider/kubernetes/controller_test.go b/internal/provider/kubernetes/controller_test.go index e3b63360163..b2fb1c3d791 100644 --- a/internal/provider/kubernetes/controller_test.go +++ b/internal/provider/kubernetes/controller_test.go @@ -73,7 +73,6 @@ func TestAddGatewayClassFinalizer(t *testing.T) { ctx := context.Background() for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { r.client = fakeclient.NewClientBuilder().WithScheme(envoygateway.GetScheme()).WithObjects(tc.gc).Build() err := r.addFinalizer(ctx, tc.gc) @@ -137,7 +136,6 @@ func TestRemoveGatewayClassFinalizer(t *testing.T) { ctx := context.Background() for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { r.client = fakeclient.NewClientBuilder().WithScheme(envoygateway.GetScheme()).WithObjects(tc.gc).Build() err := r.removeFinalizer(ctx, tc.gc) diff --git a/internal/provider/kubernetes/filters.go b/internal/provider/kubernetes/filters.go index 8ef8dc1ede1..985990fef14 100644 --- a/internal/provider/kubernetes/filters.go +++ b/internal/provider/kubernetes/filters.go @@ -26,7 +26,6 @@ func (r *gatewayAPIReconciler) getExtensionRefFilters(ctx context.Context) ([]un if r.namespaceLabel != nil { var extRs []unstructured.Unstructured for _, extR := range uExtResources { - extR := extR ok, err := r.checkObjectNamespaceLabels(&extR) if err != nil { r.log.Error(err, "failed to check namespace labels for ExtensionRefFilter %s in namespace %s: %w", extR.GetName(), extR.GetNamespace()) diff --git a/internal/provider/kubernetes/helpers_test.go b/internal/provider/kubernetes/helpers_test.go index 0d5deb0d5d3..38a634f9c7b 100644 --- a/internal/provider/kubernetes/helpers_test.go +++ b/internal/provider/kubernetes/helpers_test.go @@ -103,7 +103,6 @@ func TestGatewaysOfClass(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { gwList := &gwapiv1.GatewayList{Items: tc.gws} actual := gatewaysOfClass(gc, gwList) @@ -185,7 +184,6 @@ func TestIsGatewayClassAccepted(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { actual := isAccepted(tc.gc) require.Equal(t, tc.expect, actual) diff --git a/internal/provider/kubernetes/predicates.go b/internal/provider/kubernetes/predicates.go index e64c08619db..e606138fa09 100644 --- a/internal/provider/kubernetes/predicates.go +++ b/internal/provider/kubernetes/predicates.go @@ -208,7 +208,6 @@ func (r *gatewayAPIReconciler) isGatewayReferencingSecret(nsName *types.Namespac } for _, gw := range gwList.Items { - gw := gw if !r.validateGatewayForReconcile(&gw) { return false } @@ -549,7 +548,6 @@ func (r *gatewayAPIReconciler) updateStatusForGatewaysUnderGatewayClass(ctx cont } for _, gateway := range gateways.Items { - gateway := gateway r.updateStatusForGateway(ctx, &gateway) } diff --git a/internal/provider/kubernetes/predicates_test.go b/internal/provider/kubernetes/predicates_test.go index 6379263bdb0..054de1e5395 100644 --- a/internal/provider/kubernetes/predicates_test.go +++ b/internal/provider/kubernetes/predicates_test.go @@ -59,7 +59,6 @@ func TestGatewayClassHasMatchingController(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { res := r.hasMatchingController(tc.gc) require.Equal(t, tc.expect, res) @@ -107,8 +106,6 @@ func TestGatewayClassHasMatchingNamespaceLabels(t *testing.T) { logger := logging.DefaultLogger(egv1a1.LogLevelInfo) for _, tc := range testCases { - tc := tc - r := gatewayAPIReconciler{ classController: egv1a1.GatewayControllerName, namespaceLabel: &metav1.LabelSelector{MatchExpressions: matchExpressions(tc.namespaceLabels, metav1.LabelSelectorOpExists, []string{})}, @@ -172,7 +169,6 @@ func TestValidateGatewayForReconcile(t *testing.T) { } for _, tc := range testCases { - tc := tc r.client = fakeclient.NewClientBuilder().WithScheme(envoygateway.GetScheme()).WithObjects(tc.configs...).Build() t.Run(tc.name, func(t *testing.T) { res := r.validateGatewayForReconcile(tc.gateway) @@ -368,7 +364,6 @@ func TestValidateSecretForReconcile(t *testing.T) { } for _, tc := range testCases { - tc := tc r.client = fakeclient.NewClientBuilder(). WithScheme(envoygateway.GetScheme()). WithObjects(tc.configs...). @@ -435,7 +430,6 @@ func TestValidateEndpointSliceForReconcile(t *testing.T) { } for _, tc := range testCases { - tc := tc r.client = fakeclient.NewClientBuilder(). WithScheme(envoygateway.GetScheme()). WithObjects(tc.configs...). @@ -471,12 +465,14 @@ func TestValidateServiceForReconcile(t *testing.T) { { Type: egv1a1.ProxyAccessLogSinkTypeOpenTelemetry, OpenTelemetry: &egv1a1.OpenTelemetryEnvoyProxyAccessLog{ - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "otel-collector", - Namespace: ptr.To(gwapiv1.Namespace("default")), - Port: ptr.To(gwapiv1.PortNumber(4317)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "otel-collector", + Namespace: ptr.To(gwapiv1.Namespace("default")), + Port: ptr.To(gwapiv1.PortNumber(4317)), + }, }, }, }, @@ -491,12 +487,14 @@ func TestValidateServiceForReconcile(t *testing.T) { { Type: egv1a1.MetricSinkTypeOpenTelemetry, OpenTelemetry: &egv1a1.ProxyOpenTelemetrySink{ - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "otel-collector", - Namespace: ptr.To(gwapiv1.Namespace("default")), - Port: ptr.To(gwapiv1.PortNumber(4317)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "otel-collector", + Namespace: ptr.To(gwapiv1.Namespace("default")), + Port: ptr.To(gwapiv1.PortNumber(4317)), + }, }, }, }, @@ -507,12 +505,14 @@ func TestValidateServiceForReconcile(t *testing.T) { Tracing: &egv1a1.ProxyTracing{ Provider: egv1a1.TracingProvider{ Type: egv1a1.TracingProviderTypeOpenTelemetry, - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "otel-collector", - Namespace: ptr.To(gwapiv1.Namespace("default")), - Port: ptr.To(gwapiv1.PortNumber(4317)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "otel-collector", + Namespace: ptr.To(gwapiv1.Namespace("default")), + Port: ptr.To(gwapiv1.PortNumber(4317)), + }, }, }, }, @@ -675,10 +675,12 @@ func TestValidateServiceForReconcile(t *testing.T) { }, ExtAuth: &egv1a1.ExtAuth{ HTTP: &egv1a1.HTTPExtAuthService{ - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "ext-auth-http-service", + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "ext-auth-http-service", + }, }, }, }, @@ -708,10 +710,12 @@ func TestValidateServiceForReconcile(t *testing.T) { }, ExtAuth: &egv1a1.ExtAuth{ GRPC: &egv1a1.GRPCExtAuthService{ - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "ext-auth-grpc-service", + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "ext-auth-grpc-service", + }, }, }, }, @@ -741,10 +745,12 @@ func TestValidateServiceForReconcile(t *testing.T) { }, ExtProc: []egv1a1.ExtProc{ { - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "ext-proc-service", + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "ext-proc-service", + }, }, }, }, @@ -774,10 +780,12 @@ func TestValidateServiceForReconcile(t *testing.T) { }, ExtProc: []egv1a1.ExtProc{ { - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "ext-proc-service", + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "ext-proc-service", + }, }, }, }, @@ -836,7 +844,6 @@ func TestValidateServiceForReconcile(t *testing.T) { } for _, tc := range testCases { - tc := tc r.client = fakeclient.NewClientBuilder(). WithScheme(envoygateway.GetScheme()). WithObjects(tc.configs...). @@ -933,7 +940,6 @@ func TestValidateDeploymentForReconcile(t *testing.T) { } for _, tc := range testCases { - tc := tc r.client = fakeclient.NewClientBuilder().WithScheme(envoygateway.GetScheme()).WithObjects(tc.configs...).Build() t.Run(tc.name, func(t *testing.T) { res := r.validateDeploymentForReconcile(tc.deployment) @@ -1039,7 +1045,6 @@ func TestCheckObjectNamespaceLabels(t *testing.T) { } 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) diff --git a/internal/provider/kubernetes/routes.go b/internal/provider/kubernetes/routes.go index ad2638684cd..c52e39ef349 100644 --- a/internal/provider/kubernetes/routes.go +++ b/internal/provider/kubernetes/routes.go @@ -34,7 +34,7 @@ func (r *gatewayAPIReconciler) processTLSRoutes(ctx context.Context, gatewayName } for _, tlsRoute := range tlsRouteList.Items { - tlsRoute := tlsRoute + tlsRoute := tlsRoute //nolint:copyloopvar 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()) @@ -54,7 +54,6 @@ func (r *gatewayAPIReconciler) processTLSRoutes(ctx context.Context, gatewayName for _, rule := range tlsRoute.Spec.Rules { for _, backendRef := range rule.BackendRefs { - backendRef := backendRef ref := gatewayapi.UpgradeBackendRef(backendRef) if err := validateBackendRef(&ref); err != nil { r.log.Error(err, "invalid backendRef") @@ -114,7 +113,7 @@ func (r *gatewayAPIReconciler) processGRPCRoutes(ctx context.Context, gatewayNam } for _, grpcRoute := range grpcRouteList.Items { - grpcRoute := grpcRoute + grpcRoute := grpcRoute //nolint:copyloopvar 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()) @@ -134,7 +133,6 @@ func (r *gatewayAPIReconciler) processGRPCRoutes(ctx context.Context, gatewayNam for _, rule := range grpcRoute.Spec.Rules { for _, backendRef := range rule.BackendRefs { - backendRef := backendRef if err := validateBackendRef(&backendRef.BackendRef); err != nil { r.log.Error(err, "invalid backendRef") continue @@ -249,7 +247,7 @@ func (r *gatewayAPIReconciler) processHTTPRoutes(ctx context.Context, gatewayNam } for _, httpRoute := range httpRouteList.Items { - httpRoute := httpRoute + httpRoute := httpRoute //nolint:copyloopvar 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()) @@ -269,7 +267,6 @@ func (r *gatewayAPIReconciler) processHTTPRoutes(ctx context.Context, gatewayNam for _, rule := range httpRoute.Spec.Rules { for _, backendRef := range rule.BackendRefs { - backendRef := backendRef if err := validateBackendRef(&backendRef.BackendRef); err != nil { r.log.Error(err, "invalid backendRef") continue @@ -427,7 +424,7 @@ func (r *gatewayAPIReconciler) processTCPRoutes(ctx context.Context, gatewayName } for _, tcpRoute := range tcpRouteList.Items { - tcpRoute := tcpRoute + tcpRoute := tcpRoute //nolint:copyloopvar 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()) @@ -447,7 +444,6 @@ func (r *gatewayAPIReconciler) processTCPRoutes(ctx context.Context, gatewayName for _, rule := range tcpRoute.Spec.Rules { for _, backendRef := range rule.BackendRefs { - backendRef := backendRef ref := gatewayapi.UpgradeBackendRef(backendRef) if err := validateBackendRef(&ref); err != nil { r.log.Error(err, "invalid backendRef") @@ -506,7 +502,7 @@ func (r *gatewayAPIReconciler) processUDPRoutes(ctx context.Context, gatewayName } for _, udpRoute := range udpRouteList.Items { - udpRoute := udpRoute + udpRoute := udpRoute //nolint:copyloopvar 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()) @@ -526,7 +522,6 @@ func (r *gatewayAPIReconciler) processUDPRoutes(ctx context.Context, gatewayName for _, rule := range udpRoute.Spec.Rules { for _, backendRef := range rule.BackendRefs { - backendRef := backendRef ref := gatewayapi.UpgradeBackendRef(backendRef) if err := validateBackendRef(&ref); err != nil { r.log.Error(err, "invalid backendRef") diff --git a/internal/provider/kubernetes/routes_test.go b/internal/provider/kubernetes/routes_test.go index be6769589a1..9bd4126d325 100644 --- a/internal/provider/kubernetes/routes_test.go +++ b/internal/provider/kubernetes/routes_test.go @@ -851,7 +851,6 @@ func TestValidateHTTPRouteParentRefs(t *testing.T) { ctx := context.Background() for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { var objs []client.Object for i := range tc.classes { diff --git a/internal/provider/runner/runner_test.go b/internal/provider/runner/runner_test.go index a393462da94..8252bb407ca 100644 --- a/internal/provider/runner/runner_test.go +++ b/internal/provider/runner/runner_test.go @@ -47,7 +47,6 @@ func TestStart(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { runner := &Runner{ Config: Config{ diff --git a/internal/utils/misc_test.go b/internal/utils/misc_test.go index 5955f28aecd..f1b10bcec63 100644 --- a/internal/utils/misc_test.go +++ b/internal/utils/misc_test.go @@ -24,7 +24,6 @@ func TestGetHashedName(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { result := GetHashedName(tc.nsName, tc.length) require.Equal(t, tc.expected, result, "Result does not match expected string") diff --git a/internal/wasm/cache.go b/internal/wasm/cache.go index 6082a078855..785d8d3701a 100644 --- a/internal/wasm/cache.go +++ b/internal/wasm/cache.go @@ -247,7 +247,7 @@ func (c *localFileCache) getOrFetch(key cacheKey, opts GetOptions) (*cacheEntry, sha := sha256.Sum256(b) dChecksum = hex.EncodeToString(sha[:]) case "oci": - if opts.PullSecret != nil && len(opts.PullSecret) > 0 { + if len(opts.PullSecret) > 0 { isPrivate = true } if imageBinaryFetcher, dChecksum, err = c.prepareFetch(ctx, u, insecure, opts); err != nil { @@ -303,7 +303,7 @@ func (c *localFileCache) prepareFetch( imgFetcherOps := ImageFetcherOption{ Insecure: insecure, } - if opts.PullSecret != nil && len(opts.PullSecret) > 0 { + if len(opts.PullSecret) > 0 { imgFetcherOps.PullSecret = opts.PullSecret } fetcher := NewImageFetcher(ctx, imgFetcherOps, c.logger) diff --git a/internal/wasm/imagefetcher.go b/internal/wasm/imagefetcher.go index 5c97ad5f4a4..1b8c40fcd25 100644 --- a/internal/wasm/imagefetcher.go +++ b/internal/wasm/imagefetcher.go @@ -54,7 +54,7 @@ type ImageFetcherOption struct { } func (o *ImageFetcherOption) useAnonymous() bool { - return o.PullSecret == nil || len(o.PullSecret) == 0 + return len(o.PullSecret) == 0 } func (o *ImageFetcherOption) String() string { diff --git a/internal/xds/bootstrap/bootstrap_test.go b/internal/xds/bootstrap/bootstrap_test.go index 19e020c499e..2023a7096bd 100644 --- a/internal/xds/bootstrap/bootstrap_test.go +++ b/internal/xds/bootstrap/bootstrap_test.go @@ -86,12 +86,14 @@ func TestGetRenderedBootstrapConfig(t *testing.T) { OpenTelemetry: &egv1a1.ProxyOpenTelemetrySink{ Host: ptr.To("otel-collector.monitoring.svc"), Port: 4317, - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "otel-collector", - Namespace: ptr.To(gwapiv1.Namespace("monitoring")), - Port: ptr.To(gwapiv1.PortNumber(4317)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "otel-collector", + Namespace: ptr.To(gwapiv1.Namespace("monitoring")), + Port: ptr.To(gwapiv1.PortNumber(4317)), + }, }, }, }, diff --git a/internal/xds/server/runner/runner_test.go b/internal/xds/server/runner/runner_test.go index 45f59da0edc..74bf30f2caf 100644 --- a/internal/xds/server/runner/runner_test.go +++ b/internal/xds/server/runner/runner_test.go @@ -131,7 +131,6 @@ func TestTLSConfig(t *testing.T) { defer g.GracefulStop() for name, tc := range tests { - tc := tc t.Run(name, func(t *testing.T) { // Store certificate and key to temp dir used by serveContext. err = tc.serverCredentials.WritePEM(certFile, keyFile) diff --git a/internal/xds/translator/accesslog.go b/internal/xds/translator/accesslog.go index 01c448b65e9..8acb6e4b005 100644 --- a/internal/xds/translator/accesslog.go +++ b/internal/xds/translator/accesslog.go @@ -478,14 +478,27 @@ func processClusterForAccessLog(tCtx *types.ResourceVersionTable, al *ir.AccessL if al == nil { return nil } - // add clusters for ALS access logs for _, als := range al.ALS { + traffic := als.Traffic + // Make sure that there are safe defaults for the traffic + if traffic == nil { + traffic = &ir.TrafficFeatures{} + } if err := addXdsCluster(tCtx, &xdsClusterArgs{ - name: als.Destination.Name, - settings: als.Destination.Settings, - tSocket: nil, - endpointType: EndpointTypeStatic, + name: als.Destination.Name, + settings: als.Destination.Settings, + tSocket: nil, + endpointType: EndpointTypeStatic, + loadBalancer: traffic.LoadBalancer, + proxyProtocol: traffic.ProxyProtocol, + circuitBreaker: traffic.CircuitBreaker, + healthCheck: traffic.HealthCheck, + timeout: traffic.Timeout, + tcpkeepalive: traffic.TCPKeepalive, + backendConnection: traffic.BackendConnection, + dns: traffic.DNS, + http2Settings: traffic.HTTP2, }); err != nil && !errors.Is(err, ErrXdsClusterExists) { return err } @@ -493,12 +506,27 @@ func processClusterForAccessLog(tCtx *types.ResourceVersionTable, al *ir.AccessL // add clusters for Open Telemetry access logs for _, otel := range al.OpenTelemetry { + traffic := otel.Traffic + // Make sure that there are safe defaults for the traffic + if traffic == nil { + traffic = &ir.TrafficFeatures{} + } + if err := addXdsCluster(tCtx, &xdsClusterArgs{ - name: otel.Destination.Name, - settings: otel.Destination.Settings, - tSocket: nil, - endpointType: EndpointTypeDNS, - metrics: metrics, + name: otel.Destination.Name, + settings: otel.Destination.Settings, + tSocket: nil, + endpointType: EndpointTypeDNS, + metrics: metrics, + loadBalancer: traffic.LoadBalancer, + proxyProtocol: traffic.ProxyProtocol, + circuitBreaker: traffic.CircuitBreaker, + healthCheck: traffic.HealthCheck, + timeout: traffic.Timeout, + tcpkeepalive: traffic.TCPKeepalive, + backendConnection: traffic.BackendConnection, + dns: traffic.DNS, + http2Settings: traffic.HTTP2, }); err != nil && !errors.Is(err, ErrXdsClusterExists) { return err } diff --git a/internal/xds/translator/cluster.go b/internal/xds/translator/cluster.go index 697736dbc4d..9786ed972c6 100644 --- a/internal/xds/translator/cluster.go +++ b/internal/xds/translator/cluster.go @@ -235,7 +235,8 @@ func buildXdsHealthCheck(healthcheck *ir.ActiveHealthCheck) []*corev3.HealthChec if healthcheck.HealthyThreshold != nil { hc.HealthyThreshold = wrapperspb.UInt32(*healthcheck.HealthyThreshold) } - if healthcheck.HTTP != nil { + switch { + case healthcheck.HTTP != nil: httpChecker := &corev3.HealthCheck_HttpHealthCheck{ Host: healthcheck.HTTP.Host, Path: healthcheck.HTTP.Path, @@ -250,8 +251,7 @@ func buildXdsHealthCheck(healthcheck *ir.ActiveHealthCheck) []*corev3.HealthChec hc.HealthChecker = &corev3.HealthCheck_HttpHealthCheck_{ HttpHealthCheck: httpChecker, } - } - if healthcheck.TCP != nil { + case healthcheck.TCP != nil: tcpChecker := &corev3.HealthCheck_TcpHealthCheck{ Send: buildHealthCheckPayload(healthcheck.TCP.Send), } @@ -261,6 +261,12 @@ func buildXdsHealthCheck(healthcheck *ir.ActiveHealthCheck) []*corev3.HealthChec hc.HealthChecker = &corev3.HealthCheck_TcpHealthCheck_{ TcpHealthCheck: tcpChecker, } + case healthcheck.GRPC != nil: + hc.HealthChecker = &corev3.HealthCheck_GrpcHealthCheck_{ + GrpcHealthCheck: &corev3.HealthCheck_GrpcHealthCheck{ + ServiceName: ptr.Deref(healthcheck.GRPC.Service, ""), + }, + } } return []*corev3.HealthCheck{hc} } @@ -438,7 +444,7 @@ func buildXdsClusterLoadAssignment(clusterName string, destSettings []*ir.Destin weight = 1 } locality.LoadBalancingWeight = &wrapperspb.UInt32Value{Value: weight} - + locality.Priority = ptr.Deref(ds.Priority, 0) localities = append(localities, locality) } return &endpointv3.ClusterLoadAssignment{ClusterName: clusterName, Endpoints: localities} @@ -739,10 +745,7 @@ func (httpRoute *HTTPRouteTranslator) asClusterArgs(extra *ExtraArgs) *xdsCluste clusterArgs.timeout = bt.Timeout clusterArgs.tcpkeepalive = bt.TCPKeepalive clusterArgs.backendConnection = bt.BackendConnection - } - - if httpRoute.DNS != nil { - clusterArgs.dns = httpRoute.DNS + clusterArgs.dns = bt.DNS } return clusterArgs diff --git a/internal/xds/translator/extauth.go b/internal/xds/translator/extauth.go index 35ca41e79f6..3b64326c4c3 100644 --- a/internal/xds/translator/extauth.go +++ b/internal/xds/translator/extauth.go @@ -222,13 +222,13 @@ func (*extAuth) patchResources(tCtx *types.ResourceVersionTable, } if route.Security.ExtAuth.HTTP != nil { if err := createExtServiceXDSCluster( - &route.Security.ExtAuth.HTTP.Destination, tCtx); err != nil && !errors.Is( + &route.Security.ExtAuth.HTTP.Destination, route.Security.ExtAuth.Traffic, tCtx); err != nil && !errors.Is( err, ErrXdsClusterExists) { errs = errors.Join(errs, err) } } else { if err := createExtServiceXDSCluster( - &route.Security.ExtAuth.GRPC.Destination, tCtx); err != nil && !errors.Is( + &route.Security.ExtAuth.GRPC.Destination, route.Security.ExtAuth.Traffic, tCtx); err != nil && !errors.Is( err, ErrXdsClusterExists) { errs = errors.Join(errs, err) } diff --git a/internal/xds/translator/extproc.go b/internal/xds/translator/extproc.go index 6f4db53a08b..2bc6c4b6ba6 100644 --- a/internal/xds/translator/extproc.go +++ b/internal/xds/translator/extproc.go @@ -173,12 +173,11 @@ func (*extProc) patchResources(tCtx *types.ResourceVersionTable, for i := range route.EnvoyExtensions.ExtProcs { ep := route.EnvoyExtensions.ExtProcs[i] if err := createExtServiceXDSCluster( - &ep.Destination, tCtx); err != nil && !errors.Is( + &ep.Destination, ep.Traffic, tCtx); err != nil && !errors.Is( err, ErrXdsClusterExists) { errs = errors.Join(errs, err) } } - } return errs diff --git a/internal/xds/translator/httpfilters.go b/internal/xds/translator/httpfilters.go index ad5789fb6ff..1b994fba669 100644 --- a/internal/xds/translator/httpfilters.go +++ b/internal/xds/translator/httpfilters.go @@ -114,8 +114,10 @@ func newOrderedHTTPFilter(filter *hcmv3.HttpFilter) *OrderedHTTPFilter { order = 5 case isFilterType(filter, egv1a1.EnvoyFilterJWTAuthn): order = 6 + case isFilterType(filter, egv1a1.EnvoyFilterSessionPersistence): + order = 7 case isFilterType(filter, egv1a1.EnvoyFilterExtProc): - order = 7 + mustGetFilterIndex(filter.Name) + order = 8 + mustGetFilterIndex(filter.Name) case isFilterType(filter, egv1a1.EnvoyFilterWasm): order = 100 + mustGetFilterIndex(filter.Name) case isFilterType(filter, egv1a1.EnvoyFilterRBAC): diff --git a/internal/xds/translator/jsonpatch.go b/internal/xds/translator/jsonpatch.go index e7808abe0c5..bb8ed8bef2b 100644 --- a/internal/xds/translator/jsonpatch.go +++ b/internal/xds/translator/jsonpatch.go @@ -84,9 +84,9 @@ func processJSONPatches(tCtx *types.ResourceVersionTable, envoyPatchPolicies []* } } - // If Path is "" and op is "add", unmarshal and add the patch as a complete + // If Path and JSONPath is "" and op is "add", unmarshal and add the patch as a complete // resource - if p.Operation.Op == AddOperation && p.Operation.Path == EmptyPath { + if p.Operation.Op == AddOperation && p.Operation.IsPathNilOrEmpty() && p.Operation.IsJSONPathNilOrEmpty() { // Convert patch to JSON // The patch library expects an array so convert it into one y, err := yaml.Marshal(p.Operation.Value) @@ -106,7 +106,7 @@ func processJSONPatches(tCtx *types.ResourceVersionTable, envoyPatchPolicies []* case resourcev3.ListenerType: temp := &listenerv3.Listener{} if err = protojson.Unmarshal(jsonBytes, temp); err != nil { - tErr := fmt.Errorf(unmarshalErrorMessage(err, p.Operation.Value)) + tErr := errors.New(unmarshalErrorMessage(err, p.Operation.Value)) tErrs = errors.Join(tErrs, tErr) continue } @@ -119,7 +119,7 @@ func processJSONPatches(tCtx *types.ResourceVersionTable, envoyPatchPolicies []* case resourcev3.RouteType: temp := &routev3.RouteConfiguration{} if err = protojson.Unmarshal(jsonBytes, temp); err != nil { - tErr := fmt.Errorf(unmarshalErrorMessage(err, p.Operation.Value)) + tErr := errors.New(unmarshalErrorMessage(err, p.Operation.Value)) tErrs = errors.Join(tErrs, tErr) continue } @@ -132,7 +132,7 @@ func processJSONPatches(tCtx *types.ResourceVersionTable, envoyPatchPolicies []* case resourcev3.ClusterType: temp := &clusterv3.Cluster{} if err = protojson.Unmarshal(jsonBytes, temp); err != nil { - tErr := fmt.Errorf(unmarshalErrorMessage(err, p.Operation.Value)) + tErr := errors.New(unmarshalErrorMessage(err, p.Operation.Value)) tErrs = errors.Join(tErrs, tErr) continue } @@ -145,7 +145,7 @@ func processJSONPatches(tCtx *types.ResourceVersionTable, envoyPatchPolicies []* case resourcev3.EndpointType: temp := &endpointv3.ClusterLoadAssignment{} if err = protojson.Unmarshal(jsonBytes, temp); err != nil { - tErr := fmt.Errorf(unmarshalErrorMessage(err, p.Operation.Value)) + tErr := errors.New(unmarshalErrorMessage(err, p.Operation.Value)) tErrs = errors.Join(tErrs, tErr) continue } @@ -158,7 +158,7 @@ func processJSONPatches(tCtx *types.ResourceVersionTable, envoyPatchPolicies []* case resourcev3.SecretType: temp := &tlsv3.Secret{} if err = protojson.Unmarshal(jsonBytes, temp); err != nil { - tErr := fmt.Errorf(unmarshalErrorMessage(err, p.Operation.Value)) + tErr := errors.New(unmarshalErrorMessage(err, p.Operation.Value)) tErrs = errors.Join(tErrs, tErr) continue } @@ -240,125 +240,150 @@ func processJSONPatches(tCtx *types.ResourceVersionTable, envoyPatchPolicies []* } } - // Convert patch to JSON - // The patch library expects an array so convert it into one - y, err := yaml.Marshal([]ir.JSONPatchOperation{p.Operation}) - if err != nil { - tErr := fmt.Errorf("unable to marshal patch %+v, err: %s", p.Operation, err.Error()) - tErrs = errors.Join(tErrs, tErr) - continue - } - jsonBytes, err := yaml.YAMLToJSON(y) - if err != nil { - tErr := fmt.Errorf("unable to convert patch to json %s, err: %s", string(y), err.Error()) - tErrs = errors.Join(tErrs, tErr) - continue - } - patchObj, err := jsonpatchv5.DecodePatch(jsonBytes) - if err != nil { - tErr := fmt.Errorf("unable to decode patch %s, err: %s", string(jsonBytes), err.Error()) - tErrs = errors.Join(tErrs, tErr) - continue - } - - // Apply patch - opts := jsonpatchv5.NewApplyOptions() - opts.EnsurePathExistsOnAdd = true - modifiedJSON, err := patchObj.ApplyWithOptions(resourceJSON, opts) - if err != nil { - tErr := fmt.Errorf("unable to apply patch:\n%s on resource:\n%s, err: %s", string(jsonBytes), string(resourceJSON), err.Error()) - tErrs = errors.Join(tErrs, tErr) - continue - } - - // Unmarshal back to typed resource - // Use a temp staging variable that can be marshalled - // into and validated before saving it into the xds output resource - switch p.Type { - case resourcev3.ListenerType: - temp := &listenerv3.Listener{} - if err = protojson.Unmarshal(modifiedJSON, temp); err != nil { - tErr := fmt.Errorf(unmarshalErrorMessage(err, string(modifiedJSON))) - tErrs = errors.Join(tErrs, tErr) - continue + var jsonPointers []string + if p.Operation.JSONPath != nil { + path := "" + if p.Operation.Path != nil { + path = *p.Operation.Path } - if err = temp.Validate(); err != nil { - tErr := fmt.Errorf("validation failed for xds resource %s, err:%s", string(modifiedJSON), err.Error()) - tErrs = errors.Join(tErrs, tErr) - continue - } - if err = deepCopyPtr(temp, listener); err != nil { - tErr := fmt.Errorf("unable to copy xds resource %s, err: %w", string(modifiedJSON), err) - tErrs = errors.Join(tErrs, tErr) - continue - } - case resourcev3.RouteType: - temp := &routev3.RouteConfiguration{} - if err = protojson.Unmarshal(modifiedJSON, temp); err != nil { - tErr := fmt.Errorf(unmarshalErrorMessage(err, string(modifiedJSON))) - tErrs = errors.Join(tErrs, tErr) - continue - } - if err = temp.Validate(); err != nil { - tErr := fmt.Errorf("validation failed for xds resource %s, err:%s", string(modifiedJSON), err.Error()) - tErrs = errors.Join(tErrs, tErr) - continue - } - if err = deepCopyPtr(temp, routeConfig); err != nil { - tErr := fmt.Errorf("unable to copy xds resource %s, err: %w", string(modifiedJSON), err) - tErrs = errors.Join(tErrs, tErr) - continue - } - case resourcev3.ClusterType: - temp := &clusterv3.Cluster{} - if err = protojson.Unmarshal(modifiedJSON, temp); err != nil { - tErr := fmt.Errorf(unmarshalErrorMessage(err, string(modifiedJSON))) - tErrs = errors.Join(tErrs, tErr) - continue - } - if err = temp.Validate(); err != nil { - tErr := fmt.Errorf("validation failed for xds resource %s, err:%s", string(modifiedJSON), err.Error()) - tErrs = errors.Join(tErrs, tErr) - continue - } - if err = deepCopyPtr(temp, cluster); err != nil { - tErr := fmt.Errorf("unable to copy xds resource %s, err: %w", string(modifiedJSON), err) + jsonPointers, err = ConvertPathToPointers(resourceJSON, *p.Operation.JSONPath, path) + if err != nil { + tErr := fmt.Errorf("unable to convert jsonPath: '%s' into jsonPointers, err: %s", *p.Operation.JSONPath, err.Error()) tErrs = errors.Join(tErrs, tErr) continue } - case resourcev3.EndpointType: - temp := &endpointv3.ClusterLoadAssignment{} - if err = protojson.Unmarshal(modifiedJSON, temp); err != nil { - tErr := fmt.Errorf(unmarshalErrorMessage(err, string(modifiedJSON))) - tErrs = errors.Join(tErrs, tErr) - continue + } else { + jsonPointers = []string{*p.Operation.Path} + } + + for _, path := range jsonPointers { + op := ir.JSONPatchOperation{ + Path: &path, + Op: p.Operation.Op, + Value: p.Operation.Value, + From: p.Operation.From, } - if err = temp.Validate(); err != nil { - tErr := fmt.Errorf("validation failed for xds resource %s, err:%s", string(modifiedJSON), err.Error()) + + // Convert patch to JSON + // The patch library expects an array so convert it into one + y, err := yaml.Marshal([]ir.JSONPatchOperation{op}) + if err != nil { + tErr := fmt.Errorf("unable to marshal patch %+v, err: %s", op, err.Error()) tErrs = errors.Join(tErrs, tErr) continue } - if err = deepCopyPtr(temp, endpoint); err != nil { - tErr := fmt.Errorf("unable to copy xds resource %s, err: %w", string(modifiedJSON), err) + jsonBytes, err := yaml.YAMLToJSON(y) + if err != nil { + tErr := fmt.Errorf("unable to convert patch to json %s, err: %s", string(y), err.Error()) tErrs = errors.Join(tErrs, tErr) continue } - case resourcev3.SecretType: - temp := &tlsv3.Secret{} - if err = protojson.Unmarshal(modifiedJSON, temp); err != nil { - tErr := fmt.Errorf(unmarshalErrorMessage(err, string(modifiedJSON))) + patchObj, err := jsonpatchv5.DecodePatch(jsonBytes) + if err != nil { + tErr := fmt.Errorf("unable to decode patch %s, err: %s", string(jsonBytes), err.Error()) tErrs = errors.Join(tErrs, tErr) continue } - if err = temp.Validate(); err != nil { - tErr := fmt.Errorf("validation failed for xds resource %s, err:%s", string(modifiedJSON), err.Error()) + + // Apply patch + opts := jsonpatchv5.NewApplyOptions() + opts.EnsurePathExistsOnAdd = true + modifiedJSON, err := patchObj.ApplyWithOptions(resourceJSON, opts) + if err != nil { + tErr := fmt.Errorf("unable to apply patch:\n%s on resource:\n%s, err: %s", string(jsonBytes), string(resourceJSON), err.Error()) tErrs = errors.Join(tErrs, tErr) continue } - if err = deepCopyPtr(temp, secret); err != nil { - tErr := fmt.Errorf("unable to copy xds resource %s, err: %w", string(modifiedJSON), err) - tErrs = errors.Join(tErrs, tErr) - continue + + // Unmarshal back to typed resource + // Use a temp staging variable that can be marshalled + // into and validated before saving it into the xds output resource + switch p.Type { + case resourcev3.ListenerType: + temp := &listenerv3.Listener{} + if err = protojson.Unmarshal(modifiedJSON, temp); err != nil { + tErr := errors.New(unmarshalErrorMessage(err, string(modifiedJSON))) + tErrs = errors.Join(tErrs, tErr) + continue + } + if err = temp.Validate(); err != nil { + tErr := fmt.Errorf("validation failed for xds resource %s, err:%s", string(modifiedJSON), err.Error()) + tErrs = errors.Join(tErrs, tErr) + continue + } + if err = deepCopyPtr(temp, listener); err != nil { + tErr := fmt.Errorf("unable to copy xds resource %s, err: %w", string(modifiedJSON), err) + tErrs = errors.Join(tErrs, tErr) + continue + } + case resourcev3.RouteType: + temp := &routev3.RouteConfiguration{} + if err = protojson.Unmarshal(modifiedJSON, temp); err != nil { + tErr := errors.New(unmarshalErrorMessage(err, string(modifiedJSON))) + tErrs = errors.Join(tErrs, tErr) + continue + } + if err = temp.Validate(); err != nil { + tErr := fmt.Errorf("validation failed for xds resource %s, err:%s", string(modifiedJSON), err.Error()) + tErrs = errors.Join(tErrs, tErr) + continue + } + if err = deepCopyPtr(temp, routeConfig); err != nil { + tErr := fmt.Errorf("unable to copy xds resource %s, err: %w", string(modifiedJSON), err) + tErrs = errors.Join(tErrs, tErr) + continue + } + case resourcev3.ClusterType: + temp := &clusterv3.Cluster{} + if err = protojson.Unmarshal(modifiedJSON, temp); err != nil { + tErr := errors.New(unmarshalErrorMessage(err, string(modifiedJSON))) + tErrs = errors.Join(tErrs, tErr) + continue + } + if err = temp.Validate(); err != nil { + tErr := fmt.Errorf("validation failed for xds resource %s, err:%s", string(modifiedJSON), err.Error()) + tErrs = errors.Join(tErrs, tErr) + continue + } + if err = deepCopyPtr(temp, cluster); err != nil { + tErr := fmt.Errorf("unable to copy xds resource %s, err: %w", string(modifiedJSON), err) + tErrs = errors.Join(tErrs, tErr) + continue + } + case resourcev3.EndpointType: + temp := &endpointv3.ClusterLoadAssignment{} + if err = protojson.Unmarshal(modifiedJSON, temp); err != nil { + tErr := errors.New(unmarshalErrorMessage(err, string(modifiedJSON))) + tErrs = errors.Join(tErrs, tErr) + continue + } + if err = temp.Validate(); err != nil { + tErr := fmt.Errorf("validation failed for xds resource %s, err:%s", string(modifiedJSON), err.Error()) + tErrs = errors.Join(tErrs, tErr) + continue + } + if err = deepCopyPtr(temp, endpoint); err != nil { + tErr := fmt.Errorf("unable to copy xds resource %s, err: %w", string(modifiedJSON), err) + tErrs = errors.Join(tErrs, tErr) + continue + } + case resourcev3.SecretType: + temp := &tlsv3.Secret{} + if err = protojson.Unmarshal(modifiedJSON, temp); err != nil { + tErr := errors.New(unmarshalErrorMessage(err, string(modifiedJSON))) + tErrs = errors.Join(tErrs, tErr) + continue + } + if err = temp.Validate(); err != nil { + tErr := fmt.Errorf("validation failed for xds resource %s, err:%s", string(modifiedJSON), err.Error()) + tErrs = errors.Join(tErrs, tErr) + continue + } + if err = deepCopyPtr(temp, secret); err != nil { + tErr := fmt.Errorf("unable to copy xds resource %s, err: %w", string(modifiedJSON), err) + tErrs = errors.Join(tErrs, tErr) + continue + } } } } diff --git a/internal/xds/translator/jsonpathtopointer.go b/internal/xds/translator/jsonpathtopointer.go new file mode 100644 index 00000000000..89d7fdf1c77 --- /dev/null +++ b/internal/xds/translator/jsonpathtopointer.go @@ -0,0 +1,120 @@ +// 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 ( + "reflect" + "strings" + + "github.com/ohler55/ojg/jp" + "github.com/ohler55/ojg/oj" + "github.com/pkg/errors" +) + +func ConvertPathToPointers(jsonDoc []byte, jsonPath string, path string) ([]string, error) { + var jsonPointers []string + + jObj, err := oj.Parse(jsonDoc) + if err != nil { + return nil, errors.Wrap(err, "Error during parsing json") + } + + jPath, err := jp.ParseString(jsonPath) + if err != nil { + return nil, errors.Wrap(err, "Error during parsing jpath") + } + + if len(jPath) == 1 { + _, isRoot := jPath[0].(jp.Root) + if isRoot { + return nil, errors.New("Using only Root ('$') in json path expression is not allowed!") + } + } + + locations := jPath.Locate(jObj, 0) + for _, l := range locations { + jsonPointer, err := expToPointer(l) + if err != nil { + return nil, errors.Wrap(err, "Error during converting path to pointer") + } + jsonPointers = append(jsonPointers, concat(jsonPointer, path)) + } + return jsonPointers, nil +} + +func concat(jsonPointer string, path string) string { + if path == "" { + return jsonPointer + } + const separator string = "/" + parts := []string{ + strings.TrimSuffix(jsonPointer, separator), + strings.TrimPrefix(path, separator), + } + return strings.Join(parts, separator) +} + +func expToPointer(e jp.Expr) (string, error) { + var buf []byte + for _, f := range e { + v, err := fragToPointer(f) + if err != nil { + return "", err + } + if v != nil { + buf = append(buf, '/') + } + + buf = append(buf, v...) + } + + return string(buf), nil +} + +func fragToPointer(f jp.Frag) ([]byte, error) { + switch v := f.(type) { + case jp.Root: + return rootToPointer() + case jp.Nth: + return nthToPointer(v) + case jp.Child: + return toPointer(v) + default: + return nil, errors.New("There is no conversion implemented for " + reflect.TypeOf(v).Name()) + } +} + +func rootToPointer() ([]byte, error) { + return nil, nil +} + +func nthToPointer(f jp.Nth) ([]byte, error) { + var buf []byte + i := int(f) + if i < 0 { + buf = append(buf, '-') + i = -i + } + num := [20]byte{} + cnt := 0 + for ; i != 0; cnt++ { + num[cnt] = byte(i%10) + '0' + i /= 10 + } + if 0 < cnt { + cnt-- + for ; 0 <= cnt; cnt-- { + buf = append(buf, num[cnt]) + } + } else { + buf = append(buf, '0') + } + return buf, nil +} + +func toPointer(f jp.Frag) ([]byte, error) { + return f.Append(nil, false, true), nil +} diff --git a/internal/xds/translator/jsonpathtopointer_test.go b/internal/xds/translator/jsonpathtopointer_test.go new file mode 100644 index 00000000000..cefb5925869 --- /dev/null +++ b/internal/xds/translator/jsonpathtopointer_test.go @@ -0,0 +1,395 @@ +// 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 ( + "sort" + "strconv" + "testing" + + "github.com/ohler55/ojg/jp" + "github.com/stretchr/testify/require" +) + +const case1Simple string = `{ + "a": "b" + }` + +const case2Nested string = `{ + "a": "b", + "v": [{ + "x": "test1", + "y": "hello" + }, + { + "x": "test2", + "y": "world" + }], + "f":{ + "w": "hi", + "q": "welcome", + "y": "ciao" + }, + "y": "c" + }` + +const case3Route string = `{ + "name": "default/eg/http", + "virtual_hosts": [ + { + "name": "default/eg/http/www_test_com", + "domains": [ + "www.test.com" + ], + "routes": [ + { + "name": "httproute/default/backend/rule/0/match/0/www_test_com", + "match": { + "prefix": "/" + }, + "route": { + "cluster": "httproute/default/backend/rule/0", + "upgrade_configs": [ + { + "upgrade_type": "websocket" + } + ] + } + } + ] + }, + { + "name": "default/eg/http/www_example_com", + "domains": [ + "www.example.com" + ], + "routes": [ + { + "name": "httproute/default/backend/rule/1/match/1/www_example_com", + "match": { + "prefix": "/" + }, + "route": { + "cluster": "httproute/default/backend/rule/1", + "upgrade_configs": [ + { + "upgrade_type": "websocket" + } + ] + } + } + ] + } + ], + "ignore_port_in_host_matching": true +}` + +func Test(t *testing.T) { + tests := []struct { + // Json Document + doc string + + // JSONPath + jsonPath string + + // path + path string + + // List of expected pointers + expected []string + }{ + { + doc: case1Simple, + jsonPath: "$.a", + expected: []string{ + "/a", + }, + }, + { + doc: case2Nested, + jsonPath: "$.v[?(@.x=='test2')]", + expected: []string{ + "/v/1", + }, + }, + { + doc: case2Nested, + jsonPath: "..v[?(@.x=='test1')].y", + expected: []string{ + "/v/0/y", + }, + }, + { + doc: case2Nested, + jsonPath: "$.v[?(@.x=='test2')].y", + expected: []string{ + "/v/1/y", + }, + }, + { + doc: case2Nested, + jsonPath: "$.v[?(@.x=='test1')].y", + expected: []string{ + "/v/0/y", + }, + }, + { + doc: case2Nested, + jsonPath: "$.v[*].y", + expected: []string{ + "/v/0/y", + "/v/1/y", + }, + }, + { + doc: case2Nested, + jsonPath: "$.v[?(@.x=='UNKNOWN')].y", + expected: []string{}, + }, + { + doc: case1Simple, + jsonPath: ".a", + expected: []string{ + "/a", + }, + }, + { + doc: case1Simple, + jsonPath: "a", + expected: []string{ + "/a", + }, + }, + { + doc: case2Nested, + jsonPath: "f.w", + expected: []string{ + "/f/w", + }, + }, + { + doc: case2Nested, + jsonPath: "f.*", + expected: []string{ + "/f/w", + "/f/q", + "/f/y", + }, + }, + { + doc: case2Nested, + jsonPath: "v.*", + expected: []string{ + "/v/0", + "/v/1", + }, + }, + { + doc: case2Nested, + jsonPath: "v.**", + expected: []string{ + "/v/0/x", + "/v/0/y", + "/v/1/x", + "/v/1/y", + }, + }, + { + doc: case2Nested, + jsonPath: "$..y", + expected: []string{ + "/f/y", + "/v/0/y", + "/v/1/y", + "/y", + }, + }, + { + doc: case2Nested, + jsonPath: "..y", + expected: []string{ + "/f/y", + "/v/0/y", + "/v/1/y", + "/y", + }, + }, + { + doc: case2Nested, + jsonPath: "**.y", + expected: []string{ + "/v/0/y", + "/v/1/y", + }, + }, + { + doc: case3Route, + jsonPath: "..routes[?(@.name =~ 'www_example_com')]", + expected: []string{ + "/virtual_hosts/1/routes/0", + }, + }, + { + doc: case3Route, + jsonPath: "..routes[?(@.name =~ 'www_test_com')]", + expected: []string{ + "/virtual_hosts/0/routes/0", + }, + }, + { + doc: case3Route, + jsonPath: "..routes[?(@.name =~ 'www')]", + expected: []string{ + "/virtual_hosts/0/routes/0", + "/virtual_hosts/1/routes/0", + }, + }, + { + doc: case3Route, + jsonPath: "..routes[?(@.name =~ 'www')].route.cluster", + expected: []string{ + "/virtual_hosts/0/routes/0/route/cluster", + "/virtual_hosts/1/routes/0/route/cluster", + }, + }, + { + doc: case3Route, + jsonPath: "..routes[?(@.name =~ 'www')]['route']['cluster']", + expected: []string{ + "/virtual_hosts/0/routes/0/route/cluster", + "/virtual_hosts/1/routes/0/route/cluster", + }, + }, + { + doc: case3Route, + jsonPath: "..routes[?(@.name=='httproute/default/backend/rule/1/match/1/www_example_com')].route.upgrade_configs", + expected: []string{ + "/virtual_hosts/1/routes/0/route/upgrade_configs", + }, + }, + { + doc: case3Route, + jsonPath: "..routes[?(@.name =~ 'www')]", + path: "/abc", + expected: []string{ + "/virtual_hosts/0/routes/0/abc", + "/virtual_hosts/1/routes/0/abc", + }, + }, + { + doc: case3Route, + jsonPath: "..routes[?(@.name =~ 'www')]", + path: "abc", + expected: []string{ + "/virtual_hosts/0/routes/0/abc", + "/virtual_hosts/1/routes/0/abc", + }, + }, + { + doc: case3Route, + jsonPath: "..routes[?(@.name =~ 'www')]", + path: "/", + expected: []string{ + "/virtual_hosts/0/routes/0/", + "/virtual_hosts/1/routes/0/", + }, + }, + } + + for i, test := range tests { + + testCasePrefix := "TestCase " + strconv.Itoa(i+1) + pointers, err := ConvertPathToPointers([]byte(test.doc), test.jsonPath, test.path) + if err != nil { + t.Error(testCasePrefix + ": Error during conversion:\n" + err.Error()) + continue + } + + expectedAsString := asString(test.expected) + pointersAsString := asString(pointers) + + require.Equal(t, expectedAsString, pointersAsString) + } +} + +func TestException(t *testing.T) { + tests := []struct { + // Json Document + doc string + + // JSONPath + jsonPath string + + // path + path string + + // expected exception + expected string + }{ + { + doc: case1Simple, + jsonPath: ".$", + expected: "Error during parsing jpath", + }, + { + doc: case1Simple, + jsonPath: "$", + expected: "only Root", + }, + { + doc: "{", + jsonPath: ".$", + expected: "Error during parsing json", + }, + } + + for i, test := range tests { + + testCasePrefix := "TestCase " + strconv.Itoa(i+1) + _, err := ConvertPathToPointers([]byte(test.doc), test.jsonPath, test.path) + if err == nil { + t.Error(testCasePrefix + ": Error expected, but no error found!") + continue + } + + require.ErrorContains(t, err, test.expected) + } +} + +func TestUnexpectedFrag(t *testing.T) { + expr := jp.Expr{} + expr = append(expr, jp.Union{}) + + _, err := expToPointer(expr) + if err == nil { + t.Error("Error expected, but no error found!") + } + + require.ErrorContains(t, err, "There is no conversion implemented for Union") +} + +func TestNegativeNth(t *testing.T) { + result, err := nthToPointer(jp.Nth(-1)) + if err != nil { + t.Error(err) + } + test := string(result) + if test != "-1" { + t.Error("expected -1, but was " + test + "!") + } +} + +func asString(values []string) string { + var buf []byte + + sort.Strings(values) + for _, v := range values { + buf = append(buf, []byte(v)...) + buf = append(buf, []byte("\n")...) + } + + return string(buf) +} diff --git a/internal/xds/translator/listener.go b/internal/xds/translator/listener.go index 0812010ade1..9b442c75105 100644 --- a/internal/xds/translator/listener.go +++ b/internal/xds/translator/listener.go @@ -12,6 +12,7 @@ import ( xdscore "github.com/cncf/xds/go/xds/core/v3" matcher "github.com/cncf/xds/go/xds/type/matcher/v3" + mutation_rulesv3 "github.com/envoyproxy/go-control-plane/envoy/config/common/mutation_rules/v3" corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" listenerv3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" tls_inspectorv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/tls_inspector/v3" @@ -19,6 +20,7 @@ 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" + early_header_mutationv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/http/early_header_mutation/header_mutation/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" @@ -274,9 +276,10 @@ func (t *Translator) addHCMToXDSListener(xdsListener *listenerv3.Listener, irLis CommonHttpProtocolOptions: &corev3.HttpProtocolOptions{ HeadersWithUnderscoresAction: buildHeadersWithUnderscoresAction(irListener.Headers), }, - Tracing: hcmTracing, - ForwardClientCertDetails: buildForwardClientCertDetailsAction(irListener.Headers), - PreserveExternalRequestId: ptr.Deref(irListener.Headers, ir.HeaderSettings{}).PreserveXRequestID, + Tracing: hcmTracing, + ForwardClientCertDetails: buildForwardClientCertDetailsAction(irListener.Headers), + PreserveExternalRequestId: ptr.Deref(irListener.Headers, ir.HeaderSettings{}).PreserveXRequestID, + EarlyHeaderMutationExtensions: buildEarlyHeaderMutation(irListener.Headers), } if mgr.ForwardClientCertDetails == hcmv3.HttpConnectionManager_APPEND_FORWARD || mgr.ForwardClientCertDetails == hcmv3.HttpConnectionManager_SANITIZE_SET { @@ -365,6 +368,73 @@ func (t *Translator) addHCMToXDSListener(xdsListener *listenerv3.Listener, irLis return nil } +func buildEarlyHeaderMutation(headers *ir.HeaderSettings) []*corev3.TypedExtensionConfig { + if headers == nil || (len(headers.EarlyAddRequestHeaders) == 0 && len(headers.EarlyRemoveRequestHeaders) == 0) { + return nil + } + + var mutationRules []*mutation_rulesv3.HeaderMutation + + for _, header := range headers.EarlyAddRequestHeaders { + 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 + } + // Allow empty headers to be set, but don't add the config to do so unless necessary + if len(header.Value) == 0 { + mutationRules = append(mutationRules, &mutation_rulesv3.HeaderMutation{ + Action: &mutation_rulesv3.HeaderMutation_Append{ + Append: &corev3.HeaderValueOption{ + Header: &corev3.HeaderValue{ + Key: header.Name, + }, + AppendAction: appendAction, + KeepEmptyValue: true, + }, + }, + }) + } else { + for _, val := range header.Value { + mutationRules = append(mutationRules, &mutation_rulesv3.HeaderMutation{ + Action: &mutation_rulesv3.HeaderMutation_Append{ + Append: &corev3.HeaderValueOption{ + Header: &corev3.HeaderValue{ + Key: header.Name, + Value: val, + }, + AppendAction: appendAction, + KeepEmptyValue: val == "", + }, + }, + }) + } + } + } + + for _, header := range headers.EarlyRemoveRequestHeaders { + mr := &mutation_rulesv3.HeaderMutation{ + Action: &mutation_rulesv3.HeaderMutation_Remove{ + Remove: header, + }, + } + + mutationRules = append(mutationRules, mr) + } + + earlyHeaderMutationAny, _ := anypb.New(&early_header_mutationv3.HeaderMutation{ + Mutations: mutationRules, + }) + + return []*corev3.TypedExtensionConfig{ + { + Name: "envoy.http.early_header_mutation.header_mutation", + TypedConfig: earlyHeaderMutationAny, + }, + } +} + func addServerNamesMatch(xdsListener *listenerv3.Listener, filterChain *listenerv3.FilterChain, hostnames []string) error { // Dont add a filter chain match if the hostname is a wildcard character. if len(hostnames) > 0 && hostnames[0] != "*" { diff --git a/internal/xds/translator/route.go b/internal/xds/translator/route.go index 8a56e9e42b1..42f17ff94f1 100644 --- a/internal/xds/translator/route.go +++ b/internal/xds/translator/route.go @@ -438,9 +438,9 @@ func buildXdsRequestMirrorPolicies(mirrorDestinations []*ir.RouteDestination) [] } func buildXdsAddedHeaders(headersToAdd []ir.AddHeader) []*corev3.HeaderValueOption { - headerValueOptions := make([]*corev3.HeaderValueOption, len(headersToAdd)) + headerValueOptions := []*corev3.HeaderValueOption{} - for i, header := range headersToAdd { + for _, header := range headersToAdd { var appendAction corev3.HeaderValueOption_HeaderAppendAction if header.Append { @@ -448,18 +448,26 @@ func buildXdsAddedHeaders(headersToAdd []ir.AddHeader) []*corev3.HeaderValueOpti } else { appendAction = corev3.HeaderValueOption_OVERWRITE_IF_EXISTS_OR_ADD } - - headerValueOptions[i] = &corev3.HeaderValueOption{ - Header: &corev3.HeaderValue{ - Key: header.Name, - Value: header.Value, - }, - AppendAction: appendAction, - } - // Allow empty headers to be set, but don't add the config to do so unless necessary - if header.Value == "" { - headerValueOptions[i].KeepEmptyValue = true + if len(header.Value) == 0 { + headerValueOptions = append(headerValueOptions, &corev3.HeaderValueOption{ + Header: &corev3.HeaderValue{ + Key: header.Name, + }, + AppendAction: appendAction, + KeepEmptyValue: true, + }) + } else { + for _, val := range header.Value { + headerValueOptions = append(headerValueOptions, &corev3.HeaderValueOption{ + Header: &corev3.HeaderValue{ + Key: header.Name, + Value: val, + }, + AppendAction: appendAction, + KeepEmptyValue: val == "", + }) + } } } @@ -548,7 +556,7 @@ func buildRetryPolicy(route *ir.HTTPRoute) (*routev3.RetryPolicy, error) { } if rr.RetryOn != nil { - if rr.RetryOn.Triggers != nil && len(rr.RetryOn.Triggers) > 0 { + if len(rr.RetryOn.Triggers) > 0 { if ro, err := buildRetryOn(rr.RetryOn.Triggers); err == nil { rp.RetryOn = ro } else { @@ -556,7 +564,7 @@ func buildRetryPolicy(route *ir.HTTPRoute) (*routev3.RetryPolicy, error) { } } - if rr.RetryOn.HTTPStatusCodes != nil && len(rr.RetryOn.HTTPStatusCodes) > 0 { + if len(rr.RetryOn.HTTPStatusCodes) > 0 { rp.RetriableStatusCodes = buildRetryStatusCodes(rr.RetryOn.HTTPStatusCodes) } } diff --git a/internal/xds/translator/session_persistence.go b/internal/xds/translator/session_persistence.go new file mode 100644 index 00000000000..703e553ce47 --- /dev/null +++ b/internal/xds/translator/session_persistence.go @@ -0,0 +1,169 @@ +// 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" + "fmt" + "strings" + + corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" + routev3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" + statefulsessionv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/stateful_session/v3" + hcmv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" + cookiev3 "github.com/envoyproxy/go-control-plane/envoy/extensions/http/stateful_session/cookie/v3" + headerv3 "github.com/envoyproxy/go-control-plane/envoy/extensions/http/stateful_session/header/v3" + httpv3 "github.com/envoyproxy/go-control-plane/envoy/type/http/v3" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/durationpb" + + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" + "github.com/envoyproxy/gateway/internal/ir" + "github.com/envoyproxy/gateway/internal/xds/types" +) + +const ( + cookieConfigName = "envoy.http.stateful_session.cookie" + headerConfigName = "envoy.http.stateful_session.header" +) + +type sessionPersistence struct{} + +func init() { + registerHTTPFilter(&sessionPersistence{}) +} + +var _ httpFilter = &sessionPersistence{} + +// patchHCM patches the HttpConnectionManager with the filter. +// Note: this method may be called multiple times for the same filter, please +// make sure to avoid duplicate additions of the same filter. +func (s *sessionPersistence) patchHCM(mgr *hcmv3.HttpConnectionManager, irListener *ir.HTTPListener) 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 { + sp := route.SessionPersistence + if sp == nil { + continue + } + + if hcmContainsFilter(mgr, perRouteFilterName(egv1a1.EnvoyFilterSessionPersistence, route.Name)) { + continue + } + + var sessionCfg proto.Message + var configName string + switch { + case sp.Cookie != nil: + configName = cookieConfigName + sessionCfg = &cookiev3.CookieBasedSessionState{ + Cookie: &httpv3.Cookie{ + Name: sp.Cookie.Name, + Path: routePathToCookiePath(route.PathMatch), + Ttl: durationpb.New(sp.Cookie.TTL.Duration), + }, + } + case sp.Header != nil: + configName = headerConfigName + sessionCfg = &headerv3.HeaderBasedSessionState{ + Name: sp.Header.Name, + } + } + + sessionCfgAny, err := anypb.New(sessionCfg) + if err != nil { + return fmt.Errorf("failed to marshal %s config: %w", egv1a1.EnvoyFilterSessionPersistence.String(), err) + } + + cfg := &statefulsessionv3.StatefulSession{ + SessionState: &corev3.TypedExtensionConfig{ + Name: configName, + TypedConfig: sessionCfgAny, + }, + } + + cfgAny, err := anypb.New(cfg) + if err != nil { + return fmt.Errorf("failed to marshal %s config: %w", egv1a1.EnvoyFilterSessionPersistence.String(), err) + } + + mgr.HttpFilters = append(mgr.HttpFilters, &hcmv3.HttpFilter{ + Name: perRouteFilterName(egv1a1.EnvoyFilterSessionPersistence, route.Name), + Disabled: true, + ConfigType: &hcmv3.HttpFilter_TypedConfig{ + TypedConfig: cfgAny, + }, + }) + } + + return nil +} + +func routePathToCookiePath(path *ir.StringMatch) string { + if path == nil { + return "/" + } + switch { + case path.Exact != nil: + return *path.Exact + case path.Prefix != nil: + return *path.Prefix + case path.SafeRegex != nil: + return getLongestNonRegexPrefix(*path.SafeRegex) + } + + // Shouldn't reach here because the path should be either of the above three kinds. + return "/" +} + +// getLongestNonRegexPrefix takes a regex path and returns the longest non-regex prefix. +// > 3. For an xRoute using a path that is a regex, the Path should be set to the longest non-regex prefix +// (.e.g. if the path is /p1/p2/*/p3 and the request path was /p1/p2/foo/p3, then the cookie path would be /p1/p2). +// https://gateway-api.sigs.k8s.io/geps/gep-1619/#path +func getLongestNonRegexPrefix(path string) string { + parts := strings.Split(path, "/") + var longestNonRegexPrefix []string + for _, part := range parts { + if part == "*" || strings.Contains(part, "*") { + break + } + longestNonRegexPrefix = append(longestNonRegexPrefix, part) + } + + return strings.Join(longestNonRegexPrefix, "/") +} + +// patchRoute patches the provide Route with a filter's Route level configuration. +func (s *sessionPersistence) 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.SessionPersistence == nil { + return nil + } + + if err := enableFilterOnRoute(route, perRouteFilterName(egv1a1.EnvoyFilterSessionPersistence, route.Name)); err != nil { + return err + } + + return nil +} + +// patchResources adds all the other needed resources referenced by this +// filter to the resource version table. +func (s *sessionPersistence) patchResources(tCtx *types.ResourceVersionTable, routes []*ir.HTTPRoute) error { + return nil +} diff --git a/internal/xds/translator/testdata/in/xds-ir/accesslog-als-tcp.yaml b/internal/xds/translator/testdata/in/xds-ir/accesslog-als-tcp.yaml index 2d8f0c6aa48..4b437f443e8 100644 --- a/internal/xds/translator/testdata/in/xds-ir/accesslog-als-tcp.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/accesslog-als-tcp.yaml @@ -17,6 +17,27 @@ accesslog: port: 9000 protocol: GRPC weight: 1 + traffic: + backendConnection: + bufferLimit: 20971520 + circuitBreaker: + maxConnections: 2048 + healthCheck: + passive: + baseEjectionTime: 30s + consecutiveGatewayErrors: 4 + consecutive5XxErrors: 5 + consecutiveLocalOriginFailures: 5 + interval: 5s + maxEjectionPercent: 10 + splitExternalLocalOriginErrors: false + proxyProtocol: + version: V2 + tcpKeepalive: + probes: 7 + timeout: + tcp: + connectTimeout: 15s attributes: attr1: value1 attr2: value2 diff --git a/internal/xds/translator/testdata/in/xds-ir/backend-priority.yaml b/internal/xds/translator/testdata/in/xds-ir/backend-priority.yaml new file mode 100644 index 00000000000..b18671d7879 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/backend-priority.yaml @@ -0,0 +1,97 @@ +http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-1 + namespace: default + sectionName: http + name: default/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + envoyExtensions: + extProcs: + - authority: grpc-backend.envoy-gateway:8000 + destination: + name: envoyextensionpolicy/default/policy-for-http-route/0 + settings: + - addressType: IP + protocol: GRPC + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + name: policy-btls-grpc/envoy-gateway-ca + sni: grpc-backend + weight: 1 + - addressType: IP + endpoints: + - host: 8.8.8.8 + port: 9000 + priority: 1 + protocol: GRPC + weight: 1 + - addressType: IP + endpoints: + - host: 1.1.1.1 + port: 3001 + priority: 1 + protocol: GRPC + weight: 1 + - addressType: IP + endpoints: + - host: 2.2.2.2 + port: 3443 + priority: 1 + protocol: GRPC + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + name: policy-btls-backend-ip/envoy-gateway-ca + sni: ip-backend + weight: 1 + name: envoyextensionpolicy/default/policy-for-http-route/extproc/0 + hostname: www.foo.com + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0/match/0/www_foo_com + pathMatch: + distinct: false + name: "" + prefix: /foo + - destination: + name: httproute/default/httproute-2/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: www.bar.com + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-2 + namespace: default + name: httproute/default/httproute-2/rule/0/match/0/www_bar_com + pathMatch: + distinct: false + name: "" + prefix: /bar diff --git a/internal/xds/translator/testdata/in/xds-ir/ext-auth-backend.yaml b/internal/xds/translator/testdata/in/xds-ir/ext-auth-backend.yaml new file mode 100644 index 00000000000..4f93e2e7734 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/ext-auth-backend.yaml @@ -0,0 +1,123 @@ +http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: default/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - name: httproute/default/httproute-1/rule/0/match/0/www_foo_com + hostname: www.foo.com + isHTTP2: false + pathMatch: + distinct: false + name: "" + prefix: /foo1 + 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 + security: + extAuth: + name: securitypolicy/default/policy-for-http-route-1 + failOpen: false + grpc: + authority: primary.foo.com + destination: + name: securitypolicy/default/policy-for-http-route-1/default/grpc-backend + settings: + - addressType: FQDN + endpoints: + - host: primary.foo.com + port: 9000 + protocol: GRPC + weight: 1 + headersToExtAuth: + - header1 + - header2 + - name: httproute/default/httproute-1/rule/1/match/0/www_foo_com + hostname: www.foo.com + isHTTP2: false + pathMatch: + distinct: false + name: "" + prefix: /foo2 + backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-1/rule/1 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + security: + extAuth: + name: securitypolicy/default/policy-for-http-route-1 + failOpen: false + grpc: + authority: primary.foo.com + destination: + name: securitypolicy/default/policy-for-http-route-1/default/grpc-backend + settings: + - addressType: IP + endpoints: + - host: primary.foo.com + port: 3000 + protocol: GRPC + weight: 1 + headersToExtAuth: + - header1 + - header2 + - name: httproute/default/httproute-2/rule/0/match/0/www_bar_com + hostname: www.bar.com + isHTTP2: false + pathMatch: + distinct: false + name: "" + prefix: /bar + 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 + security: + extAuth: + name: securitypolicy/default/policy-for-gateway-1 + failOpen: true + http: + authority: primary.foo.com + destination: + name: securitypolicy/default/policy-for-gateway-1/envoy-gateway/http-backend + settings: + - addressType: FQDN + endpoints: + - host: primary.foo.com + port: 80 + protocol: HTTP + weight: 1 + headersToBackend: + - header1 + - header2 + path: /auth diff --git a/internal/xds/translator/testdata/in/xds-ir/ext-proc-with-traffic-settings.yaml b/internal/xds/translator/testdata/in/xds-ir/ext-proc-with-traffic-settings.yaml new file mode 100644 index 00000000000..136fd53ff6a --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/ext-proc-with-traffic-settings.yaml @@ -0,0 +1,124 @@ +http: +- address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-1 + namespace: default + sectionName: http + name: default/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + envoyExtensions: + extProcs: + - authority: grpc-backend.envoy-gateway:8000 + destination: + name: envoyextensionpolicy/default/policy-for-http-route/0 + settings: + - addressType: IP + protocol: GRPC + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + name: policy-btls-grpc/envoy-gateway-ca + sni: grpc-backend + weight: 1 + - addressType: IP + endpoints: + - host: 8.8.8.8 + port: 9000 + protocol: GRPC + weight: 1 + - addressType: IP + endpoints: + - host: 1.1.1.1 + port: 3001 + protocol: GRPC + weight: 1 + - addressType: IP + endpoints: + - host: 2.2.2.2 + port: 3443 + protocol: GRPC + tls: + caCertificate: + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + name: policy-btls-backend-ip/envoy-gateway-ca + sni: ip-backend + weight: 1 + name: envoyextensionpolicy/default/policy-for-http-route/extproc/0 + traffic: + backendConnection: + bufferLimit: 20971520 + circuitBreaker: + maxConnections: 2048 + healthCheck: + passive: + baseEjectionTime: 30s + consecutiveGatewayErrors: 4 + consecutive5XxErrors: 5 + consecutiveLocalOriginFailures: 5 + interval: 5s + maxEjectionPercent: 10 + splitExternalLocalOriginErrors: false + http2: + initialConnectionWindowSize: 131072 + initialStreamWindowSize: 2097152 + maxConcurrentStreams: 200 + resetStreamOnError: true + loadBalancer: + roundRobin: + slowStart: + window: 5s + proxyProtocol: + version: V2 + tcpKeepalive: + probes: 7 + timeout: + tcp: + connectTimeout: 15s + hostname: www.foo.com + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0/match/0/www_foo_com + pathMatch: + distinct: false + name: "" + prefix: /foo + - destination: + name: httproute/default/httproute-2/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: www.bar.com + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-2 + namespace: default + name: httproute/default/httproute-2/rule/0/match/0/www_bar_com + pathMatch: + distinct: false + name: "" + prefix: /bar 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 30ecd2da792..12f62f86414 100644 --- a/internal/xds/translator/testdata/in/xds-ir/health-check.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/health-check.yaml @@ -126,3 +126,21 @@ http: - endpoints: - host: "1.2.3.4" port: 50000 + - name: "fifth-route" + hostname: "*" + traffic: + healthCheck: + active: + timeout: "1s" + interval: "5s" + unhealthyThreshold: 3 + healthyThreshold: 3 + grpc: + service: my-service + destination: + name: "fifth-route-dest" + protocol: GRPC + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 diff --git a/internal/xds/translator/testdata/in/xds-ir/http-early-header-mutation.yaml b/internal/xds/translator/testdata/in/xds-ir/http-early-header-mutation.yaml new file mode 100644 index 00000000000..6301153cd1c --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/http-early-header-mutation.yaml @@ -0,0 +1,59 @@ +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: + - "*" + headers: + earlyAddRequestHeaders: + - name: "some-header" + value: + - "some-value1" + - "some-value2" + append: true + - name: "some-header-2" + value: + - "some-value" + append: true + - name: "some-header3" + value: + - "some-value" + append: false + - name: "some-header4" + value: + - "some-value" + append: false + - name: "empty-header" + value: + append: false + earlyRemoveRequestHeaders: + - "some-header5" + - "some-header6" + 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/http-route-request-headers.yaml b/internal/xds/translator/testdata/in/xds-ir/http-route-request-headers.yaml index c3dc4417dcc..fb45b8db724 100644 --- a/internal/xds/translator/testdata/in/xds-ir/http-route-request-headers.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/http-route-request-headers.yaml @@ -18,20 +18,30 @@ http: - host: "1.2.3.4" port: 50000 addRequestHeaders: + - name: "some-header-multi-value" + value: + - "some-value" + - "some-additional-value" + append: true - name: "some-header" - value: "some-value" + value: + - "some-value" append: true - name: "some-header-2" - value: "some-value" + value: + - "some-value" append: true - name: "some-header3" - value: "some-value" + value: + - "some-value" append: false - name: "some-header4" - value: "some-value" + value: + - "some-value" append: false - name: "empty-header" - value: "" + value: + - "" append: false removeRequestHeaders: - "some-header5" diff --git a/internal/xds/translator/testdata/in/xds-ir/http-route-response-add-headers.yaml b/internal/xds/translator/testdata/in/xds-ir/http-route-response-add-headers.yaml index e3114e2d252..3cfaf5e4945 100644 --- a/internal/xds/translator/testdata/in/xds-ir/http-route-response-add-headers.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/http-route-response-add-headers.yaml @@ -19,17 +19,22 @@ http: port: 50000 addResponseHeaders: - name: "some-header" - value: "some-value" + value: + - "some-value" append: true - name: "some-header-2" - value: "some-value" + value: + - "some-value" append: true - name: "some-header3" - value: "some-value" + value: + - "some-value" append: false - name: "some-header4" - value: "some-value" + value: + - "some-value" append: false - name: "empty-header" - value: "" + value: + - "" append: false diff --git a/internal/xds/translator/testdata/in/xds-ir/http-route-response-add-remove-headers.yaml b/internal/xds/translator/testdata/in/xds-ir/http-route-response-add-remove-headers.yaml index 0e59f8f124d..c97d927dff6 100644 --- a/internal/xds/translator/testdata/in/xds-ir/http-route-response-add-remove-headers.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/http-route-response-add-remove-headers.yaml @@ -19,19 +19,24 @@ http: port: 50000 addResponseHeaders: - name: "some-header" - value: "some-value" + value: + - "some-value" append: true - name: "some-header-2" - value: "some-value" + value: + - "some-value" append: true - name: "some-header3" - value: "some-value" + value: + - "some-value" append: false - name: "some-header4" - value: "some-value" + value: + - "some-value" append: false - name: "empty-header" - value: "" + value: + - "" append: false removeResponseHeaders: - "some-header5" diff --git a/internal/xds/translator/testdata/in/xds-ir/http-route-session-persistence.yaml b/internal/xds/translator/testdata/in/xds-ir/http-route-session-persistence.yaml new file mode 100644 index 00000000000..536c5ad50cb --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/http-route-session-persistence.yaml @@ -0,0 +1,66 @@ +http: +- name: "first-listener" + address: "0.0.0.0" + port: 10080 + hostnames: + - "*" + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + routes: + - name: "header-based-session-persistence-route" + hostname: "*" + pathMatch: + safeRegex: "/v1/.*" + sessionPersistence: + header: { + name: "session-header" + } + destination: + name: "regex-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 + - name: "cookie-based-session-persistence-route-regex" + hostname: "*" + pathMatch: + safeRegex: "/v1/.*/hoge" + sessionPersistence: + cookie: + name: "session-header" + ttl: "1h" + destination: + name: "regex-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 + - name: "cookie-based-session-persistence-route-prefix" + hostname: "*" + pathMatch: + prefix: "/v2/" + sessionPersistence: + cookie: + name: "session-header" + ttl: "1h" + destination: + name: "regex-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 + - name: "cookie-based-session-persistence-route-exact" + hostname: "*" + pathMatch: + exact: "/v3/user" + sessionPersistence: + cookie: + name: "session-cookie" + ttl: "1h" + destination: + name: "regex-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 diff --git a/internal/xds/translator/testdata/in/xds-ir/http-route-weighted-backend-with-filters.yaml b/internal/xds/translator/testdata/in/xds-ir/http-route-weighted-backend-with-filters.yaml index f8943d07f01..8745e9893bc 100644 --- a/internal/xds/translator/testdata/in/xds-ir/http-route-weighted-backend-with-filters.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/http-route-weighted-backend-with-filters.yaml @@ -19,7 +19,8 @@ http: addRequestHeaders: - append: false name: add-header-3 - value: some-value + value: + - some-value protocol: HTTP weight: 1 hostname: '*' @@ -37,10 +38,12 @@ http: addRequestHeaders: - append: true name: add-header-1 - value: some-value + value: + - some-value - append: true name: add-header-2 - value: some-value + value: + - some-value protocol: HTTP weight: 8 - addressType: IP diff --git a/internal/xds/translator/testdata/in/xds-ir/jsonpatch-add-op-empty-jsonpath.yaml b/internal/xds/translator/testdata/in/xds-ir/jsonpatch-add-op-empty-jsonpath.yaml new file mode 100644 index 00000000000..9c248772920 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/jsonpatch-add-op-empty-jsonpath.yaml @@ -0,0 +1,63 @@ +envoyPatchPolicies: +- status: + ancestors: + - ancestorRef: + group: "gateway.networking.k8s.io" + kind: "Gateway" + namespace: "default" + name: "foobar" + name: "first-policy" + namespace: "default" + jsonPatches: + - type: "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment" + name: second-listener + operation: + op: add + value: + clusterName: second-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 4.5.6.7 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: second-route-dest/backend/0 +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-with-jsonpath.yaml b/internal/xds/translator/testdata/in/xds-ir/jsonpatch-with-jsonpath.yaml new file mode 100644 index 00000000000..a02cad99d67 --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/jsonpatch-with-jsonpath.yaml @@ -0,0 +1,172 @@ +envoyPatchPolicies: +- status: + ancestors: + - ancestorRef: + group: "gateway.networking.k8s.io" + kind: "Gateway" + namespace: "default" + name: "foobar" + name: "first-policy" + namespace: "default" + jsonPatches: + - type: "type.googleapis.com/envoy.config.listener.v3.Listener" + name: first-listener + operation: + op: "add" + jsonPath: "$.filter_chains[0].filters[0].typed_config" + path: "/preserve_external_request_id" + value: true + - type: "type.googleapis.com/envoy.config.listener.v3.Listener" + name: "first-listener" + operation: + op: "add" + jsonPath: "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" + jsonPath: "virtual_hosts[0]" + path: "rate_limits" + value: + - actions: + - remote_address: {} + - type: "type.googleapis.com/envoy.config.route.v3.RouteConfiguration" + name: "first-listener" + operation: + op: "replace" + jsonPath: "..routes[?(@.name=='second-route')].route.upgrade_configs" + value: + - upgrade_type: CONNECT + connect_config: + {} + - type: "type.googleapis.com/envoy.config.cluster.v3.Cluster" + name: rate-limit-cluster + operation: + op: add + path: "" + value: + name: rate-limit-cluster + type: STRICT_DNS + connect_timeout: 10s + lb_policy: ROUND_ROBIN + http2_protocol_options: {} + load_assignment: + cluster_name: rate-limit-cluster + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: ratelimit.svc.cluster.local + port_value: 8081 + - type: "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment" + name: "first-route-dest" + operation: + op: "replace" + jsonPath: "..endpoints[*].load_balancing_weight" + value: "50" + - type: "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret" + name: "secret-1" + operation: + op: "replace" + jsonPath: "$.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 + jsonPath: "endpoints" + path: "/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" + 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 + - name: "second-route" + hostname: "*" + headerMatches: + - name: user + stringMatch: + exact: "james" + - name: country + stringMatch: + exact: "US" + destination: + name: "second-route-dest" + settings: + - endpoints: + - host: "4.5.6.7" + port: 60000 + diff --git a/internal/xds/translator/testdata/in/xds-ir/tracing.yaml b/internal/xds/translator/testdata/in/xds-ir/tracing.yaml index 0f3555524ff..2bd8aff1b7d 100644 --- a/internal/xds/translator/testdata/in/xds-ir/tracing.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/tracing.yaml @@ -25,6 +25,27 @@ tracing: - host: "otel-collector.default.svc.cluster.local" port: 4317 protocol: "GRPC" + traffic: + backendConnection: + bufferLimit: 20971520 + circuitBreaker: + maxConnections: 2048 + healthCheck: + passive: + baseEjectionTime: 30s + consecutiveGatewayErrors: 4 + consecutive5XxErrors: 5 + consecutiveLocalOriginFailures: 5 + interval: 5s + maxEjectionPercent: 10 + splitExternalLocalOriginErrors: false + proxyProtocol: + version: V2 + tcpKeepalive: + probes: 7 + timeout: + tcp: + connectTimeout: 15s provider: host: otel-collector.monitoring.svc.cluster.local port: 4317 diff --git a/internal/xds/translator/testdata/out/xds-ir/accesslog-als-tcp.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/accesslog-als-tcp.clusters.yaml index 9603f302b73..be515fc1afb 100755 --- a/internal/xds/translator/testdata/out/xds-ir/accesslog-als-tcp.clusters.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/accesslog-als-tcp.clusters.yaml @@ -1,9 +1,10 @@ - circuitBreakers: thresholds: - - maxRetries: 1024 + - maxConnections: 2048 + maxRetries: 1024 commonLbConfig: localityWeightedLbConfig: {} - connectTimeout: 10s + connectTimeout: 15s dnsLookupFamily: V4_ONLY edsClusterConfig: edsConfig: @@ -12,8 +13,24 @@ serviceName: accesslog/monitoring/envoy-als/port/9000 lbPolicy: LEAST_REQUEST name: accesslog/monitoring/envoy-als/port/9000 - outlierDetection: {} - perConnectionBufferLimitBytes: 32768 + outlierDetection: + baseEjectionTime: 30s + consecutive5xx: 5 + consecutiveGatewayFailure: 4 + consecutiveLocalOriginFailure: 5 + interval: 5s + maxEjectionPercent: 10 + perConnectionBufferLimitBytes: 20971520 + transportSocket: + name: envoy.transport_sockets.upstream_proxy_protocol + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.proxy_protocol.v3.ProxyProtocolUpstreamTransport + config: + version: V2 + transportSocket: + name: envoy.transport_sockets.raw_buffer + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.raw_buffer.v3.RawBuffer type: EDS typedExtensionProtocolOptions: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: @@ -22,3 +39,6 @@ http2ProtocolOptions: initialConnectionWindowSize: 1048576 initialStreamWindowSize: 65536 + upstreamConnectionOptions: + tcpKeepalive: + keepaliveProbes: 7 diff --git a/internal/xds/translator/testdata/out/xds-ir/backend-priority.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/backend-priority.clusters.yaml new file mode 100644 index 00000000000..b6f2821b650 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/backend-priority.clusters.yaml @@ -0,0 +1,99 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + 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 +- circuitBreakers: + thresholds: + - maxRetries: 1024 + 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 +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: envoyextensionpolicy/default/policy-for-http-route/0 + lbPolicy: LEAST_REQUEST + name: envoyextensionpolicy/default/policy-for-http-route/0 + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + transportSocketMatches: + - match: + name: envoyextensionpolicy/default/policy-for-http-route/0/tls/0 + name: envoyextensionpolicy/default/policy-for-http-route/0/tls/0 + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + commonTlsContext: + combinedValidationContext: + defaultValidationContext: + matchTypedSubjectAltNames: + - matcher: + exact: grpc-backend + sanType: DNS + validationContextSdsSecretConfig: + name: policy-btls-grpc/envoy-gateway-ca + sdsConfig: + ads: {} + resourceApiVersion: V3 + sni: grpc-backend + - match: + name: envoyextensionpolicy/default/policy-for-http-route/0/tls/3 + name: envoyextensionpolicy/default/policy-for-http-route/0/tls/3 + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + commonTlsContext: + combinedValidationContext: + defaultValidationContext: + matchTypedSubjectAltNames: + - matcher: + exact: ip-backend + sanType: DNS + validationContextSdsSecretConfig: + name: policy-btls-backend-ip/envoy-gateway-ca + sdsConfig: + ads: {} + resourceApiVersion: V3 + sni: ip-backend + type: EDS + typedExtensionProtocolOptions: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicitHttpConfig: + http2ProtocolOptions: + initialConnectionWindowSize: 1048576 + initialStreamWindowSize: 65536 diff --git a/internal/xds/translator/testdata/out/xds-ir/backend-priority.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/backend-priority.endpoints.yaml new file mode 100644 index 00000000000..30f113b0a73 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/backend-priority.endpoints.yaml @@ -0,0 +1,66 @@ +- clusterName: httproute/default/httproute-1/rule/0 + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 7.7.7.7 + portValue: 8080 + 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: 7.7.7.7 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: httproute/default/httproute-2/rule/0/backend/0 +- clusterName: envoyextensionpolicy/default/policy-for-http-route/0 + endpoints: + - loadBalancingWeight: 1 + locality: + region: envoyextensionpolicy/default/policy-for-http-route/0/backend/0 + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 8.8.8.8 + portValue: 9000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: envoyextensionpolicy/default/policy-for-http-route/0/backend/1 + priority: 1 + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.1.1.1 + portValue: 3001 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: envoyextensionpolicy/default/policy-for-http-route/0/backend/2 + priority: 1 + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 2.2.2.2 + portValue: 3443 + loadBalancingWeight: 1 + metadata: + filterMetadata: + envoy.transport_socket_match: + name: envoyextensionpolicy/default/policy-for-http-route/0/tls/3 + loadBalancingWeight: 1 + locality: + region: envoyextensionpolicy/default/policy-for-http-route/0/backend/3 + priority: 1 diff --git a/internal/xds/translator/testdata/out/xds-ir/backend-priority.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/backend-priority.listeners.yaml new file mode 100644 index 00000000000..7ed44e9e2bf --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/backend-priority.listeners.yaml @@ -0,0 +1,49 @@ +- 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_proc/envoyextensionpolicy/default/policy-for-http-route/extproc/0 + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor + grpcService: + envoyGrpc: + authority: grpc-backend.envoy-gateway:8000 + clusterName: envoyextensionpolicy/default/policy-for-http-route/0 + timeout: 10s + processingMode: + requestHeaderMode: SKIP + requestTrailerMode: SKIP + responseHeaderMode: SKIP + responseTrailerMode: SKIP + - 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: default/gateway-1/http + serverHeaderTransformation: PASS_THROUGH + statPrefix: http-10080 + useRemoteAddress: true + name: default/gateway-1/http + drainType: MODIFY_ONLY + name: default/gateway-1/http + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/backend-priority.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/backend-priority.routes.yaml new file mode 100644 index 00000000000..e5e50ccde27 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/backend-priority.routes.yaml @@ -0,0 +1,59 @@ +- ignorePortInHostMatching: true + name: default/gateway-1/http + virtualHosts: + - domains: + - www.foo.com + metadata: + filterMetadata: + envoy-gateway: + resources: + - kind: Gateway + name: gateway-1 + namespace: default + sectionName: http + name: default/gateway-1/http/www_foo_com + routes: + - match: + pathSeparatedPrefix: /foo + metadata: + filterMetadata: + envoy-gateway: + resources: + - kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0/match/0/www_foo_com + route: + cluster: httproute/default/httproute-1/rule/0 + upgradeConfigs: + - upgradeType: websocket + typedPerFilterConfig: + envoy.filters.http.ext_proc/envoyextensionpolicy/default/policy-for-http-route/extproc/0: + '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig + config: {} + - domains: + - www.bar.com + metadata: + filterMetadata: + envoy-gateway: + resources: + - kind: Gateway + name: gateway-1 + namespace: default + sectionName: http + name: default/gateway-1/http/www_bar_com + routes: + - match: + pathSeparatedPrefix: /bar + metadata: + filterMetadata: + envoy-gateway: + resources: + - kind: HTTPRoute + name: httproute-2 + namespace: default + name: httproute/default/httproute-2/rule/0/match/0/www_bar_com + route: + cluster: httproute/default/httproute-2/rule/0 + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/backend-priority.secrets.yaml b/internal/xds/translator/testdata/out/xds-ir/backend-priority.secrets.yaml new file mode 100644 index 00000000000..387926a79f3 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/backend-priority.secrets.yaml @@ -0,0 +1,8 @@ +- name: policy-btls-grpc/envoy-gateway-ca + validationContext: + trustedCa: + inlineBytes: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K +- name: policy-btls-backend-ip/envoy-gateway-ca + validationContext: + trustedCa: + inlineBytes: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-auth-backend.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-auth-backend.clusters.yaml new file mode 100644 index 00000000000..880f77a06f0 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/ext-auth-backend.clusters.yaml @@ -0,0 +1,112 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + 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 +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: httproute/default/httproute-1/rule/1 + lbPolicy: LEAST_REQUEST + name: httproute/default/httproute-1/rule/1 + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + 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 +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + dnsRefreshRate: 30s + lbPolicy: LEAST_REQUEST + loadAssignment: + clusterName: securitypolicy/default/policy-for-http-route-1/default/grpc-backend + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: primary.foo.com + portValue: 9000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: securitypolicy/default/policy-for-http-route-1/default/grpc-backend/backend/0 + name: securitypolicy/default/policy-for-http-route-1/default/grpc-backend + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + respectDnsTtl: true + type: STRICT_DNS + typedExtensionProtocolOptions: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicitHttpConfig: + http2ProtocolOptions: + initialConnectionWindowSize: 1048576 + initialStreamWindowSize: 65536 +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + dnsRefreshRate: 30s + lbPolicy: LEAST_REQUEST + loadAssignment: + clusterName: securitypolicy/default/policy-for-gateway-1/envoy-gateway/http-backend + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: primary.foo.com + portValue: 80 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: securitypolicy/default/policy-for-gateway-1/envoy-gateway/http-backend/backend/0 + name: securitypolicy/default/policy-for-gateway-1/envoy-gateway/http-backend + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + respectDnsTtl: true + type: STRICT_DNS diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-auth-backend.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-auth-backend.endpoints.yaml new file mode 100644 index 00000000000..bf9f0023789 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/ext-auth-backend.endpoints.yaml @@ -0,0 +1,36 @@ +- clusterName: httproute/default/httproute-1/rule/0 + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 7.7.7.7 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: httproute/default/httproute-1/rule/0/backend/0 +- clusterName: httproute/default/httproute-1/rule/1 + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 7.7.7.7 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: httproute/default/httproute-1/rule/1/backend/0 +- clusterName: httproute/default/httproute-2/rule/0 + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 7.7.7.7 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: httproute/default/httproute-2/rule/0/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-auth-backend.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-auth-backend.listeners.yaml new file mode 100644 index 00000000000..c60348a3b91 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/ext-auth-backend.listeners.yaml @@ -0,0 +1,70 @@ +- 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/securitypolicy/default/policy-for-http-route-1 + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz + allowedHeaders: + patterns: + - exact: header1 + ignoreCase: true + - exact: header2 + ignoreCase: true + grpcService: + envoyGrpc: + authority: primary.foo.com + clusterName: securitypolicy/default/policy-for-http-route-1/default/grpc-backend + timeout: 10s + transportApiVersion: V3 + - disabled: true + name: envoy.filters.http.ext_authz/securitypolicy/default/policy-for-gateway-1 + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz + failureModeAllow: true + httpService: + authorizationResponse: + allowedUpstreamHeaders: + patterns: + - exact: header1 + ignoreCase: true + - exact: header2 + ignoreCase: true + pathPrefix: /auth + serverUri: + cluster: securitypolicy/default/policy-for-gateway-1/envoy-gateway/http-backend + timeout: 10s + uri: http://primary.foo.com/auth + transportApiVersion: V3 + - 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: default/gateway-1/http + serverHeaderTransformation: PASS_THROUGH + statPrefix: http-10080 + useRemoteAddress: true + name: default/gateway-1/http + drainType: MODIFY_ONLY + name: default/gateway-1/http + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-auth-backend.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-auth-backend.routes.yaml new file mode 100644 index 00000000000..08edfc3c406 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/ext-auth-backend.routes.yaml @@ -0,0 +1,44 @@ +- ignorePortInHostMatching: true + name: default/gateway-1/http + virtualHosts: + - domains: + - www.foo.com + name: default/gateway-1/http/www_foo_com + routes: + - match: + pathSeparatedPrefix: /foo1 + name: httproute/default/httproute-1/rule/0/match/0/www_foo_com + route: + cluster: httproute/default/httproute-1/rule/0 + upgradeConfigs: + - upgradeType: websocket + typedPerFilterConfig: + envoy.filters.http.ext_authz/securitypolicy/default/policy-for-http-route-1: + '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig + config: {} + - match: + pathSeparatedPrefix: /foo2 + name: httproute/default/httproute-1/rule/1/match/0/www_foo_com + route: + cluster: httproute/default/httproute-1/rule/1 + upgradeConfigs: + - upgradeType: websocket + typedPerFilterConfig: + envoy.filters.http.ext_authz/securitypolicy/default/policy-for-http-route-1: + '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig + config: {} + - domains: + - www.bar.com + name: default/gateway-1/http/www_bar_com + routes: + - match: + pathSeparatedPrefix: /bar + name: httproute/default/httproute-2/rule/0/match/0/www_bar_com + route: + cluster: httproute/default/httproute-2/rule/0 + upgradeConfigs: + - upgradeType: websocket + typedPerFilterConfig: + envoy.filters.http.ext_authz/securitypolicy/default/policy-for-gateway-1: + '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig + config: {} diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-proc-with-traffic-settings.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-proc-with-traffic-settings.clusters.yaml new file mode 100644 index 00000000000..4e73328fa8e --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/ext-proc-with-traffic-settings.clusters.yaml @@ -0,0 +1,135 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + 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 +- circuitBreakers: + thresholds: + - maxRetries: 1024 + 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 +- circuitBreakers: + thresholds: + - maxConnections: 2048 + maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 15s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: envoyextensionpolicy/default/policy-for-http-route/0 + name: envoyextensionpolicy/default/policy-for-http-route/0 + outlierDetection: + baseEjectionTime: 30s + consecutive5xx: 5 + consecutiveGatewayFailure: 4 + consecutiveLocalOriginFailure: 5 + interval: 5s + maxEjectionPercent: 10 + perConnectionBufferLimitBytes: 20971520 + roundRobinLbConfig: + slowStartConfig: + slowStartWindow: 5s + transportSocket: + name: envoy.transport_sockets.upstream_proxy_protocol + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.proxy_protocol.v3.ProxyProtocolUpstreamTransport + config: + version: V2 + transportSocket: + name: envoy.transport_sockets.raw_buffer + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.raw_buffer.v3.RawBuffer + transportSocketMatches: + - match: + name: envoyextensionpolicy/default/policy-for-http-route/0/tls/0 + name: envoyextensionpolicy/default/policy-for-http-route/0/tls/0 + transportSocket: + name: envoy.transport_sockets.upstream_proxy_protocol + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.proxy_protocol.v3.ProxyProtocolUpstreamTransport + config: + version: V2 + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + commonTlsContext: + combinedValidationContext: + defaultValidationContext: + matchTypedSubjectAltNames: + - matcher: + exact: grpc-backend + sanType: DNS + validationContextSdsSecretConfig: + name: policy-btls-grpc/envoy-gateway-ca + sdsConfig: + ads: {} + resourceApiVersion: V3 + sni: grpc-backend + - match: + name: envoyextensionpolicy/default/policy-for-http-route/0/tls/3 + name: envoyextensionpolicy/default/policy-for-http-route/0/tls/3 + transportSocket: + name: envoy.transport_sockets.upstream_proxy_protocol + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.proxy_protocol.v3.ProxyProtocolUpstreamTransport + config: + version: V2 + transportSocket: + name: envoy.transport_sockets.tls + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + commonTlsContext: + combinedValidationContext: + defaultValidationContext: + matchTypedSubjectAltNames: + - matcher: + exact: ip-backend + sanType: DNS + validationContextSdsSecretConfig: + name: policy-btls-backend-ip/envoy-gateway-ca + sdsConfig: + ads: {} + resourceApiVersion: V3 + sni: ip-backend + type: EDS + typedExtensionProtocolOptions: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicitHttpConfig: + http2ProtocolOptions: + initialConnectionWindowSize: 2097152 + initialStreamWindowSize: 131072 + maxConcurrentStreams: 200 + overrideStreamErrorOnInvalidHttpMessage: true + upstreamConnectionOptions: + tcpKeepalive: + keepaliveProbes: 7 diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-proc-with-traffic-settings.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-proc-with-traffic-settings.endpoints.yaml new file mode 100644 index 00000000000..a3d4fd4dc11 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/ext-proc-with-traffic-settings.endpoints.yaml @@ -0,0 +1,63 @@ +- clusterName: httproute/default/httproute-1/rule/0 + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 7.7.7.7 + portValue: 8080 + 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: 7.7.7.7 + portValue: 8080 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: httproute/default/httproute-2/rule/0/backend/0 +- clusterName: envoyextensionpolicy/default/policy-for-http-route/0 + endpoints: + - loadBalancingWeight: 1 + locality: + region: envoyextensionpolicy/default/policy-for-http-route/0/backend/0 + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 8.8.8.8 + portValue: 9000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: envoyextensionpolicy/default/policy-for-http-route/0/backend/1 + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.1.1.1 + portValue: 3001 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: envoyextensionpolicy/default/policy-for-http-route/0/backend/2 + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 2.2.2.2 + portValue: 3443 + loadBalancingWeight: 1 + metadata: + filterMetadata: + envoy.transport_socket_match: + name: envoyextensionpolicy/default/policy-for-http-route/0/tls/3 + loadBalancingWeight: 1 + locality: + region: envoyextensionpolicy/default/policy-for-http-route/0/backend/3 diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-proc-with-traffic-settings.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-proc-with-traffic-settings.listeners.yaml new file mode 100644 index 00000000000..7ed44e9e2bf --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/ext-proc-with-traffic-settings.listeners.yaml @@ -0,0 +1,49 @@ +- 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_proc/envoyextensionpolicy/default/policy-for-http-route/extproc/0 + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor + grpcService: + envoyGrpc: + authority: grpc-backend.envoy-gateway:8000 + clusterName: envoyextensionpolicy/default/policy-for-http-route/0 + timeout: 10s + processingMode: + requestHeaderMode: SKIP + requestTrailerMode: SKIP + responseHeaderMode: SKIP + responseTrailerMode: SKIP + - 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: default/gateway-1/http + serverHeaderTransformation: PASS_THROUGH + statPrefix: http-10080 + useRemoteAddress: true + name: default/gateway-1/http + drainType: MODIFY_ONLY + name: default/gateway-1/http + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-proc-with-traffic-settings.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-proc-with-traffic-settings.routes.yaml new file mode 100644 index 00000000000..e5e50ccde27 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/ext-proc-with-traffic-settings.routes.yaml @@ -0,0 +1,59 @@ +- ignorePortInHostMatching: true + name: default/gateway-1/http + virtualHosts: + - domains: + - www.foo.com + metadata: + filterMetadata: + envoy-gateway: + resources: + - kind: Gateway + name: gateway-1 + namespace: default + sectionName: http + name: default/gateway-1/http/www_foo_com + routes: + - match: + pathSeparatedPrefix: /foo + metadata: + filterMetadata: + envoy-gateway: + resources: + - kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0/match/0/www_foo_com + route: + cluster: httproute/default/httproute-1/rule/0 + upgradeConfigs: + - upgradeType: websocket + typedPerFilterConfig: + envoy.filters.http.ext_proc/envoyextensionpolicy/default/policy-for-http-route/extproc/0: + '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig + config: {} + - domains: + - www.bar.com + metadata: + filterMetadata: + envoy-gateway: + resources: + - kind: Gateway + name: gateway-1 + namespace: default + sectionName: http + name: default/gateway-1/http/www_bar_com + routes: + - match: + pathSeparatedPrefix: /bar + metadata: + filterMetadata: + envoy-gateway: + resources: + - kind: HTTPRoute + name: httproute-2 + namespace: default + name: httproute/default/httproute-2/rule/0/match/0/www_bar_com + route: + cluster: httproute/default/httproute-2/rule/0 + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-proc-with-traffic-settings.secrets.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-proc-with-traffic-settings.secrets.yaml new file mode 100644 index 00000000000..387926a79f3 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/ext-proc-with-traffic-settings.secrets.yaml @@ -0,0 +1,8 @@ +- name: policy-btls-grpc/envoy-gateway-ca + validationContext: + trustedCa: + inlineBytes: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K +- name: policy-btls-backend-ip/envoy-gateway-ca + validationContext: + trustedCa: + inlineBytes: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K 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 b789b876c3c..485139eb2c8 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 @@ -139,3 +139,27 @@ splitExternalLocalOriginErrors: true perConnectionBufferLimitBytes: 32768 type: EDS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: fifth-route-dest + healthChecks: + - grpcHealthCheck: + serviceName: my-service + healthyThreshold: 3 + interval: 5s + timeout: 1s + unhealthyThreshold: 3 + lbPolicy: LEAST_REQUEST + name: fifth-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/health-check.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/health-check.endpoints.yaml index f185af17da7..b93d9b43bde 100644 --- a/internal/xds/translator/testdata/out/xds-ir/health-check.endpoints.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/health-check.endpoints.yaml @@ -46,3 +46,15 @@ loadBalancingWeight: 1 locality: region: fourth-route-dest/backend/0 +- clusterName: fifth-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: fifth-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/health-check.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/health-check.routes.yaml index de4249178e4..2f5c4977b24 100644 --- a/internal/xds/translator/testdata/out/xds-ir/health-check.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/health-check.routes.yaml @@ -33,3 +33,10 @@ cluster: fourth-route-dest upgradeConfigs: - upgradeType: websocket + - match: + prefix: / + name: fifth-route + route: + cluster: fifth-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-early-header-mutation.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/http-early-header-mutation.clusters.yaml new file mode 100644 index 00000000000..22e6727066a --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-early-header-mutation.clusters.yaml @@ -0,0 +1,44 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + 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 +- circuitBreakers: + thresholds: + - maxRetries: 1024 + 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 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-early-header-mutation.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/http-early-header-mutation.endpoints.yaml new file mode 100644 index 00000000000..28a57caf3b5 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-early-header-mutation.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/http-early-header-mutation.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-early-header-mutation.listeners.yaml new file mode 100644 index 00000000000..69c2612a5f8 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-early-header-mutation.listeners.yaml @@ -0,0 +1,108 @@ +- 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-10080 + useRemoteAddress: true + name: first-listener + drainType: MODIFY_ONLY + 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 + earlyHeaderMutationExtensions: + - name: envoy.http.early_header_mutation.header_mutation + typedConfig: + '@type': type.googleapis.com/envoy.extensions.http.early_header_mutation.header_mutation.v3.HeaderMutation + mutations: + - append: + header: + key: some-header + value: some-value1 + - append: + header: + key: some-header + value: some-value2 + - append: + header: + key: some-header-2 + value: some-value + - append: + appendAction: OVERWRITE_IF_EXISTS_OR_ADD + header: + key: some-header3 + value: some-value + - append: + appendAction: OVERWRITE_IF_EXISTS_OR_ADD + header: + key: some-header4 + value: some-value + - append: + appendAction: OVERWRITE_IF_EXISTS_OR_ADD + header: + key: empty-header + keepEmptyValue: true + - remove: some-header5 + - remove: some-header6 + 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: second-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: http-10081 + useRemoteAddress: true + name: second-listener + drainType: MODIFY_ONLY + name: second-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-early-header-mutation.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-early-header-mutation.routes.yaml new file mode 100644 index 00000000000..ff93cfff360 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-early-header-mutation.routes.yaml @@ -0,0 +1,28 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + prefix: / + name: first-route + route: + cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket +- ignorePortInHostMatching: true + name: second-listener + virtualHosts: + - domains: + - '*' + name: second-listener/* + routes: + - match: + prefix: / + name: second-route + route: + cluster: second-route-dest + 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 f91a70cb2ee..1f2c6be4057 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,6 +9,12 @@ prefix: / name: request-header-route requestHeadersToAdd: + - header: + key: some-header-multi-value + value: some-value + - header: + key: some-header-multi-value + value: some-additional-value - header: key: some-header value: some-value diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-session-persistence.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-session-persistence.clusters.yaml new file mode 100644 index 00000000000..0f75e67e278 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-session-persistence.clusters.yaml @@ -0,0 +1,17 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: regex-route-dest + lbPolicy: LEAST_REQUEST + name: regex-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-session-persistence.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-session-persistence.endpoints.yaml new file mode 100644 index 00000000000..b36ee450059 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-session-persistence.endpoints.yaml @@ -0,0 +1,12 @@ +- clusterName: regex-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: regex-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-session-persistence.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-session-persistence.listeners.yaml new file mode 100644 index 00000000000..f29e11a27a4 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-session-persistence.listeners.yaml @@ -0,0 +1,80 @@ +- 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.stateful_session/header-based-session-persistence-route + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.stateful_session.v3.StatefulSession + sessionState: + name: envoy.http.stateful_session.header + typedConfig: + '@type': type.googleapis.com/envoy.extensions.http.stateful_session.header.v3.HeaderBasedSessionState + name: session-header + - disabled: true + name: envoy.filters.http.stateful_session/cookie-based-session-persistence-route-regex + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.stateful_session.v3.StatefulSession + sessionState: + name: envoy.http.stateful_session.cookie + typedConfig: + '@type': type.googleapis.com/envoy.extensions.http.stateful_session.cookie.v3.CookieBasedSessionState + cookie: + name: session-header + path: /v1 + ttl: 3600s + - disabled: true + name: envoy.filters.http.stateful_session/cookie-based-session-persistence-route-prefix + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.stateful_session.v3.StatefulSession + sessionState: + name: envoy.http.stateful_session.cookie + typedConfig: + '@type': type.googleapis.com/envoy.extensions.http.stateful_session.cookie.v3.CookieBasedSessionState + cookie: + name: session-header + path: /v2/ + ttl: 3600s + - disabled: true + name: envoy.filters.http.stateful_session/cookie-based-session-persistence-route-exact + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.stateful_session.v3.StatefulSession + sessionState: + name: envoy.http.stateful_session.cookie + typedConfig: + '@type': type.googleapis.com/envoy.extensions.http.stateful_session.cookie.v3.CookieBasedSessionState + cookie: + name: session-cookie + path: /v3/user + ttl: 3600s + - 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-10080 + useRemoteAddress: true + name: first-listener + drainType: MODIFY_ONLY + name: first-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-session-persistence.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-session-persistence.routes.yaml new file mode 100644 index 00000000000..c5450601be4 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-session-persistence.routes.yaml @@ -0,0 +1,53 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + routes: + - match: + safeRegex: + regex: /v1/.* + name: header-based-session-persistence-route + route: + cluster: regex-route-dest + upgradeConfigs: + - upgradeType: websocket + typedPerFilterConfig: + envoy.filters.http.stateful_session/header-based-session-persistence-route: + '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig + config: {} + - match: + safeRegex: + regex: /v1/.*/hoge + name: cookie-based-session-persistence-route-regex + route: + cluster: regex-route-dest + upgradeConfigs: + - upgradeType: websocket + typedPerFilterConfig: + envoy.filters.http.stateful_session/cookie-based-session-persistence-route-regex: + '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig + config: {} + - match: + pathSeparatedPrefix: /v2 + name: cookie-based-session-persistence-route-prefix + route: + cluster: regex-route-dest + upgradeConfigs: + - upgradeType: websocket + typedPerFilterConfig: + envoy.filters.http.stateful_session/cookie-based-session-persistence-route-prefix: + '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig + config: {} + - match: + path: /v3/user + name: cookie-based-session-persistence-route-exact + route: + cluster: regex-route-dest + upgradeConfigs: + - upgradeType: websocket + typedPerFilterConfig: + envoy.filters.http.stateful_session/cookie-based-session-persistence-route-exact: + '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig + config: {} diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-empty-jsonpath.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-empty-jsonpath.clusters.yaml new file mode 100644 index 00000000000..d53a7a1b2ce --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-empty-jsonpath.clusters.yaml @@ -0,0 +1,17 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + 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-empty-jsonpath.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-empty-jsonpath.endpoints.yaml new file mode 100644 index 00000000000..9a6f5a46c91 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-empty-jsonpath.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: 4.5.6.7 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: second-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-empty-jsonpath.envoypatchpolicies.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-empty-jsonpath.envoypatchpolicies.yaml new file mode 100644 index 00000000000..9508dd3e7b3 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-empty-jsonpath.envoypatchpolicies.yaml @@ -0,0 +1,16 @@ +- name: first-policy + namespace: default + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: foobar + namespace: default + conditions: + - lastTransitionTime: null + message: Patches have been successfully applied. + reason: Programmed + status: "True" + type: Programmed + controllerName: "" diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-empty-jsonpath.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-empty-jsonpath.listeners.yaml new file mode 100644 index 00000000000..51c022c26f3 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-empty-jsonpath.listeners.yaml @@ -0,0 +1,52 @@ +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10080 + drainType: MODIFY_ONLY + 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-10080 + useRemoteAddress: true + name: first-listener + 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-empty-jsonpath.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-empty-jsonpath.routes.yaml new file mode 100644 index 00000000000..4a412b3576a --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-empty-jsonpath.routes.yaml @@ -0,0 +1,18 @@ +- 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 + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-empty-jsonpath.secrets.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-empty-jsonpath.secrets.yaml new file mode 100644 index 00000000000..ad88ffe43cd --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-empty-jsonpath.secrets.yaml @@ -0,0 +1,12 @@ +- name: secret-1 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= +- name: secret-2 + tlsCertificate: + certificateChain: + inlineBytes: Y2VydC1kYXRh + privateKey: + inlineBytes: a2V5LWRhdGE= diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-with-jsonpath.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-with-jsonpath.clusters.yaml new file mode 100644 index 00000000000..b3842b6e52e --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-with-jsonpath.clusters.yaml @@ -0,0 +1,47 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + 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 +- circuitBreakers: + thresholds: + - maxRetries: 1024 + 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 +- connectTimeout: 10s + http2ProtocolOptions: {} + loadAssignment: + clusterName: rate-limit-cluster + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: ratelimit.svc.cluster.local + portValue: 8081 + name: rate-limit-cluster + type: STRICT_DNS diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-with-jsonpath.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-with-jsonpath.endpoints.yaml new file mode 100644 index 00000000000..131cd47c730 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-with-jsonpath.endpoints.yaml @@ -0,0 +1,32 @@ +- clusterName: first-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 50 + locality: + region: first-route-dest/backend/0 + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 50 +- clusterName: second-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 4.5.6.7 + portValue: 60000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: second-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-with-jsonpath.envoypatchpolicies.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-with-jsonpath.envoypatchpolicies.yaml new file mode 100644 index 00000000000..9508dd3e7b3 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-with-jsonpath.envoypatchpolicies.yaml @@ -0,0 +1,16 @@ +- name: first-policy + namespace: default + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: foobar + namespace: default + conditions: + - lastTransitionTime: null + message: Patches have been successfully applied. + reason: Programmed + status: "True" + type: Programmed + controllerName: "" diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-with-jsonpath.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-with-jsonpath.listeners.yaml new file mode 100644 index 00000000000..08b5d410df5 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-with-jsonpath.listeners.yaml @@ -0,0 +1,64 @@ +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10080 + drainType: MODIFY_ONLY + 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 + preserveExternalRequestId: true + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: https-10080 + useRemoteAddress: true + name: first-listener + 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-with-jsonpath.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-with-jsonpath.routes.yaml new file mode 100644 index 00000000000..a7273c7a1b8 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-with-jsonpath.routes.yaml @@ -0,0 +1,36 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - '*' + name: first-listener/* + rateLimits: + - actions: + - remoteAddress: {} + routes: + - match: + headers: + - name: user + stringMatch: + exact: jason + prefix: / + name: first-route + route: + cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket + - match: + headers: + - name: user + stringMatch: + exact: james + - name: country + stringMatch: + exact: US + prefix: / + name: second-route + route: + cluster: second-route-dest + upgradeConfigs: + - connectConfig: {} + upgradeType: CONNECT diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-with-jsonpath.secrets.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-with-jsonpath.secrets.yaml new file mode 100644 index 00000000000..d1c4b32fd5f --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-with-jsonpath.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/tracing.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/tracing.clusters.yaml index dce48b2c083..4d419611516 100644 --- a/internal/xds/translator/testdata/out/xds-ir/tracing.clusters.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/tracing.clusters.yaml @@ -17,10 +17,11 @@ type: EDS - circuitBreakers: thresholds: - - maxRetries: 1024 + - maxConnections: 2048 + maxRetries: 1024 commonLbConfig: localityWeightedLbConfig: {} - connectTimeout: 10s + connectTimeout: 15s dnsLookupFamily: V4_ONLY dnsRefreshRate: 30s lbPolicy: LEAST_REQUEST @@ -38,9 +39,25 @@ locality: region: tracing-0/backend/0 name: tracing-0 - outlierDetection: {} - perConnectionBufferLimitBytes: 32768 + outlierDetection: + baseEjectionTime: 30s + consecutive5xx: 5 + consecutiveGatewayFailure: 4 + consecutiveLocalOriginFailure: 5 + interval: 5s + maxEjectionPercent: 10 + perConnectionBufferLimitBytes: 20971520 respectDnsTtl: true + transportSocket: + name: envoy.transport_sockets.upstream_proxy_protocol + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.proxy_protocol.v3.ProxyProtocolUpstreamTransport + config: + version: V2 + transportSocket: + name: envoy.transport_sockets.raw_buffer + typedConfig: + '@type': type.googleapis.com/envoy.extensions.transport_sockets.raw_buffer.v3.RawBuffer type: STRICT_DNS typedExtensionProtocolOptions: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: @@ -49,3 +66,6 @@ http2ProtocolOptions: initialConnectionWindowSize: 1048576 initialStreamWindowSize: 65536 + upstreamConnectionOptions: + tcpKeepalive: + keepaliveProbes: 7 diff --git a/internal/xds/translator/tracing.go b/internal/xds/translator/tracing.go index b2a52ec6a18..ad9a3ecc0e1 100644 --- a/internal/xds/translator/tracing.go +++ b/internal/xds/translator/tracing.go @@ -160,12 +160,26 @@ func processClusterForTracing(tCtx *types.ResourceVersionTable, tracing *ir.Trac return nil } + traffic := tracing.Traffic + // Make sure that there are safe defaults for the traffic + if traffic == nil { + traffic = &ir.TrafficFeatures{} + } if err := addXdsCluster(tCtx, &xdsClusterArgs{ - name: tracing.Destination.Name, - settings: tracing.Destination.Settings, - tSocket: nil, - endpointType: EndpointTypeDNS, - metrics: metrics, + name: tracing.Destination.Name, + settings: tracing.Destination.Settings, + tSocket: nil, + endpointType: EndpointTypeDNS, + metrics: metrics, + loadBalancer: traffic.LoadBalancer, + proxyProtocol: traffic.ProxyProtocol, + circuitBreaker: traffic.CircuitBreaker, + healthCheck: traffic.HealthCheck, + timeout: traffic.Timeout, + tcpkeepalive: traffic.TCPKeepalive, + backendConnection: traffic.BackendConnection, + dns: traffic.DNS, + http2Settings: traffic.HTTP2, }); 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 44d6d127bca..08ab0d24b3b 100644 --- a/internal/xds/translator/translator_test.go +++ b/internal/xds/translator/translator_test.go @@ -55,6 +55,12 @@ func TestTranslateXds(t *testing.T) { "jsonpatch": { requireEnvoyPatchPolicies: true, }, + "jsonpatch-with-jsonpath": { + requireEnvoyPatchPolicies: true, + }, + "jsonpatch-add-op-empty-jsonpath": { + requireEnvoyPatchPolicies: true, + }, "jsonpatch-missing-resource": { requireEnvoyPatchPolicies: true, }, @@ -103,7 +109,6 @@ func TestTranslateXds(t *testing.T) { require.NoError(t, err) for _, inputFile := range inputFiles { - inputFile := inputFile inputFileName := testName(inputFile) t.Run(inputFileName, func(t *testing.T) { cfg, ok := testConfigs[inputFileName] @@ -127,10 +132,9 @@ func TestTranslateXds(t *testing.T) { }, FilterOrder: x.FilterOrder, } - tCtx, err := tr.Translate(x) if !strings.HasSuffix(inputFileName, "partial-invalid") && len(cfg.errMsg) == 0 { - t.Logf(inputFileName) + t.Log(inputFileName) require.NoError(t, err) } else if len(cfg.errMsg) > 0 { require.Error(t, err) @@ -187,7 +191,6 @@ func TestTranslateRateLimitConfig(t *testing.T) { require.NoError(t, err) for _, inputFile := range inputFiles { - inputFile := inputFile inputFileName := testName(inputFile) t.Run(inputFileName, func(t *testing.T) { in := requireXdsIRListenerFromInputTestData(t, inputFile) @@ -217,7 +220,6 @@ func TestTranslateXdsWithExtension(t *testing.T) { require.NoError(t, err) for _, inputFile := range inputFiles { - inputFile := inputFile inputFileName := testName(inputFile) t.Run(inputFileName, func(t *testing.T) { cfg, ok := testConfigs[inputFileName] diff --git a/internal/xds/translator/utils.go b/internal/xds/translator/utils.go index 10148150865..23d455edd9c 100644 --- a/internal/xds/translator/utils.go +++ b/internal/xds/translator/utils.go @@ -129,13 +129,17 @@ func hcmContainsFilter(mgr *hcmv3.HttpConnectionManager, filterName string) bool return false } -func createExtServiceXDSCluster(rd *ir.RouteDestination, tCtx *types.ResourceVersionTable) error { +func createExtServiceXDSCluster(rd *ir.RouteDestination, traffic *ir.TrafficFeatures, tCtx *types.ResourceVersionTable) error { var ( endpointType EndpointType tSocket *corev3.TransportSocket err error ) + // Make sure that there are safe defaults for the traffic + if traffic == nil { + traffic = &ir.TrafficFeatures{} + } // Get the address type from the first setting. // This is safe because no mixed address types in the settings. addrTypeState := rd.Settings[0].AddressType @@ -144,12 +148,20 @@ func createExtServiceXDSCluster(rd *ir.RouteDestination, tCtx *types.ResourceVer } else { endpointType = EndpointTypeStatic } - if err = addXdsCluster(tCtx, &xdsClusterArgs{ - name: rd.Name, - settings: rd.Settings, - tSocket: tSocket, - endpointType: endpointType, + name: rd.Name, + settings: rd.Settings, + tSocket: tSocket, + loadBalancer: traffic.LoadBalancer, + proxyProtocol: traffic.ProxyProtocol, + circuitBreaker: traffic.CircuitBreaker, + healthCheck: traffic.HealthCheck, + timeout: traffic.Timeout, + tcpkeepalive: traffic.TCPKeepalive, + backendConnection: traffic.BackendConnection, + endpointType: endpointType, + dns: traffic.DNS, + http2Settings: traffic.HTTP2, }); err != nil && !errors.Is(err, ErrXdsClusterExists) { return err } diff --git a/internal/xds/types/resourceversiontable_test.go b/internal/xds/types/resourceversiontable_test.go index 8da1c0cc7ca..5fe96253bc8 100644 --- a/internal/xds/types/resourceversiontable_test.go +++ b/internal/xds/types/resourceversiontable_test.go @@ -71,7 +71,6 @@ func TestDeepCopy(t *testing.T) { }, } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { if tc.out == nil { require.Nil(t, tc.in.DeepCopy()) @@ -531,7 +530,6 @@ func TestAddOrReplaceXdsResource(t *testing.T) { } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { err := tc.tableIn.AddOrReplaceXdsResource(tc.typeIn, tc.resourceIn, tc.funcIn) require.NoError(t, err) @@ -887,7 +885,6 @@ func TestInvalidAddXdsResource(t *testing.T) { }, } for _, tc := range testCases { - tc := tc t.Run(tc.name, func(t *testing.T) { err := tc.tableIn.AddOrReplaceXdsResource(tc.typeIn, tc.resourceIn, tc.funcIn) require.Error(t, err) diff --git a/site/content/en/docs/boilerplates/prerequisites.md b/site/content/en/docs/boilerplates/prerequisites.md new file mode 100644 index 00000000000..064238e4d13 --- /dev/null +++ b/site/content/en/docs/boilerplates/prerequisites.md @@ -0,0 +1,24 @@ +--- +--- + +Follow the steps from the [Quickstart](../tasks/quickstart) task to install Envoy Gateway and the example manifest. +Before proceeding, you should be able to query the example backend using HTTP. + +Verify the Gateway status: + +{{< tabpane text=true >}} +{{% tab header="kubectl" %}} + +```shell +kubectl get gateway/eg -o yaml +``` + +{{% /tab %}} +{{% tab header="egctl (experimental)" %}} + +```shell +egctl x status gateway -v +``` + +{{% /tab %}} +{{< /tabpane >}} diff --git a/site/content/en/docs/concepts/concepts_overview.md b/site/content/en/docs/concepts/concepts_overview.md index 31838b520f2..9af9a3fff10 100644 --- a/site/content/en/docs/concepts/concepts_overview.md +++ b/site/content/en/docs/concepts/concepts_overview.md @@ -10,13 +10,12 @@ There are several resources that play a part in enabling you to meet your Kubern There are several resources that play a part in enabling you to meet your Kubernetes ingress traffic handling needs. This page provides a brief overview of the resources you’ll be working with. -# Overview - -## Kubernetes Gateway API Resources +### Kubernetes Gateway API Resources - **GatewayClass:** Defines a class of Gateways with common configuration. - **Gateway:** Specifies how traffic can enter the cluster. - **Routes:** **HTTPRoute, GRPCRoute, TLSRoute, TCPRoute, UDPRoute:** Define routing rules for different types of traffic. -## Envoy Gateway (EG) API Resources + +### Envoy Gateway (EG) API Resources - **EnvoyProxy:** Represents the deployment and configuration of the Envoy proxy within a Kubernetes cluster, managing its lifecycle and settings. - **EnvoyPatchPolicy, ClientTrafficPolicy, SecurityPolicy, BackendTrafficPolicy, EnvoyExtensionPolicy, BackendTLSPolicy:** Additional policies and configurations specific to Envoy Gateway. - **Backend:** A resource that makes routing to cluster-external backends easier and makes access to external processes via Unix Domain Sockets possible. diff --git a/site/content/en/docs/install/install-yaml.md b/site/content/en/docs/install/install-yaml.md index e675f15fbec..c0a8d1caa72 100644 --- a/site/content/en/docs/install/install-yaml.md +++ b/site/content/en/docs/install/install-yaml.md @@ -13,7 +13,7 @@ installation, it is recommended that you use helm. Envoy Gateway is designed to run in Kubernetes for production. The most essential requirements are: -* Kubernetes 1.25 or later +* Kubernetes 1.27 or later * The `kubectl` command-line tool {{% alert title="Compatibility Matrix" color="warning" %}} @@ -37,3 +37,31 @@ Refer to the [Developer Guide](../../contributions/develop) to learn more. 2. Next Steps Envoy Gateway should now be successfully installed and running, but in order to experience more abilities of Envoy Gateway, you can refer to [Tasks](/latest/tasks). + +## Upgrading from v1.0 + +Due to breaking changes in Gateway API v1.1, some manual migration steps are required to upgrade Envoy Gateway to v1.1. + +1. Delete `BackendTLSPolicy` CRD (and resources): + +```shell +kubectl delete crd backendtlspolicies.gateway.networking.k8s.io +``` + +2. Update Gateway-API and Envoy Gateway CRDs: + +```shell +helm pull oci://docker.io/envoyproxy/gateway-helm --version {{< yaml-version >}} --untar +kubectl apply --force-conflicts --server-side -f ./gateway-helm/crds/gatewayapi-crds.yaml +kubectl apply --force-conflicts --server-side -f ./gateway-helm/crds/generated +``` + +3. Update your `BackendTLSPolicy` and `GRPCRoute` resources according to Gateway-API [v1.1 Upgrade Notes](https://gateway-api.sigs.k8s.io/guides/#v11-upgrade-notes) + +4. Update your Envoy Gateway xPolicy resources: remove the namespace section from targetRef. + +5. Install Envoy Gateway {{< yaml-version >}}: + +```shell +helm upgrade eg oci://docker.io/envoyproxy/gateway-helm --version {{< yaml-version >}} -n envoy-gateway-system +``` diff --git a/site/content/en/docs/tasks/extensibility/envoy-patch-policy.md b/site/content/en/docs/tasks/extensibility/envoy-patch-policy.md index ff819754d1f..7fe84762189 100644 --- a/site/content/en/docs/tasks/extensibility/envoy-patch-policy.md +++ b/site/content/en/docs/tasks/extensibility/envoy-patch-policy.md @@ -111,7 +111,6 @@ spec: group: gateway.networking.k8s.io kind: Gateway name: eg - namespace: default type: JSONPatch jsonPatches: - type: "type.googleapis.com/envoy.config.listener.v3.Listener" @@ -151,7 +150,6 @@ spec: group: gateway.networking.k8s.io kind: Gateway name: eg - namespace: default type: JSONPatch jsonPatches: - type: "type.googleapis.com/envoy.config.listener.v3.Listener" @@ -195,7 +193,6 @@ spec: group: gateway.networking.k8s.io kind: GatewayClass name: eg - namespace: default type: JSONPatch jsonPatches: - type: "type.googleapis.com/envoy.config.listener.v3.Listener" @@ -235,7 +232,6 @@ spec: group: gateway.networking.k8s.io kind: GatewayClass name: eg - namespace: default type: JSONPatch jsonPatches: - type: "type.googleapis.com/envoy.config.listener.v3.Listener" @@ -322,7 +318,6 @@ spec: group: gateway.networking.k8s.io kind: Gateway name: eg - namespace: default type: JSONPatch status: conditions: diff --git a/site/content/en/docs/tasks/extensibility/ext-proc.md b/site/content/en/docs/tasks/extensibility/ext-proc.md index 9028447ab09..31ad551c63b 100644 --- a/site/content/en/docs/tasks/extensibility/ext-proc.md +++ b/site/content/en/docs/tasks/extensibility/ext-proc.md @@ -113,10 +113,10 @@ kind: EnvoyExtensionPolicy metadata: name: ext-proc-example spec: - targetRef: - group: gateway.networking.k8s.io - kind: HTTPRoute - name: myapp + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: myapp extProc: - backendRefs: - name: grpc-ext-proc @@ -139,10 +139,10 @@ kind: EnvoyExtensionPolicy metadata: name: ext-proc-example spec: - targetRef: - group: gateway.networking.k8s.io - kind: HTTPRoute - name: myapp + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: myapp extProc: - backendRefs: - name: grpc-ext-proc diff --git a/site/content/en/docs/tasks/extensibility/wasm.md b/site/content/en/docs/tasks/extensibility/wasm.md index d973de77950..cb2e013dd80 100644 --- a/site/content/en/docs/tasks/extensibility/wasm.md +++ b/site/content/en/docs/tasks/extensibility/wasm.md @@ -44,10 +44,10 @@ kind: EnvoyExtensionPolicy metadata: name: wasm-test spec: - targetRef: - group: gateway.networking.k8s.io - kind: HTTPRoute - name: backend + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: backend wasm: - name: wasm-filter rootID: my_root_id @@ -70,10 +70,10 @@ kind: EnvoyExtensionPolicy metadata: name: wasm-test spec: - targetRef: - group: gateway.networking.k8s.io - kind: HTTPRoute - name: backend + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: backend wasm: - name: wasm-filter rootID: my_root_id @@ -107,8 +107,8 @@ kind: EnvoyExtensionPolicy metadata: name: wasm-test spec: - targetRef: - group: gateway.networking.k8s.io + targetRefs: + - group: gateway.networking.k8s.io kind: HTTPRoute name: backend wasm: @@ -132,17 +132,17 @@ kind: EnvoyExtensionPolicy metadata: name: wasm-test spec: - targetRef: - group: gateway.networking.k8s.io + targetRefs: + - group: gateway.networking.k8s.io kind: HTTPRoute name: backend wasm: - - name: wasm-filter - rootID: my_root_id - code: - type: Image - image: - url: zhaohuabing/testwasm:v0.0.1 + - name: wasm-filter + rootID: my_root_id + code: + type: Image + image: + url: zhaohuabing/testwasm:v0.0.1 ``` {{% /tab %}} diff --git a/site/content/en/docs/tasks/operations/customize-envoyproxy.md b/site/content/en/docs/tasks/operations/customize-envoyproxy.md index 562237bfc43..892c3496ff0 100644 --- a/site/content/en/docs/tasks/operations/customize-envoyproxy.md +++ b/site/content/en/docs/tasks/operations/customize-envoyproxy.md @@ -3,15 +3,68 @@ title: "Customize EnvoyProxy" --- Envoy Gateway provides an [EnvoyProxy][] CRD that can be linked to the ParametersRef -in GatewayClass, allowing cluster admins to customize the managed EnvoyProxy Deployment and +in a Gateway and GatewayClass, allowing cluster admins to customize the managed EnvoyProxy Deployment and Service. To learn more about GatewayClass and ParametersRef, please refer to [Gateway API documentation][]. ## Prerequisites -Follow the steps from the [Quickstart](../../quickstart) to install Envoy Gateway and the example manifest. -Before proceeding, you should be able to query the example backend using HTTP. +{{< boilerplate prerequisites >}} -Before you start, you need to add `ParametersRef` in GatewayClass, and refer to EnvoyProxy Config: +Before you start, you need to add `Infrastructure.ParametersRef` in Gateway, and refer to EnvoyProxy Config: +**Note**: `MergeGateways` cannot be set to `true` in your EnvoyProxy config if attaching to the Gateway. + +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + +```shell +cat <}} + +You can also attach the EnvoyProxy resource to the GatewayClass using the `parametersRef` field. +This configuration is discouraged if you plan on creating multiple Gateways linking to the same +GatewayClass and would like different infrastructure configurations for each of them. {{< tabpane text=true >}} {{% tab header="Apply from stdin" %}} @@ -28,7 +81,7 @@ spec: group: gateway.envoyproxy.io kind: EnvoyProxy name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default EOF ``` @@ -48,7 +101,7 @@ spec: group: gateway.envoyproxy.io kind: EnvoyProxy name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default ``` {{% /tab %}} @@ -67,7 +120,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -87,7 +140,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -119,7 +172,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -140,7 +193,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -168,7 +221,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -191,7 +244,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -221,7 +274,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -248,7 +301,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -280,7 +333,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -305,7 +358,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -339,7 +392,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -368,7 +421,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -404,7 +457,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -426,7 +479,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -459,7 +512,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: bootstrap: type: Replace @@ -547,7 +600,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: bootstrap: type: Replace @@ -649,7 +702,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -677,7 +730,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -713,7 +766,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: extraArgs: - --disable-extensions envoy.access_loggers/envoy.access_loggers.wasm @@ -730,7 +783,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: extraArgs: - --disable-extensions envoy.access_loggers/envoy.access_loggers.wasm @@ -756,7 +809,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: eg - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -792,7 +845,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: eg - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -835,7 +888,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: eg - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -860,7 +913,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: eg - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -918,7 +971,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: filterOrder: - name: envoy.filters.http.wasm @@ -938,7 +991,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: filterOrder: - name: envoy.filters.http.wasm diff --git a/site/content/en/docs/tasks/quickstart.md b/site/content/en/docs/tasks/quickstart.md index 03d7b6de842..802b7989a88 100644 --- a/site/content/en/docs/tasks/quickstart.md +++ b/site/content/en/docs/tasks/quickstart.md @@ -92,34 +92,6 @@ curl --verbose --header "Host: www.example.com" http://localhost:8888/get {{% /tab %}} {{< /tabpane >}} -## v1.1 Upgrade Notes - -Due to breaking changes in the Gateway API v1.1, some manual migration steps are required to upgrade Envoy Gateway to v1.1. - -Delete `BackendTLSPolicy` CRD (and resources): - -```shell -kubectl delete crd backendtlspolicies.gateway.networking.k8s.io -``` - -Update Gateway-API and Envoy Gateway CRDs: - -```shell -helm pull oci://docker.io/envoyproxy/gateway-helm --version v1.1.0 --untar -kubectl apply -f ./gateway-helm/crds/gatewayapi-crds.yaml -kubectl apply -f ./gateway-helm/crds/generated -``` - -Update your `BackendTLSPolicy` and `GRPCRoute` resources according to Gateway-API [v1.1 Upgrade Notes](https://gateway-api.sigs.k8s.io/guides/#v11-upgrade-notes) - -Update your Envoy Gateway xPolicy resources: remove the namespace section from targetRef. - -Install Envoy Gateway v1.1.0: - -```shell -helm upgrade eg oci://docker.io/envoyproxy/gateway-helm --version v1.1.0 -n envoy-gateway-system -``` - ## What to explore next? In this quickstart, you have: diff --git a/site/content/en/docs/tasks/security/backend-tls.md b/site/content/en/docs/tasks/security/backend-tls.md index 53e9ccbd44a..3aadbc34714 100644 --- a/site/content/en/docs/tasks/security/backend-tls.md +++ b/site/content/en/docs/tasks/security/backend-tls.md @@ -25,11 +25,30 @@ Create a root certificate and private key to sign certificates: openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout ca.key -out ca.crt ``` -Create a certificate and a private key for `www.example.com`: +Create a certificate and a private key for `www.example.com`. + +First, create an openssl configuration file: + +```shell +cat > openssl.conf <the access logs will be sent. Currently only Service is supported. | +| `backendRef` | _[BackendObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.BackendObjectReference)_ | false | BackendRef references a Kubernetes object that represents the
backend server to which the authorization request will be sent.

Deprecated: Use BackendRefs instead. | +| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs references a Kubernetes object that represents the
backend server to which the authorization request will be sent. | +| `backendSettings` | _[ClusterSettings](#clustersettings)_ | false | BackendSettings holds configuration for managing the connection
to the backend. | | `logName` | _string_ | false | LogName defines the friendly name of the access log to be returned in
StreamAccessLogsMessage.Identifier. This allows the access log server
to differentiate between different access logs coming from the same Envoy. | | `type` | _[ALSEnvoyProxyAccessLogType](#alsenvoyproxyaccesslogtype)_ | true | Type defines the type of accesslog. Supported types are "HTTP" and "TCP". | | `http` | _[ALSEnvoyProxyHTTPAccessLogConfig](#alsenvoyproxyhttpaccesslogconfig)_ | false | HTTP defines additional configuration specific to HTTP access logs. | @@ -124,6 +126,7 @@ _Appears in:_ | `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. | +| `grpc` | _[GRPCActiveHealthChecker](#grpcactivehealthchecker)_ | false | GRPC defines the configuration of the GRPC health checker.
It's optional, and can only be used if the specified type is GRPC. | #### ActiveHealthCheckPayload @@ -171,6 +174,7 @@ _Appears in:_ | ----- | ----------- | | `HTTP` | ActiveHealthCheckerTypeHTTP defines the HTTP type of health checking.
| | `TCP` | ActiveHealthCheckerTypeTCP defines the TCP type of health checking.
| +| `GRPC` | ActiveHealthCheckerTypeGRPC defines the GRPC type of health checking.
| #### AppProtocolType @@ -273,22 +277,34 @@ _Appears in:_ | `status` | _[BackendStatus](#backendstatus)_ | true | Status defines the current status of Backend. | +#### BackendCluster +BackendCluster contains all the configuration required for configuring access +to a backend. This can include multiple endpoints, and settings that apply for +managing the connection to all these endpoints. + +_Appears in:_ +- [ALSEnvoyProxyAccessLog](#alsenvoyproxyaccesslog) +- [ExtProc](#extproc) +- [GRPCExtAuthService](#grpcextauthservice) +- [HTTPExtAuthService](#httpextauthservice) +- [OpenTelemetryEnvoyProxyAccessLog](#opentelemetryenvoyproxyaccesslog) +- [ProxyOpenTelemetrySink](#proxyopentelemetrysink) +- [TracingProvider](#tracingprovider) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `backendRef` | _[BackendObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.BackendObjectReference)_ | false | BackendRef references a Kubernetes object that represents the
backend server to which the authorization request will be sent.

Deprecated: Use BackendRefs instead. | +| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs references a Kubernetes object that represents the
backend server to which the authorization request will be sent. | +| `backendSettings` | _[ClusterSettings](#clustersettings)_ | false | BackendSettings holds configuration for managing the connection
to the backend. | -#### BackendConnection -BackendConnection allows users to configure connection-level settings of backend -_Appears in:_ -- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `bufferLimit` | _[Quantity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#quantity-resource-api)_ | false | BufferLimit Soft limit on size of the cluster’s connections read and write buffers.
BufferLimit applies to connection streaming (maybe non-streaming) channel between processes, it's in user space.
If unspecified, an implementation defined default is applied (32768 bytes).
For example, 20Mi, 1Gi, 256Ki etc.
Note: that when the suffix is not provided, the value is interpreted as bytes. | #### BackendEndpoint @@ -333,6 +349,7 @@ BackendRef defines how an ObjectReference that is specific to BackendRef. _Appears in:_ - [ALSEnvoyProxyAccessLog](#alsenvoyproxyaccesslog) +- [BackendCluster](#backendcluster) - [ExtProc](#extproc) - [GRPCExtAuthService](#grpcextauthservice) - [HTTPExtAuthService](#httpextauthservice) @@ -347,6 +364,7 @@ _Appears in:_ | `name` | _[ObjectName](#objectname)_ | true | Name is the name of the referent. | | `namespace` | _[Namespace](#namespace)_ | false | Namespace is the namespace of the backend. When unspecified, the local
namespace is inferred.

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.

Support: Core | | `port` | _[PortNumber](#portnumber)_ | false | 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. | +| `failover` | _boolean_ | false | Failover This indicates whether the backend is designated as a failover.
Multiple failover backends can be configured.
It is highly recommended to configure active or passive health checks to ensure that failover can be detected
when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again.
The overprovisioning factor is set to 1.4, meaning the failover backends will only start receiving traffic when
the health of the active backends falls below 72%. | #### BackendSpec @@ -447,19 +465,19 @@ _Appears in:_ | `targetRef` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName)_ | 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

Deprecated: use targetRefs/targetSelectors instead | | `targetRefs` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName) array_ | true | TargetRefs are the names of the Gateway resources this policy
is being attached to. | | `targetSelectors` | _[TargetSelector](#targetselector) array_ | true | TargetSelectors allow targeting resources for this policy based on labels | -| `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 | +| `loadBalancer` | _[LoadBalancer](#loadbalancer)_ | false | LoadBalancer policy to apply when routing traffic from the gateway to
the backend endpoints. Defaults to `LeastRequest`. | | `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. | -| `useClientProtocol` | _boolean_ | false | UseClientProtocol configures Envoy to prefer sending requests to backends using
the same HTTP protocol that the incoming request used. Defaults to false, which means
that Envoy will use the protocol indicated by the attached BackendRef. | | `timeout` | _[Timeout](#timeout)_ | false | Timeout settings for the backend connections. | | `connection` | _[BackendConnection](#backendconnection)_ | false | Connection includes backend connection settings. | | `dns` | _[DNS](#dns)_ | false | DNS includes dns resolution settings. | | `http2` | _[HTTP2Settings](#http2settings)_ | false | HTTP2 provides HTTP/2 configuration for backend connections. | +| `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. | +| `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 | +| `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. | +| `useClientProtocol` | _boolean_ | false | UseClientProtocol configures Envoy to prefer sending requests to backends using
the same HTTP protocol that the incoming request used. Defaults to false, which means
that Envoy will use the protocol indicated by the attached BackendRef. | #### BasicAuth @@ -522,22 +540,6 @@ _Appears in:_ | `allowCredentials` | _boolean_ | true | AllowCredentials indicates whether a request can include user credentials
like cookies, authentication headers, or TLS client certificates. | -#### CircuitBreaker - - - -CircuitBreaker defines the Circuit Breaker configuration. - -_Appears in:_ -- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) - -| 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. | -| `maxParallelRetries` | _integer_ | false | The maximum number of parallel retries 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 @@ -700,6 +702,37 @@ _Appears in:_ | `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. | +#### ClusterSettings + + + +ClusterSettings provides the various knobs that can be set to control how traffic to a given +backend will be configured. + +_Appears in:_ +- [ALSEnvoyProxyAccessLog](#alsenvoyproxyaccesslog) +- [BackendCluster](#backendcluster) +- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) +- [ExtProc](#extproc) +- [GRPCExtAuthService](#grpcextauthservice) +- [HTTPExtAuthService](#httpextauthservice) +- [OpenTelemetryEnvoyProxyAccessLog](#opentelemetryenvoyproxyaccesslog) +- [ProxyOpenTelemetrySink](#proxyopentelemetrysink) +- [TracingProvider](#tracingprovider) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `loadBalancer` | _[LoadBalancer](#loadbalancer)_ | false | LoadBalancer policy to apply when routing traffic from the gateway to
the backend endpoints. Defaults to `LeastRequest`. | +| `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. | +| `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 | +| `timeout` | _[Timeout](#timeout)_ | false | Timeout settings for the backend connections. | +| `connection` | _[BackendConnection](#backendconnection)_ | false | Connection includes backend connection settings. | +| `dns` | _[DNS](#dns)_ | false | DNS includes dns resolution settings. | +| `http2` | _[HTTP2Settings](#http2settings)_ | false | HTTP2 provides HTTP/2 configuration for backend connections. | + + #### Compression @@ -845,19 +878,6 @@ _Appears in:_ | `RequestHeader` | CustomTagTypeRequestHeader adds value from request header to each span.
| -#### DNS - - - - - -_Appears in:_ -- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `dnsRefreshRate` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | true | DNSRefreshRate specifies the rate at which DNS records should be refreshed.
Defaults to 30 seconds. | -| `respectDnsTtl` | _boolean_ | true | RespectDNSTTL indicates whether the DNS Time-To-Live (TTL) should be respected.
If the value is set to true, the DNS refresh rate will be set to the resource record’s TTL.
Defaults to true. | #### EnvironmentCustomTag @@ -945,6 +965,7 @@ _Appears in:_ | `envoy.filters.http.basic_auth` | EnvoyFilterBasicAuth defines the Envoy HTTP basic authentication filter.
| | `envoy.filters.http.oauth2` | EnvoyFilterOAuth2 defines the Envoy HTTP OAuth2 filter.
| | `envoy.filters.http.jwt_authn` | EnvoyFilterJWTAuthn defines the Envoy HTTP JWT authentication filter.
| +| `envoy.filters.http.stateful_session` | EnvoyFilterSessionPersistence defines the Envoy HTTP session persistence filter.
| | `envoy.filters.http.ext_proc` | EnvoyFilterExtProc defines the Envoy HTTP external process filter.
| | `envoy.filters.http.wasm` | EnvoyFilterWasm defines the Envoy HTTP WebAssembly filter.
| | `envoy.filters.http.rbac` | EnvoyFilterRBAC defines the Envoy RBAC filter.
| @@ -1403,7 +1424,7 @@ _Appears in:_ | `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. | | `shutdown` | _[ShutdownConfig](#shutdownconfig)_ | false | Shutdown defines configuration for graceful envoy shutdown process. | -| `filterOrder` | _[FilterPosition](#filterposition) array_ | false | FilterOrder defines the order of filters in the Envoy proxy's HTTP filter chain.
The FilterPosition in the list will be applied in the order they are defined.
If unspecified, the default filter order is applied.
Default filter order is:

- envoy.filters.http.health_check

- envoy.filters.http.fault

- envoy.filters.http.cors

- envoy.filters.http.ext_authz

- envoy.filters.http.basic_auth

- envoy.filters.http.oauth2

- envoy.filters.http.jwt_authn

- envoy.filters.http.ext_proc

- envoy.filters.http.wasm

- envoy.filters.http.rbac

- envoy.filters.http.local_ratelimit

- envoy.filters.http.ratelimit

- envoy.filters.http.router

Note: "envoy.filters.http.router" cannot be reordered, it's always the last filter in the chain. | +| `filterOrder` | _[FilterPosition](#filterposition) array_ | false | FilterOrder defines the order of filters in the Envoy proxy's HTTP filter chain.
The FilterPosition in the list will be applied in the order they are defined.
If unspecified, the default filter order is applied.
Default filter order is:

- envoy.filters.http.health_check

- envoy.filters.http.fault

- envoy.filters.http.cors

- envoy.filters.http.ext_authz

- envoy.filters.http.basic_auth

- envoy.filters.http.oauth2

- envoy.filters.http.jwt_authn

- envoy.filters.http.stateful_session

- envoy.filters.http.ext_proc

- envoy.filters.http.wasm

- envoy.filters.http.rbac

- envoy.filters.http.local_ratelimit

- envoy.filters.http.ratelimit

- envoy.filters.http.router

Note: "envoy.filters.http.router" cannot be reordered, it's always the last filter in the chain. | | `backendTLS` | _[BackendTLSConfig](#backendtlsconfig)_ | false | BackendTLS is the TLS configuration for the Envoy proxy to use when connecting to backends.
These settings are applied on backends for which TLS policies are specified. | @@ -1464,7 +1485,9 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | -| `backendRefs` | _[BackendRef](#backendref) array_ | true | BackendRefs defines the configuration of the external processing service | +| `backendRef` | _[BackendObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.BackendObjectReference)_ | false | BackendRef references a Kubernetes object that represents the
backend server to which the authorization request will be sent.

Deprecated: Use BackendRefs instead. | +| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs references a Kubernetes object that represents the
backend server to which the authorization request will be sent. | +| `backendSettings` | _[ClusterSettings](#clustersettings)_ | false | BackendSettings holds configuration for managing the connection
to the backend. | | `messageTimeout` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ | false | MessageTimeout is the timeout for a response to be returned from the external processor
Default: 200ms | | `failOpen` | _boolean_ | false | FailOpen defines if requests or responses that cannot be processed due to connectivity to the
external processor are terminated or passed-through.
Default: false | | `processingMode` | _[ExtProcProcessingMode](#extprocprocessingmode)_ | false | ProcessingMode defines how request and response body is processed
Default: header and body are not sent to the external processor | @@ -1678,6 +1701,20 @@ _Appears in:_ | `after` | _[EnvoyFilter](#envoyfilter)_ | true | After defines the filter that should come after the filter.
Only one of Before or After must be set. | +#### GRPCActiveHealthChecker + + + +GRPCActiveHealthChecker defines the settings of the GRPC health check. + +_Appears in:_ +- [ActiveHealthCheck](#activehealthcheck) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `service` | _string_ | false | Service to send in the health check request.
If this is not specified, then the health check request applies to the entire
server and not to a specific service. | + + #### GRPCExtAuthService @@ -1691,8 +1728,9 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | -| `backendRef` | _[BackendObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.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.

Deprecated: Use BackendRefs instead. | -| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs 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` | _[BackendObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.BackendObjectReference)_ | false | BackendRef references a Kubernetes object that represents the
backend server to which the authorization request will be sent.

Deprecated: Use BackendRefs instead. | +| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs references a Kubernetes object that represents the
backend server to which the authorization request will be sent. | +| `backendSettings` | _[ClusterSettings](#clustersettings)_ | false | BackendSettings holds configuration for managing the connection
to the backend. | #### Gateway @@ -1784,22 +1822,6 @@ _Appears in:_ | `http10` | _[HTTP10Settings](#http10settings)_ | false | HTTP10 turns on support for HTTP/1.0 and HTTP/0.9 requests. | -#### HTTP2Settings - - - -HTTP2Settings provides HTTP/2 configuration for listeners and backends. - -_Appears in:_ -- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) -- [ClientTrafficPolicySpec](#clienttrafficpolicyspec) - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `initialStreamWindowSize` | _[Quantity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#quantity-resource-api)_ | false | InitialStreamWindowSize sets the initial window size for HTTP/2 streams.
If not set, the default value is 64 KiB(64*1024). | -| `initialConnectionWindowSize` | _[Quantity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#quantity-resource-api)_ | false | InitialConnectionWindowSize sets the initial window size for HTTP/2 connections.
If not set, the default value is 1 MiB. | -| `maxConcurrentStreams` | _integer_ | false | MaxConcurrentStreams sets the maximum number of concurrent streams allowed per connection.
If not set, the default value is 100. | -| `onInvalidMessage` | _[InvalidMessageAction](#invalidmessageaction)_ | false | OnInvalidMessage determines if Envoy will terminate the connection or just the offending stream in the event of HTTP messaging error
It's recommended for L2 Envoy deployments to set this value to TerminateStream.
https://www.envoyproxy.io/docs/envoy/latest/configuration/best_practices/level_two
Default: TerminateConnection | #### HTTP3Settings @@ -1856,8 +1878,9 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | -| `backendRef` | _[BackendObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.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.

Deprecated: Use BackendRefs instead. | -| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs 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` | _[BackendObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.BackendObjectReference)_ | false | BackendRef references a Kubernetes object that represents the
backend server to which the authorization request will be sent.

Deprecated: Use BackendRefs instead. | +| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs references a Kubernetes object that represents the
backend server to which the authorization request will be sent. | +| `backendSettings` | _[ClusterSettings](#clustersettings)_ | false | BackendSettings holds configuration for managing the connection
to the backend. | | `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. | @@ -1954,22 +1977,9 @@ _Appears in:_ | `xForwardedClientCert` | _[XForwardedClientCert](#xforwardedclientcert)_ | false | XForwardedClientCert configures how Envoy Proxy handle the x-forwarded-client-cert (XFCC) HTTP header.

x-forwarded-client-cert (XFCC) is an HTTP header used to forward the certificate
information of part or all of the clients or proxies that a request has flowed through,
on its way from the client to the server.

Envoy proxy may choose to sanitize/append/forward the XFCC header before proxying the request.

If not set, the default behavior is sanitizing the XFCC header. | | `withUnderscoresAction` | _[WithUnderscoresAction](#withunderscoresaction)_ | false | WithUnderscoresAction configures the action to take when an HTTP header with underscores
is encountered. The default action is to reject the request. | | `preserveXRequestID` | _boolean_ | false | PreserveXRequestID configures Envoy to keep the X-Request-ID header if passed for a request that is edge
(Edge request is the request from external clients to front Envoy) and not reset it, which is the current Envoy behaviour.
It defaults to false. | +| `earlyRequestHeaders` | _[HTTPHeaderFilter](#httpheaderfilter)_ | false | EarlyRequestHeaders defines settings for early request header modification, before envoy performs
routing, tracing and built-in header manipulation. | -#### HealthCheck - - - -HealthCheck configuration to decide which endpoints -are healthy and can be used for routing. - -_Appears in:_ -- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `active` | _[ActiveHealthCheck](#activehealthcheck)_ | false | Active health check configuration | -| `passive` | _[PassiveHealthCheck](#passivehealthcheck)_ | false | Passive passive check configuration | #### HealthCheckSettings @@ -2076,7 +2086,8 @@ _Appears in:_ | 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. | +| `path` | _string_ | false | 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. | +| `jsonPath` | _string_ | false | JSONPath specifies the locations of the target document/field where the operation will be performed
Refer to https://datatracker.ietf.org/doc/rfc9535/ 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](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#json-v1-apiextensions-k8s-io)_ | false | Value is the new value of the path location. The value is only used by
the `add` and `replace` operations. | @@ -2384,20 +2395,6 @@ _Appears in:_ | `value` | _string_ | true | Value defines the hard-coded value to add to each span. | -#### LoadBalancer - - - -LoadBalancer defines the load balancer policy to be applied. - -_Appears in:_ -- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) - -| 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 @@ -2533,9 +2530,11 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | +| `backendRef` | _[BackendObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.BackendObjectReference)_ | false | BackendRef references a Kubernetes object that represents the
backend server to which the authorization request will be sent.

Deprecated: Use BackendRefs instead. | +| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs references a Kubernetes object that represents the
backend server to which the authorization request will be sent. | +| `backendSettings` | _[ClusterSettings](#clustersettings)_ | false | BackendSettings holds configuration for managing the connection
to the backend. | | `host` | _string_ | false | Host define the extension service hostname.
Deprecated: Use BackendRefs instead. | | `port` | _integer_ | false | Port defines the port the extension service is exposed on.
Deprecated: Use BackendRefs instead. | -| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs references a Kubernetes object that represents the
backend server to which the access log will be sent.
Only Service kind is supported for now. | | `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/). | @@ -2890,9 +2889,11 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | +| `backendRef` | _[BackendObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.BackendObjectReference)_ | false | BackendRef references a Kubernetes object that represents the
backend server to which the authorization request will be sent.

Deprecated: Use BackendRefs instead. | +| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs references a Kubernetes object that represents the
backend server to which the authorization request will be sent. | +| `backendSettings` | _[ClusterSettings](#clustersettings)_ | false | BackendSettings holds configuration for managing the connection
to the backend. | | `host` | _string_ | false | Host define the service hostname.
Deprecated: Use BackendRefs instead. | | `port` | _integer_ | false | Port defines the port the service is exposed on.
Deprecated: Use BackendRefs instead. | -| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs references a Kubernetes object that represents the
backend server to which the metric will be sent.
Only Service kind is supported for now. | #### ProxyPrometheusProvider @@ -2910,19 +2911,6 @@ _Appears in:_ | `compression` | _[Compression](#compression)_ | false | Configure the compression on Prometheus endpoint. Compression is useful in situations when bandwidth is scarce and large payloads can be effectively compressed at the expense of higher CPU load. | -#### ProxyProtocol - - - -ProxyProtocol defines the configuration related to the proxy protocol -when communicating with the backend. - -_Appears in:_ -- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `version` | _[ProxyProtocolVersion](#proxyprotocolversion)_ | true | Version of ProxyProtol
Valid ProxyProtocolVersion values are
"V1"
"V2" | #### ProxyProtocolVersion @@ -3528,21 +3516,6 @@ _Appears in:_ | `idleTimeout` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ | false | IdleTimeout for a TCP connection. Idle time is defined as a period in which there are no
bytes sent or received on either the upstream or downstream connection.
Default: 1 hour. | -#### TCPKeepalive - - - -TCPKeepalive define the TCP Keepalive configuration. - -_Appears in:_ -- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) -- [ClientTrafficPolicySpec](#clienttrafficpolicyspec) - -| 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](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.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](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ | false | The duration between keep-alive probes.
Defaults to `75s`. | #### TCPTimeout @@ -3619,19 +3592,6 @@ _Appears in:_ | `matchLabels` | _object (keys:string, values:string)_ | true | MatchLabels are the set of label selectors for identifying the targeted resource | -#### 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 @@ -3645,10 +3605,12 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | +| `backendRef` | _[BackendObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.BackendObjectReference)_ | false | BackendRef references a Kubernetes object that represents the
backend server to which the authorization request will be sent.

Deprecated: Use BackendRefs instead. | +| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs references a Kubernetes object that represents the
backend server to which the authorization request will be sent. | +| `backendSettings` | _[ClusterSettings](#clustersettings)_ | false | BackendSettings holds configuration for managing the connection
to the backend. | | `type` | _[TracingProviderType](#tracingprovidertype)_ | true | Type defines the tracing provider type. | | `host` | _string_ | false | Host define the provider service hostname.
Deprecated: Use BackendRefs instead. | | `port` | _integer_ | false | Port defines the port the provider service is exposed on.
Deprecated: Use BackendRefs instead. | -| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs references a Kubernetes object that represents the
backend server to which the trace will be sent.
Only Service kind is supported for now. | | `zipkin` | _[ZipkinTracingProvider](#zipkintracingprovider)_ | false | Zipkin defines the Zipkin tracing provider configuration | diff --git a/site/content/en/latest/concepts/concepts_overview.md b/site/content/en/latest/concepts/concepts_overview.md index 31838b520f2..9af9a3fff10 100644 --- a/site/content/en/latest/concepts/concepts_overview.md +++ b/site/content/en/latest/concepts/concepts_overview.md @@ -10,13 +10,12 @@ There are several resources that play a part in enabling you to meet your Kubern There are several resources that play a part in enabling you to meet your Kubernetes ingress traffic handling needs. This page provides a brief overview of the resources you’ll be working with. -# Overview - -## Kubernetes Gateway API Resources +### Kubernetes Gateway API Resources - **GatewayClass:** Defines a class of Gateways with common configuration. - **Gateway:** Specifies how traffic can enter the cluster. - **Routes:** **HTTPRoute, GRPCRoute, TLSRoute, TCPRoute, UDPRoute:** Define routing rules for different types of traffic. -## Envoy Gateway (EG) API Resources + +### Envoy Gateway (EG) API Resources - **EnvoyProxy:** Represents the deployment and configuration of the Envoy proxy within a Kubernetes cluster, managing its lifecycle and settings. - **EnvoyPatchPolicy, ClientTrafficPolicy, SecurityPolicy, BackendTrafficPolicy, EnvoyExtensionPolicy, BackendTLSPolicy:** Additional policies and configurations specific to Envoy Gateway. - **Backend:** A resource that makes routing to cluster-external backends easier and makes access to external processes via Unix Domain Sockets possible. diff --git a/site/content/en/latest/install/install-yaml.md b/site/content/en/latest/install/install-yaml.md index e675f15fbec..c0a8d1caa72 100644 --- a/site/content/en/latest/install/install-yaml.md +++ b/site/content/en/latest/install/install-yaml.md @@ -13,7 +13,7 @@ installation, it is recommended that you use helm. Envoy Gateway is designed to run in Kubernetes for production. The most essential requirements are: -* Kubernetes 1.25 or later +* Kubernetes 1.27 or later * The `kubectl` command-line tool {{% alert title="Compatibility Matrix" color="warning" %}} @@ -37,3 +37,31 @@ Refer to the [Developer Guide](../../contributions/develop) to learn more. 2. Next Steps Envoy Gateway should now be successfully installed and running, but in order to experience more abilities of Envoy Gateway, you can refer to [Tasks](/latest/tasks). + +## Upgrading from v1.0 + +Due to breaking changes in Gateway API v1.1, some manual migration steps are required to upgrade Envoy Gateway to v1.1. + +1. Delete `BackendTLSPolicy` CRD (and resources): + +```shell +kubectl delete crd backendtlspolicies.gateway.networking.k8s.io +``` + +2. Update Gateway-API and Envoy Gateway CRDs: + +```shell +helm pull oci://docker.io/envoyproxy/gateway-helm --version {{< yaml-version >}} --untar +kubectl apply --force-conflicts --server-side -f ./gateway-helm/crds/gatewayapi-crds.yaml +kubectl apply --force-conflicts --server-side -f ./gateway-helm/crds/generated +``` + +3. Update your `BackendTLSPolicy` and `GRPCRoute` resources according to Gateway-API [v1.1 Upgrade Notes](https://gateway-api.sigs.k8s.io/guides/#v11-upgrade-notes) + +4. Update your Envoy Gateway xPolicy resources: remove the namespace section from targetRef. + +5. Install Envoy Gateway {{< yaml-version >}}: + +```shell +helm upgrade eg oci://docker.io/envoyproxy/gateway-helm --version {{< yaml-version >}} -n envoy-gateway-system +``` diff --git a/site/content/en/latest/install/migrating-to-envoy.md b/site/content/en/latest/install/migrating-to-envoy.md new file mode 100644 index 00000000000..470c759ab7e --- /dev/null +++ b/site/content/en/latest/install/migrating-to-envoy.md @@ -0,0 +1,143 @@ +--- +title: Migrating from Ingress Resources +--- + +## Introduction + +Migrating from Ingress to Envoy Gateway involves converting existing Ingress resources into resources compatible with Envoy Gateway. The `ingress2gateway` tool simplifies this migration by transforming Ingress resources into Gateway API resources that Envoy Gateway can use. This guide will walk you through the prerequisites, installation of the `ingress2gateway` tool, and provide an example migration process. + +## Prerequisites + +Before you start the migration, ensure you have the following: + +1. **Envoy Gateway Installed**: You need Envoy Gateway set up in your Kubernetes cluster. Follow the [Envoy Gateway installation guide](../install) for details. +2. **Kubernetes Cluster Access**: Ensure you have access to your Kubernetes cluster and necessary permissions to manage resources. +3. **Installation of `ingress2gateway` Tool**: You need to install the `ingress2gateway` tool in your Kubernetes cluster and configure it accordingly. Follow the [ingress2gateway tool installation guide](https://github.com/kubernetes-sigs/ingress2gateway/blob/main/README.md#installation) for details. + +## Example Migration + +Here’s a step-by-step example of migrating from Ingress to Envoy Gateway using `ingress2gateway`: + +### 1. Install and Configure Envoy Gateway + +Ensure that Envoy Gateway is installed and running in your cluster. Follow the [official Envoy Gateway installation guide](../install) for setup instructions. + +### 2. Create a GatewayClass + +To ensure the generated HTTPRoutes are programmed correctly in the Envoy Gateway data plane, create a GatewayClass that links to the Envoy Gateway controller. + +Create a `GatewayClass` resource: + +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: GatewayClass +metadata: + name: envoy-gateway-class +spec: + controllerName: gateway.envoyproxy.io/controller +``` + +Apply this resource: + +```sh +kubectl apply -f gatewayclass.yaml +``` + +### 3. Install Ingress2gateway + +Ensure you have the Ingress2gateway package installed. If not, follow the package’s installation instructions. + +### 4. Run Ingress2gateway + +Use Ingress2gateway to read your existing Ingress resources and translate them into Gateway API resources. + +```sh +./ingress2gateway print +``` + +This command will: +1. Read your Kube config file to extract the cluster credentials and the current active namespace. +2. Search for Ingress and provider-specific resources in that namespace. +3. Convert them to Gateway API resources (Gateways and HTTPRoutes). + +#### Example Ingress Configuration + +```yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: example-ingress + namespace: default + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / +spec: + rules: + - host: example.com + http: + paths: + - path: /foo + pathType: Prefix + backend: + service: + name: foo-service + port: + number: 80 +``` + +### 5. Save the Output + +The command will output the equivalent Gateway API resources in YAML/JSON format to stdout. Save this output to a file for further use. + +```sh +./ingress2gateway print > gateway-resources.yaml +``` + +### 6. Apply the Translated Resources + +Apply the translated Gateway API resources to your cluster. + +```sh +kubectl apply -f gateway-resources.yaml +``` + +### 7. Create a Gateway Resource + +Create a `Gateway` resource specifying the `GatewayClass` created earlier and including the necessary listeners. + +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: example-gateway + namespace: default +spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + protocol: HTTP + port: 80 + hostname: example.com +``` + +Apply this resource: + +```sh +kubectl apply -f gateway.yaml +``` + +### 8. Validate the Migration + +Ensure the HTTPRoutes and Gateways are correctly set up and that traffic is being routed as expected. Validate the new configuration by checking the status of the Gateway and HTTPRoute resources. + +```sh +kubectl get gateways +kubectl get httproutes +``` + +### 9. Monitor and Troubleshoot + +Monitor the Envoy Gateway logs and metrics to ensure everything is functioning correctly. Troubleshoot any issues by reviewing the Gateway and HTTPRoute statuses and Envoy Gateway controller logs. + +## Summary + +By following this guide, users can effectively migrate their existing Ingress resources to Envoy Gateway using the Ingress2gateway package. Creating a GatewayClass and linking it to the Envoy Gateway controller ensures that the translated resources are properly programmed in the data plane, providing a seamless transition to the Envoy Gateway environment. \ No newline at end of file diff --git a/site/content/en/latest/tasks/extensibility/envoy-patch-policy.md b/site/content/en/latest/tasks/extensibility/envoy-patch-policy.md index 9626dc93752..36930d73785 100644 --- a/site/content/en/latest/tasks/extensibility/envoy-patch-policy.md +++ b/site/content/en/latest/tasks/extensibility/envoy-patch-policy.md @@ -110,7 +110,6 @@ spec: group: gateway.networking.k8s.io kind: Gateway name: eg - namespace: default type: JSONPatch jsonPatches: - type: "type.googleapis.com/envoy.config.listener.v3.Listener" @@ -150,7 +149,6 @@ spec: group: gateway.networking.k8s.io kind: Gateway name: eg - namespace: default type: JSONPatch jsonPatches: - type: "type.googleapis.com/envoy.config.listener.v3.Listener" @@ -194,7 +192,6 @@ spec: group: gateway.networking.k8s.io kind: GatewayClass name: eg - namespace: default type: JSONPatch jsonPatches: - type: "type.googleapis.com/envoy.config.listener.v3.Listener" @@ -234,7 +231,6 @@ spec: group: gateway.networking.k8s.io kind: GatewayClass name: eg - namespace: default type: JSONPatch jsonPatches: - type: "type.googleapis.com/envoy.config.listener.v3.Listener" @@ -321,7 +317,6 @@ spec: group: gateway.networking.k8s.io kind: Gateway name: eg - namespace: default type: JSONPatch status: conditions: diff --git a/site/content/en/latest/tasks/extensibility/ext-proc.md b/site/content/en/latest/tasks/extensibility/ext-proc.md index f6b8b5c741a..910332f4740 100644 --- a/site/content/en/latest/tasks/extensibility/ext-proc.md +++ b/site/content/en/latest/tasks/extensibility/ext-proc.md @@ -106,10 +106,10 @@ kind: EnvoyExtensionPolicy metadata: name: ext-proc-example spec: - targetRef: - group: gateway.networking.k8s.io - kind: HTTPRoute - name: myapp + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: myapp extProc: - backendRefs: - name: grpc-ext-proc @@ -132,10 +132,10 @@ kind: EnvoyExtensionPolicy metadata: name: ext-proc-example spec: - targetRef: - group: gateway.networking.k8s.io - kind: HTTPRoute - name: myapp + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: myapp extProc: - backendRefs: - name: grpc-ext-proc diff --git a/site/content/en/latest/tasks/extensibility/wasm.md b/site/content/en/latest/tasks/extensibility/wasm.md index 6cb3d1092df..8a640471ee1 100644 --- a/site/content/en/latest/tasks/extensibility/wasm.md +++ b/site/content/en/latest/tasks/extensibility/wasm.md @@ -37,8 +37,8 @@ kind: EnvoyExtensionPolicy metadata: name: wasm-test spec: - targetRef: - group: gateway.networking.k8s.io + targetRefs: + - group: gateway.networking.k8s.io kind: HTTPRoute name: backend wasm: @@ -63,18 +63,18 @@ kind: EnvoyExtensionPolicy metadata: name: wasm-test spec: - targetRef: - group: gateway.networking.k8s.io + targetRefs: + - group: gateway.networking.k8s.io kind: HTTPRoute name: backend wasm: - - name: wasm-filter - rootID: my_root_id - code: - type: HTTP - http: - url: https://raw.githubusercontent.com/envoyproxy/envoy/main/examples/wasm-cc/lib/envoy_filter_http_wasm_example.wasm - sha256: 79c9f85128bb0177b6511afa85d587224efded376ac0ef76df56595f1e6315c0 + - name: wasm-filter + rootID: my_root_id + code: + type: HTTP + http: + url: https://raw.githubusercontent.com/envoyproxy/envoy/main/examples/wasm-cc/lib/envoy_filter_http_wasm_example.wasm + sha256: 79c9f85128bb0177b6511afa85d587224efded376ac0ef76df56595f1e6315c0 ``` {{% /tab %}} @@ -100,8 +100,8 @@ kind: EnvoyExtensionPolicy metadata: name: wasm-test spec: - targetRef: - group: gateway.networking.k8s.io + targetRefs: + - group: gateway.networking.k8s.io kind: HTTPRoute name: backend wasm: @@ -125,17 +125,17 @@ kind: EnvoyExtensionPolicy metadata: name: wasm-test spec: - targetRef: - group: gateway.networking.k8s.io + targetRefs: + - group: gateway.networking.k8s.io kind: HTTPRoute name: backend wasm: - - name: wasm-filter - rootID: my_root_id - code: - type: Image - image: - url: zhaohuabing/testwasm:v0.0.1 + - name: wasm-filter + rootID: my_root_id + code: + type: Image + image: + url: zhaohuabing/testwasm:v0.0.1 ``` {{% /tab %}} diff --git a/site/content/en/latest/tasks/operations/customize-envoyproxy.md b/site/content/en/latest/tasks/operations/customize-envoyproxy.md index bfcc3d6e07a..892c3496ff0 100644 --- a/site/content/en/latest/tasks/operations/customize-envoyproxy.md +++ b/site/content/en/latest/tasks/operations/customize-envoyproxy.md @@ -3,14 +3,68 @@ title: "Customize EnvoyProxy" --- Envoy Gateway provides an [EnvoyProxy][] CRD that can be linked to the ParametersRef -in GatewayClass, allowing cluster admins to customize the managed EnvoyProxy Deployment and +in a Gateway and GatewayClass, allowing cluster admins to customize the managed EnvoyProxy Deployment and Service. To learn more about GatewayClass and ParametersRef, please refer to [Gateway API documentation][]. ## Prerequisites {{< boilerplate prerequisites >}} -Before you start, you need to add `ParametersRef` in GatewayClass, and refer to EnvoyProxy Config: +Before you start, you need to add `Infrastructure.ParametersRef` in Gateway, and refer to EnvoyProxy Config: +**Note**: `MergeGateways` cannot be set to `true` in your EnvoyProxy config if attaching to the Gateway. + +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + +```shell +cat <}} + +You can also attach the EnvoyProxy resource to the GatewayClass using the `parametersRef` field. +This configuration is discouraged if you plan on creating multiple Gateways linking to the same +GatewayClass and would like different infrastructure configurations for each of them. {{< tabpane text=true >}} {{% tab header="Apply from stdin" %}} @@ -27,7 +81,7 @@ spec: group: gateway.envoyproxy.io kind: EnvoyProxy name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default EOF ``` @@ -47,7 +101,7 @@ spec: group: gateway.envoyproxy.io kind: EnvoyProxy name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default ``` {{% /tab %}} @@ -66,7 +120,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -86,7 +140,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -118,7 +172,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -139,7 +193,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -167,7 +221,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -190,7 +244,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -220,7 +274,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -247,7 +301,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -279,7 +333,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -304,7 +358,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -338,7 +392,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -367,7 +421,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -403,7 +457,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -425,7 +479,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -458,7 +512,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: bootstrap: type: Replace @@ -546,7 +600,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: bootstrap: type: Replace @@ -648,7 +702,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -676,7 +730,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -712,7 +766,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: extraArgs: - --disable-extensions envoy.access_loggers/envoy.access_loggers.wasm @@ -729,7 +783,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: extraArgs: - --disable-extensions envoy.access_loggers/envoy.access_loggers.wasm @@ -755,7 +809,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: eg - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -791,7 +845,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: eg - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -834,7 +888,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: eg - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -859,7 +913,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: eg - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -917,7 +971,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: filterOrder: - name: envoy.filters.http.wasm @@ -937,7 +991,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: filterOrder: - name: envoy.filters.http.wasm diff --git a/site/content/en/latest/tasks/quickstart.md b/site/content/en/latest/tasks/quickstart.md index 03d7b6de842..802b7989a88 100644 --- a/site/content/en/latest/tasks/quickstart.md +++ b/site/content/en/latest/tasks/quickstart.md @@ -92,34 +92,6 @@ curl --verbose --header "Host: www.example.com" http://localhost:8888/get {{% /tab %}} {{< /tabpane >}} -## v1.1 Upgrade Notes - -Due to breaking changes in the Gateway API v1.1, some manual migration steps are required to upgrade Envoy Gateway to v1.1. - -Delete `BackendTLSPolicy` CRD (and resources): - -```shell -kubectl delete crd backendtlspolicies.gateway.networking.k8s.io -``` - -Update Gateway-API and Envoy Gateway CRDs: - -```shell -helm pull oci://docker.io/envoyproxy/gateway-helm --version v1.1.0 --untar -kubectl apply -f ./gateway-helm/crds/gatewayapi-crds.yaml -kubectl apply -f ./gateway-helm/crds/generated -``` - -Update your `BackendTLSPolicy` and `GRPCRoute` resources according to Gateway-API [v1.1 Upgrade Notes](https://gateway-api.sigs.k8s.io/guides/#v11-upgrade-notes) - -Update your Envoy Gateway xPolicy resources: remove the namespace section from targetRef. - -Install Envoy Gateway v1.1.0: - -```shell -helm upgrade eg oci://docker.io/envoyproxy/gateway-helm --version v1.1.0 -n envoy-gateway-system -``` - ## What to explore next? In this quickstart, you have: diff --git a/site/content/en/latest/tasks/security/backend-tls.md b/site/content/en/latest/tasks/security/backend-tls.md index c30777f69f3..7fca5ef8477 100644 --- a/site/content/en/latest/tasks/security/backend-tls.md +++ b/site/content/en/latest/tasks/security/backend-tls.md @@ -25,11 +25,30 @@ Create a root certificate and private key to sign certificates: openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout ca.key -out ca.crt ``` -Create a certificate and a private key for `www.example.com`: +Create a certificate and a private key for `www.example.com`. + +First, create an openssl configuration file: + +```shell +cat > openssl.conf <}} +## Early Header Modification + +In some cases, it could be necessary to modify headers before the proxy performs any sort of processing, routing or tracing. Envoy Gateway supports this functionality using the [ClientTrafficPolicy][] API. + +A ClientTrafficPolicy resource can be attached to a Gateway resource to configure early header modifications for all its routes. In the following example we will demonstrate how early header modification can be configured. + +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + +```shell +cat <}} + + +Querying `headers.example/get` should result in a `200` response from the example Gateway and the output from the +example app should indicate that the upstream example app received the following headers: +- `early-added-header` contains early (ClientTrafficPolicy) and late (RouteFilter) values +- `early-set-header` contains only early (ClientTrafficPolicy) and late (RouteFilter) values, since the early modification overwritten the client value. +- `early-removed-header` contains only the late (RouteFilter) value, since the early modification deleted the client value. + +```console +$ curl -vvv --header "Host: headers.example" "http://${GATEWAY_HOST}/get" --header "early-added-header: client" --header "early-set-header: client" --header "early-removed-header: client" +... +> GET /get HTTP/1.1 +> Host: headers.example +> User-Agent: curl/7.81.0 +> Accept: */* +> add-header: something +> +* Mark bundle as not supporting multiuse +< HTTP/1.1 200 OK +< content-type: application/json +< x-content-type-options: nosniff +< content-length: 474 +< x-envoy-upstream-service-time: 0 +< server: envoy +< + + "headers": { + "Accept": [ + "*/*" + ], + "Early-Added-Header": [ + "client", + "early", + "late" + ], + "Early-Set-Header": [ + "early", + "late" + ], + "Early-removed-Header": [ + "late" + ] +... +``` + [HTTPRoute]: https://gateway-api.sigs.k8s.io/api-types/httproute/ [HTTPRoute filters]: https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteFilter [Gateway API documentation]: https://gateway-api.sigs.k8s.io/ [req_filter]: https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPHeaderFilter +[ClientTrafficPolicy]: ../../../api/extension_types#clienttrafficpolicy diff --git a/site/content/en/latest/tasks/traffic/http-routing.md b/site/content/en/latest/tasks/traffic/http-routing.md index 705846c6ec9..0f1f3c688fb 100644 --- a/site/content/en/latest/tasks/traffic/http-routing.md +++ b/site/content/en/latest/tasks/traffic/http-routing.md @@ -140,10 +140,10 @@ kind: SecurityPolicy metadata: name: jwt-example spec: - targetRef: - group: gateway.networking.k8s.io - kind: HTTPRoute - name: jwt-claim-routing + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: jwt-claim-routing jwt: providers: - name: example @@ -208,10 +208,10 @@ kind: SecurityPolicy metadata: name: jwt-example spec: - targetRef: - group: gateway.networking.k8s.io - kind: HTTPRoute - name: jwt-claim-routing + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: jwt-claim-routing jwt: providers: - name: example diff --git a/site/content/en/latest/tasks/traffic/http3.md b/site/content/en/latest/tasks/traffic/http3.md index cb5034284c1..a0fb1594295 100644 --- a/site/content/en/latest/tasks/traffic/http3.md +++ b/site/content/en/latest/tasks/traffic/http3.md @@ -69,10 +69,10 @@ metadata: name: enable-http3 spec: http3: {} - targetRef: - group: gateway.networking.k8s.io - kind: Gateway - name: eg + targetRefs: + - group: gateway.networking.k8s.io + kind: Gateway + name: eg EOF ``` @@ -88,10 +88,10 @@ metadata: name: enable-http3 spec: http3: {} - targetRef: - group: gateway.networking.k8s.io - kind: Gateway - name: eg + targetRefs: + - group: gateway.networking.k8s.io + kind: Gateway + name: eg ``` {{% /tab %}} diff --git a/site/content/en/latest/tasks/traffic/load-balancing.md b/site/content/en/latest/tasks/traffic/load-balancing.md index b8bdff01af2..3c9a78450b5 100644 --- a/site/content/en/latest/tasks/traffic/load-balancing.md +++ b/site/content/en/latest/tasks/traffic/load-balancing.md @@ -13,7 +13,7 @@ Envoy Gateway supports the following load balancing policies: - **Consistent Hash**: load balancer implements consistent hashing to upstream hosts. Envoy Gateway introduces a new CRD called [BackendTrafficPolicy][] that allows the user to describe their desired load balancing polices. -This instantiated resource can be linked to a [Gateway][], [HTTPRoute][] or [GRPCRoute][] resource. +This instantiated resource can be linked to a [Gateway][], [HTTPRoute][] or [GRPCRoute][] resource. If `loadBalancer` is not specified in [BackendTrafficPolicy][], the default load balancing policy is `Least Request`. ## Prerequisites diff --git a/site/content/en/latest/tasks/traffic/local-rate-limit.md b/site/content/en/latest/tasks/traffic/local-rate-limit.md index a7b920db1c4..62e369044a5 100644 --- a/site/content/en/latest/tasks/traffic/local-rate-limit.md +++ b/site/content/en/latest/tasks/traffic/local-rate-limit.md @@ -43,8 +43,8 @@ kind: BackendTrafficPolicy metadata: name: policy-httproute spec: - targetRef: - group: gateway.networking.k8s.io + targetRefs: + - group: gateway.networking.k8s.io kind: HTTPRoute name: http-ratelimit rateLimit: @@ -72,8 +72,8 @@ kind: BackendTrafficPolicy metadata: name: policy-httproute spec: - targetRef: - group: gateway.networking.k8s.io + targetRefs: + - group: gateway.networking.k8s.io kind: HTTPRoute name: http-ratelimit rateLimit: @@ -259,8 +259,8 @@ kind: BackendTrafficPolicy metadata: name: policy-httproute spec: - targetRef: - group: gateway.networking.k8s.io + targetRefs: + - group: gateway.networking.k8s.io kind: HTTPRoute name: http-ratelimit rateLimit: @@ -284,8 +284,8 @@ kind: BackendTrafficPolicy metadata: name: policy-httproute spec: - targetRef: - group: gateway.networking.k8s.io + targetRefs: + - group: gateway.networking.k8s.io kind: HTTPRoute name: http-ratelimit rateLimit: diff --git a/site/content/en/latest/tasks/traffic/retry.md b/site/content/en/latest/tasks/traffic/retry.md index 25b7e2519ec..75d151bdff6 100644 --- a/site/content/en/latest/tasks/traffic/retry.md +++ b/site/content/en/latest/tasks/traffic/retry.md @@ -56,10 +56,10 @@ kind: BackendTrafficPolicy metadata: name: retry-for-route spec: - targetRef: - group: gateway.networking.k8s.io - kind: HTTPRoute - name: backend + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: backend retry: numRetries: 5 perRetry: @@ -87,10 +87,10 @@ kind: BackendTrafficPolicy metadata: name: retry-for-route spec: - targetRef: - group: gateway.networking.k8s.io - kind: HTTPRoute - name: backend + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: backend retry: numRetries: 5 perRetry: diff --git a/site/content/en/v1.0/tasks/security/backend-tls.md b/site/content/en/v1.0/tasks/security/backend-tls.md index 1f84ea4db81..5ba360e1d58 100644 --- a/site/content/en/v1.0/tasks/security/backend-tls.md +++ b/site/content/en/v1.0/tasks/security/backend-tls.md @@ -25,11 +25,30 @@ Create a root certificate and private key to sign certificates: openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout ca.key -out ca.crt ``` -Create a certificate and a private key for `www.example.com`: +Create a certificate and a private key for `www.example.com`. + +First, create an openssl configuration file: + +```shell +cat > openssl.conf <}} +{{% tab header="kubectl" %}} + +```shell +kubectl get gateway/eg -o yaml +``` + +{{% /tab %}} +{{% tab header="egctl (experimental)" %}} + +```shell +egctl x status gateway -v +``` + +{{% /tab %}} +{{< /tabpane >}} diff --git a/site/content/en/v1.1/concepts/concepts_overview.md b/site/content/en/v1.1/concepts/concepts_overview.md index 31838b520f2..9af9a3fff10 100644 --- a/site/content/en/v1.1/concepts/concepts_overview.md +++ b/site/content/en/v1.1/concepts/concepts_overview.md @@ -10,13 +10,12 @@ There are several resources that play a part in enabling you to meet your Kubern There are several resources that play a part in enabling you to meet your Kubernetes ingress traffic handling needs. This page provides a brief overview of the resources you’ll be working with. -# Overview - -## Kubernetes Gateway API Resources +### Kubernetes Gateway API Resources - **GatewayClass:** Defines a class of Gateways with common configuration. - **Gateway:** Specifies how traffic can enter the cluster. - **Routes:** **HTTPRoute, GRPCRoute, TLSRoute, TCPRoute, UDPRoute:** Define routing rules for different types of traffic. -## Envoy Gateway (EG) API Resources + +### Envoy Gateway (EG) API Resources - **EnvoyProxy:** Represents the deployment and configuration of the Envoy proxy within a Kubernetes cluster, managing its lifecycle and settings. - **EnvoyPatchPolicy, ClientTrafficPolicy, SecurityPolicy, BackendTrafficPolicy, EnvoyExtensionPolicy, BackendTLSPolicy:** Additional policies and configurations specific to Envoy Gateway. - **Backend:** A resource that makes routing to cluster-external backends easier and makes access to external processes via Unix Domain Sockets possible. diff --git a/site/content/en/v1.1/install/install-yaml.md b/site/content/en/v1.1/install/install-yaml.md index e675f15fbec..c0a8d1caa72 100644 --- a/site/content/en/v1.1/install/install-yaml.md +++ b/site/content/en/v1.1/install/install-yaml.md @@ -13,7 +13,7 @@ installation, it is recommended that you use helm. Envoy Gateway is designed to run in Kubernetes for production. The most essential requirements are: -* Kubernetes 1.25 or later +* Kubernetes 1.27 or later * The `kubectl` command-line tool {{% alert title="Compatibility Matrix" color="warning" %}} @@ -37,3 +37,31 @@ Refer to the [Developer Guide](../../contributions/develop) to learn more. 2. Next Steps Envoy Gateway should now be successfully installed and running, but in order to experience more abilities of Envoy Gateway, you can refer to [Tasks](/latest/tasks). + +## Upgrading from v1.0 + +Due to breaking changes in Gateway API v1.1, some manual migration steps are required to upgrade Envoy Gateway to v1.1. + +1. Delete `BackendTLSPolicy` CRD (and resources): + +```shell +kubectl delete crd backendtlspolicies.gateway.networking.k8s.io +``` + +2. Update Gateway-API and Envoy Gateway CRDs: + +```shell +helm pull oci://docker.io/envoyproxy/gateway-helm --version {{< yaml-version >}} --untar +kubectl apply --force-conflicts --server-side -f ./gateway-helm/crds/gatewayapi-crds.yaml +kubectl apply --force-conflicts --server-side -f ./gateway-helm/crds/generated +``` + +3. Update your `BackendTLSPolicy` and `GRPCRoute` resources according to Gateway-API [v1.1 Upgrade Notes](https://gateway-api.sigs.k8s.io/guides/#v11-upgrade-notes) + +4. Update your Envoy Gateway xPolicy resources: remove the namespace section from targetRef. + +5. Install Envoy Gateway {{< yaml-version >}}: + +```shell +helm upgrade eg oci://docker.io/envoyproxy/gateway-helm --version {{< yaml-version >}} -n envoy-gateway-system +``` diff --git a/site/content/en/v1.1/tasks/extensibility/envoy-patch-policy.md b/site/content/en/v1.1/tasks/extensibility/envoy-patch-policy.md index ff819754d1f..7fe84762189 100644 --- a/site/content/en/v1.1/tasks/extensibility/envoy-patch-policy.md +++ b/site/content/en/v1.1/tasks/extensibility/envoy-patch-policy.md @@ -111,7 +111,6 @@ spec: group: gateway.networking.k8s.io kind: Gateway name: eg - namespace: default type: JSONPatch jsonPatches: - type: "type.googleapis.com/envoy.config.listener.v3.Listener" @@ -151,7 +150,6 @@ spec: group: gateway.networking.k8s.io kind: Gateway name: eg - namespace: default type: JSONPatch jsonPatches: - type: "type.googleapis.com/envoy.config.listener.v3.Listener" @@ -195,7 +193,6 @@ spec: group: gateway.networking.k8s.io kind: GatewayClass name: eg - namespace: default type: JSONPatch jsonPatches: - type: "type.googleapis.com/envoy.config.listener.v3.Listener" @@ -235,7 +232,6 @@ spec: group: gateway.networking.k8s.io kind: GatewayClass name: eg - namespace: default type: JSONPatch jsonPatches: - type: "type.googleapis.com/envoy.config.listener.v3.Listener" @@ -322,7 +318,6 @@ spec: group: gateway.networking.k8s.io kind: Gateway name: eg - namespace: default type: JSONPatch status: conditions: diff --git a/site/content/en/v1.1/tasks/extensibility/ext-proc.md b/site/content/en/v1.1/tasks/extensibility/ext-proc.md index 9028447ab09..31ad551c63b 100644 --- a/site/content/en/v1.1/tasks/extensibility/ext-proc.md +++ b/site/content/en/v1.1/tasks/extensibility/ext-proc.md @@ -113,10 +113,10 @@ kind: EnvoyExtensionPolicy metadata: name: ext-proc-example spec: - targetRef: - group: gateway.networking.k8s.io - kind: HTTPRoute - name: myapp + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: myapp extProc: - backendRefs: - name: grpc-ext-proc @@ -139,10 +139,10 @@ kind: EnvoyExtensionPolicy metadata: name: ext-proc-example spec: - targetRef: - group: gateway.networking.k8s.io - kind: HTTPRoute - name: myapp + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: myapp extProc: - backendRefs: - name: grpc-ext-proc diff --git a/site/content/en/v1.1/tasks/extensibility/wasm.md b/site/content/en/v1.1/tasks/extensibility/wasm.md index d973de77950..cb2e013dd80 100644 --- a/site/content/en/v1.1/tasks/extensibility/wasm.md +++ b/site/content/en/v1.1/tasks/extensibility/wasm.md @@ -44,10 +44,10 @@ kind: EnvoyExtensionPolicy metadata: name: wasm-test spec: - targetRef: - group: gateway.networking.k8s.io - kind: HTTPRoute - name: backend + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: backend wasm: - name: wasm-filter rootID: my_root_id @@ -70,10 +70,10 @@ kind: EnvoyExtensionPolicy metadata: name: wasm-test spec: - targetRef: - group: gateway.networking.k8s.io - kind: HTTPRoute - name: backend + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: backend wasm: - name: wasm-filter rootID: my_root_id @@ -107,8 +107,8 @@ kind: EnvoyExtensionPolicy metadata: name: wasm-test spec: - targetRef: - group: gateway.networking.k8s.io + targetRefs: + - group: gateway.networking.k8s.io kind: HTTPRoute name: backend wasm: @@ -132,17 +132,17 @@ kind: EnvoyExtensionPolicy metadata: name: wasm-test spec: - targetRef: - group: gateway.networking.k8s.io + targetRefs: + - group: gateway.networking.k8s.io kind: HTTPRoute name: backend wasm: - - name: wasm-filter - rootID: my_root_id - code: - type: Image - image: - url: zhaohuabing/testwasm:v0.0.1 + - name: wasm-filter + rootID: my_root_id + code: + type: Image + image: + url: zhaohuabing/testwasm:v0.0.1 ``` {{% /tab %}} diff --git a/site/content/en/v1.1/tasks/operations/customize-envoyproxy.md b/site/content/en/v1.1/tasks/operations/customize-envoyproxy.md index 562237bfc43..892c3496ff0 100644 --- a/site/content/en/v1.1/tasks/operations/customize-envoyproxy.md +++ b/site/content/en/v1.1/tasks/operations/customize-envoyproxy.md @@ -3,15 +3,68 @@ title: "Customize EnvoyProxy" --- Envoy Gateway provides an [EnvoyProxy][] CRD that can be linked to the ParametersRef -in GatewayClass, allowing cluster admins to customize the managed EnvoyProxy Deployment and +in a Gateway and GatewayClass, allowing cluster admins to customize the managed EnvoyProxy Deployment and Service. To learn more about GatewayClass and ParametersRef, please refer to [Gateway API documentation][]. ## Prerequisites -Follow the steps from the [Quickstart](../../quickstart) to install Envoy Gateway and the example manifest. -Before proceeding, you should be able to query the example backend using HTTP. +{{< boilerplate prerequisites >}} -Before you start, you need to add `ParametersRef` in GatewayClass, and refer to EnvoyProxy Config: +Before you start, you need to add `Infrastructure.ParametersRef` in Gateway, and refer to EnvoyProxy Config: +**Note**: `MergeGateways` cannot be set to `true` in your EnvoyProxy config if attaching to the Gateway. + +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + +```shell +cat <}} + +You can also attach the EnvoyProxy resource to the GatewayClass using the `parametersRef` field. +This configuration is discouraged if you plan on creating multiple Gateways linking to the same +GatewayClass and would like different infrastructure configurations for each of them. {{< tabpane text=true >}} {{% tab header="Apply from stdin" %}} @@ -28,7 +81,7 @@ spec: group: gateway.envoyproxy.io kind: EnvoyProxy name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default EOF ``` @@ -48,7 +101,7 @@ spec: group: gateway.envoyproxy.io kind: EnvoyProxy name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default ``` {{% /tab %}} @@ -67,7 +120,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -87,7 +140,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -119,7 +172,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -140,7 +193,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -168,7 +221,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -191,7 +244,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -221,7 +274,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -248,7 +301,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -280,7 +333,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -305,7 +358,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -339,7 +392,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -368,7 +421,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -404,7 +457,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -426,7 +479,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -459,7 +512,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: bootstrap: type: Replace @@ -547,7 +600,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: bootstrap: type: Replace @@ -649,7 +702,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -677,7 +730,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -713,7 +766,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: extraArgs: - --disable-extensions envoy.access_loggers/envoy.access_loggers.wasm @@ -730,7 +783,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: extraArgs: - --disable-extensions envoy.access_loggers/envoy.access_loggers.wasm @@ -756,7 +809,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: eg - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -792,7 +845,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: eg - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -835,7 +888,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: eg - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -860,7 +913,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: eg - namespace: envoy-gateway-system + namespace: default spec: provider: type: Kubernetes @@ -918,7 +971,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: filterOrder: - name: envoy.filters.http.wasm @@ -938,7 +991,7 @@ apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: custom-proxy-config - namespace: envoy-gateway-system + namespace: default spec: filterOrder: - name: envoy.filters.http.wasm diff --git a/site/content/en/v1.1/tasks/quickstart.md b/site/content/en/v1.1/tasks/quickstart.md index 03d7b6de842..802b7989a88 100644 --- a/site/content/en/v1.1/tasks/quickstart.md +++ b/site/content/en/v1.1/tasks/quickstart.md @@ -92,34 +92,6 @@ curl --verbose --header "Host: www.example.com" http://localhost:8888/get {{% /tab %}} {{< /tabpane >}} -## v1.1 Upgrade Notes - -Due to breaking changes in the Gateway API v1.1, some manual migration steps are required to upgrade Envoy Gateway to v1.1. - -Delete `BackendTLSPolicy` CRD (and resources): - -```shell -kubectl delete crd backendtlspolicies.gateway.networking.k8s.io -``` - -Update Gateway-API and Envoy Gateway CRDs: - -```shell -helm pull oci://docker.io/envoyproxy/gateway-helm --version v1.1.0 --untar -kubectl apply -f ./gateway-helm/crds/gatewayapi-crds.yaml -kubectl apply -f ./gateway-helm/crds/generated -``` - -Update your `BackendTLSPolicy` and `GRPCRoute` resources according to Gateway-API [v1.1 Upgrade Notes](https://gateway-api.sigs.k8s.io/guides/#v11-upgrade-notes) - -Update your Envoy Gateway xPolicy resources: remove the namespace section from targetRef. - -Install Envoy Gateway v1.1.0: - -```shell -helm upgrade eg oci://docker.io/envoyproxy/gateway-helm --version v1.1.0 -n envoy-gateway-system -``` - ## What to explore next? In this quickstart, you have: diff --git a/site/content/en/v1.1/tasks/security/backend-tls.md b/site/content/en/v1.1/tasks/security/backend-tls.md index 53e9ccbd44a..3aadbc34714 100644 --- a/site/content/en/v1.1/tasks/security/backend-tls.md +++ b/site/content/en/v1.1/tasks/security/backend-tls.md @@ -25,11 +25,30 @@ Create a root certificate and private key to sign certificates: openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout ca.key -out ca.crt ``` -Create a certificate and a private key for `www.example.com`: +Create a certificate and a private key for `www.example.com`. + +First, create an openssl configuration file: + +```shell +cat > openssl.conf <the access logs will be sent. Currently only Service is supported. | +| `backendRef` | _[BackendObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.BackendObjectReference)_ | false | BackendRef references a Kubernetes object that represents the
backend server to which the authorization request will be sent.

Deprecated: Use BackendRefs instead. | +| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs references a Kubernetes object that represents the
backend server to which the authorization request will be sent. | +| `backendSettings` | _[ClusterSettings](#clustersettings)_ | false | BackendSettings holds configuration for managing the connection
to the backend. | | `logName` | _string_ | false | LogName defines the friendly name of the access log to be returned in
StreamAccessLogsMessage.Identifier. This allows the access log server
to differentiate between different access logs coming from the same Envoy. | | `type` | _[ALSEnvoyProxyAccessLogType](#alsenvoyproxyaccesslogtype)_ | true | Type defines the type of accesslog. Supported types are "HTTP" and "TCP". | | `http` | _[ALSEnvoyProxyHTTPAccessLogConfig](#alsenvoyproxyhttpaccesslogconfig)_ | false | HTTP defines additional configuration specific to HTTP access logs. | @@ -124,6 +126,7 @@ _Appears in:_ | `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. | +| `grpc` | _[GRPCActiveHealthChecker](#grpcactivehealthchecker)_ | false | GRPC defines the configuration of the GRPC health checker.
It's optional, and can only be used if the specified type is GRPC. | #### ActiveHealthCheckPayload @@ -171,6 +174,7 @@ _Appears in:_ | ----- | ----------- | | `HTTP` | ActiveHealthCheckerTypeHTTP defines the HTTP type of health checking.
| | `TCP` | ActiveHealthCheckerTypeTCP defines the TCP type of health checking.
| +| `GRPC` | ActiveHealthCheckerTypeGRPC defines the GRPC type of health checking.
| #### AppProtocolType @@ -273,22 +277,34 @@ _Appears in:_ | `status` | _[BackendStatus](#backendstatus)_ | true | Status defines the current status of Backend. | +#### BackendCluster +BackendCluster contains all the configuration required for configuring access +to a backend. This can include multiple endpoints, and settings that apply for +managing the connection to all these endpoints. + +_Appears in:_ +- [ALSEnvoyProxyAccessLog](#alsenvoyproxyaccesslog) +- [ExtProc](#extproc) +- [GRPCExtAuthService](#grpcextauthservice) +- [HTTPExtAuthService](#httpextauthservice) +- [OpenTelemetryEnvoyProxyAccessLog](#opentelemetryenvoyproxyaccesslog) +- [ProxyOpenTelemetrySink](#proxyopentelemetrysink) +- [TracingProvider](#tracingprovider) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `backendRef` | _[BackendObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.BackendObjectReference)_ | false | BackendRef references a Kubernetes object that represents the
backend server to which the authorization request will be sent.

Deprecated: Use BackendRefs instead. | +| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs references a Kubernetes object that represents the
backend server to which the authorization request will be sent. | +| `backendSettings` | _[ClusterSettings](#clustersettings)_ | false | BackendSettings holds configuration for managing the connection
to the backend. | -#### BackendConnection -BackendConnection allows users to configure connection-level settings of backend -_Appears in:_ -- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `bufferLimit` | _[Quantity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#quantity-resource-api)_ | false | BufferLimit Soft limit on size of the cluster’s connections read and write buffers.
BufferLimit applies to connection streaming (maybe non-streaming) channel between processes, it's in user space.
If unspecified, an implementation defined default is applied (32768 bytes).
For example, 20Mi, 1Gi, 256Ki etc.
Note: that when the suffix is not provided, the value is interpreted as bytes. | #### BackendEndpoint @@ -333,6 +349,7 @@ BackendRef defines how an ObjectReference that is specific to BackendRef. _Appears in:_ - [ALSEnvoyProxyAccessLog](#alsenvoyproxyaccesslog) +- [BackendCluster](#backendcluster) - [ExtProc](#extproc) - [GRPCExtAuthService](#grpcextauthservice) - [HTTPExtAuthService](#httpextauthservice) @@ -347,6 +364,7 @@ _Appears in:_ | `name` | _[ObjectName](#objectname)_ | true | Name is the name of the referent. | | `namespace` | _[Namespace](#namespace)_ | false | Namespace is the namespace of the backend. When unspecified, the local
namespace is inferred.

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.

Support: Core | | `port` | _[PortNumber](#portnumber)_ | false | 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. | +| `failover` | _boolean_ | false | Failover This indicates whether the backend is designated as a failover.
Multiple failover backends can be configured.
It is highly recommended to configure active or passive health checks to ensure that failover can be detected
when the active backends become unhealthy and to automatically readjust once the primary backends are healthy again.
The overprovisioning factor is set to 1.4, meaning the failover backends will only start receiving traffic when
the health of the active backends falls below 72%. | #### BackendSpec @@ -447,19 +465,19 @@ _Appears in:_ | `targetRef` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName)_ | 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

Deprecated: use targetRefs/targetSelectors instead | | `targetRefs` | _[LocalPolicyTargetReferenceWithSectionName](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1alpha2.LocalPolicyTargetReferenceWithSectionName) array_ | true | TargetRefs are the names of the Gateway resources this policy
is being attached to. | | `targetSelectors` | _[TargetSelector](#targetselector) array_ | true | TargetSelectors allow targeting resources for this policy based on labels | -| `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 | +| `loadBalancer` | _[LoadBalancer](#loadbalancer)_ | false | LoadBalancer policy to apply when routing traffic from the gateway to
the backend endpoints. Defaults to `LeastRequest`. | | `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. | -| `useClientProtocol` | _boolean_ | false | UseClientProtocol configures Envoy to prefer sending requests to backends using
the same HTTP protocol that the incoming request used. Defaults to false, which means
that Envoy will use the protocol indicated by the attached BackendRef. | | `timeout` | _[Timeout](#timeout)_ | false | Timeout settings for the backend connections. | | `connection` | _[BackendConnection](#backendconnection)_ | false | Connection includes backend connection settings. | | `dns` | _[DNS](#dns)_ | false | DNS includes dns resolution settings. | | `http2` | _[HTTP2Settings](#http2settings)_ | false | HTTP2 provides HTTP/2 configuration for backend connections. | +| `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. | +| `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 | +| `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. | +| `useClientProtocol` | _boolean_ | false | UseClientProtocol configures Envoy to prefer sending requests to backends using
the same HTTP protocol that the incoming request used. Defaults to false, which means
that Envoy will use the protocol indicated by the attached BackendRef. | #### BasicAuth @@ -522,22 +540,6 @@ _Appears in:_ | `allowCredentials` | _boolean_ | true | AllowCredentials indicates whether a request can include user credentials
like cookies, authentication headers, or TLS client certificates. | -#### CircuitBreaker - - - -CircuitBreaker defines the Circuit Breaker configuration. - -_Appears in:_ -- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) - -| 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. | -| `maxParallelRetries` | _integer_ | false | The maximum number of parallel retries 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 @@ -700,6 +702,37 @@ _Appears in:_ | `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. | +#### ClusterSettings + + + +ClusterSettings provides the various knobs that can be set to control how traffic to a given +backend will be configured. + +_Appears in:_ +- [ALSEnvoyProxyAccessLog](#alsenvoyproxyaccesslog) +- [BackendCluster](#backendcluster) +- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) +- [ExtProc](#extproc) +- [GRPCExtAuthService](#grpcextauthservice) +- [HTTPExtAuthService](#httpextauthservice) +- [OpenTelemetryEnvoyProxyAccessLog](#opentelemetryenvoyproxyaccesslog) +- [ProxyOpenTelemetrySink](#proxyopentelemetrysink) +- [TracingProvider](#tracingprovider) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `loadBalancer` | _[LoadBalancer](#loadbalancer)_ | false | LoadBalancer policy to apply when routing traffic from the gateway to
the backend endpoints. Defaults to `LeastRequest`. | +| `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. | +| `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 | +| `timeout` | _[Timeout](#timeout)_ | false | Timeout settings for the backend connections. | +| `connection` | _[BackendConnection](#backendconnection)_ | false | Connection includes backend connection settings. | +| `dns` | _[DNS](#dns)_ | false | DNS includes dns resolution settings. | +| `http2` | _[HTTP2Settings](#http2settings)_ | false | HTTP2 provides HTTP/2 configuration for backend connections. | + + #### Compression @@ -845,19 +878,6 @@ _Appears in:_ | `RequestHeader` | CustomTagTypeRequestHeader adds value from request header to each span.
| -#### DNS - - - - - -_Appears in:_ -- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `dnsRefreshRate` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | true | DNSRefreshRate specifies the rate at which DNS records should be refreshed.
Defaults to 30 seconds. | -| `respectDnsTtl` | _boolean_ | true | RespectDNSTTL indicates whether the DNS Time-To-Live (TTL) should be respected.
If the value is set to true, the DNS refresh rate will be set to the resource record’s TTL.
Defaults to true. | #### EnvironmentCustomTag @@ -945,6 +965,7 @@ _Appears in:_ | `envoy.filters.http.basic_auth` | EnvoyFilterBasicAuth defines the Envoy HTTP basic authentication filter.
| | `envoy.filters.http.oauth2` | EnvoyFilterOAuth2 defines the Envoy HTTP OAuth2 filter.
| | `envoy.filters.http.jwt_authn` | EnvoyFilterJWTAuthn defines the Envoy HTTP JWT authentication filter.
| +| `envoy.filters.http.stateful_session` | EnvoyFilterSessionPersistence defines the Envoy HTTP session persistence filter.
| | `envoy.filters.http.ext_proc` | EnvoyFilterExtProc defines the Envoy HTTP external process filter.
| | `envoy.filters.http.wasm` | EnvoyFilterWasm defines the Envoy HTTP WebAssembly filter.
| | `envoy.filters.http.rbac` | EnvoyFilterRBAC defines the Envoy RBAC filter.
| @@ -1403,7 +1424,7 @@ _Appears in:_ | `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. | | `shutdown` | _[ShutdownConfig](#shutdownconfig)_ | false | Shutdown defines configuration for graceful envoy shutdown process. | -| `filterOrder` | _[FilterPosition](#filterposition) array_ | false | FilterOrder defines the order of filters in the Envoy proxy's HTTP filter chain.
The FilterPosition in the list will be applied in the order they are defined.
If unspecified, the default filter order is applied.
Default filter order is:

- envoy.filters.http.health_check

- envoy.filters.http.fault

- envoy.filters.http.cors

- envoy.filters.http.ext_authz

- envoy.filters.http.basic_auth

- envoy.filters.http.oauth2

- envoy.filters.http.jwt_authn

- envoy.filters.http.ext_proc

- envoy.filters.http.wasm

- envoy.filters.http.rbac

- envoy.filters.http.local_ratelimit

- envoy.filters.http.ratelimit

- envoy.filters.http.router

Note: "envoy.filters.http.router" cannot be reordered, it's always the last filter in the chain. | +| `filterOrder` | _[FilterPosition](#filterposition) array_ | false | FilterOrder defines the order of filters in the Envoy proxy's HTTP filter chain.
The FilterPosition in the list will be applied in the order they are defined.
If unspecified, the default filter order is applied.
Default filter order is:

- envoy.filters.http.health_check

- envoy.filters.http.fault

- envoy.filters.http.cors

- envoy.filters.http.ext_authz

- envoy.filters.http.basic_auth

- envoy.filters.http.oauth2

- envoy.filters.http.jwt_authn

- envoy.filters.http.stateful_session

- envoy.filters.http.ext_proc

- envoy.filters.http.wasm

- envoy.filters.http.rbac

- envoy.filters.http.local_ratelimit

- envoy.filters.http.ratelimit

- envoy.filters.http.router

Note: "envoy.filters.http.router" cannot be reordered, it's always the last filter in the chain. | | `backendTLS` | _[BackendTLSConfig](#backendtlsconfig)_ | false | BackendTLS is the TLS configuration for the Envoy proxy to use when connecting to backends.
These settings are applied on backends for which TLS policies are specified. | @@ -1464,7 +1485,9 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | -| `backendRefs` | _[BackendRef](#backendref) array_ | true | BackendRefs defines the configuration of the external processing service | +| `backendRef` | _[BackendObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.BackendObjectReference)_ | false | BackendRef references a Kubernetes object that represents the
backend server to which the authorization request will be sent.

Deprecated: Use BackendRefs instead. | +| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs references a Kubernetes object that represents the
backend server to which the authorization request will be sent. | +| `backendSettings` | _[ClusterSettings](#clustersettings)_ | false | BackendSettings holds configuration for managing the connection
to the backend. | | `messageTimeout` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ | false | MessageTimeout is the timeout for a response to be returned from the external processor
Default: 200ms | | `failOpen` | _boolean_ | false | FailOpen defines if requests or responses that cannot be processed due to connectivity to the
external processor are terminated or passed-through.
Default: false | | `processingMode` | _[ExtProcProcessingMode](#extprocprocessingmode)_ | false | ProcessingMode defines how request and response body is processed
Default: header and body are not sent to the external processor | @@ -1678,6 +1701,20 @@ _Appears in:_ | `after` | _[EnvoyFilter](#envoyfilter)_ | true | After defines the filter that should come after the filter.
Only one of Before or After must be set. | +#### GRPCActiveHealthChecker + + + +GRPCActiveHealthChecker defines the settings of the GRPC health check. + +_Appears in:_ +- [ActiveHealthCheck](#activehealthcheck) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `service` | _string_ | false | Service to send in the health check request.
If this is not specified, then the health check request applies to the entire
server and not to a specific service. | + + #### GRPCExtAuthService @@ -1691,8 +1728,9 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | -| `backendRef` | _[BackendObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.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.

Deprecated: Use BackendRefs instead. | -| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs 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` | _[BackendObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.BackendObjectReference)_ | false | BackendRef references a Kubernetes object that represents the
backend server to which the authorization request will be sent.

Deprecated: Use BackendRefs instead. | +| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs references a Kubernetes object that represents the
backend server to which the authorization request will be sent. | +| `backendSettings` | _[ClusterSettings](#clustersettings)_ | false | BackendSettings holds configuration for managing the connection
to the backend. | #### Gateway @@ -1784,22 +1822,6 @@ _Appears in:_ | `http10` | _[HTTP10Settings](#http10settings)_ | false | HTTP10 turns on support for HTTP/1.0 and HTTP/0.9 requests. | -#### HTTP2Settings - - - -HTTP2Settings provides HTTP/2 configuration for listeners and backends. - -_Appears in:_ -- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) -- [ClientTrafficPolicySpec](#clienttrafficpolicyspec) - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `initialStreamWindowSize` | _[Quantity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#quantity-resource-api)_ | false | InitialStreamWindowSize sets the initial window size for HTTP/2 streams.
If not set, the default value is 64 KiB(64*1024). | -| `initialConnectionWindowSize` | _[Quantity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#quantity-resource-api)_ | false | InitialConnectionWindowSize sets the initial window size for HTTP/2 connections.
If not set, the default value is 1 MiB. | -| `maxConcurrentStreams` | _integer_ | false | MaxConcurrentStreams sets the maximum number of concurrent streams allowed per connection.
If not set, the default value is 100. | -| `onInvalidMessage` | _[InvalidMessageAction](#invalidmessageaction)_ | false | OnInvalidMessage determines if Envoy will terminate the connection or just the offending stream in the event of HTTP messaging error
It's recommended for L2 Envoy deployments to set this value to TerminateStream.
https://www.envoyproxy.io/docs/envoy/latest/configuration/best_practices/level_two
Default: TerminateConnection | #### HTTP3Settings @@ -1856,8 +1878,9 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | -| `backendRef` | _[BackendObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.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.

Deprecated: Use BackendRefs instead. | -| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs 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` | _[BackendObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.BackendObjectReference)_ | false | BackendRef references a Kubernetes object that represents the
backend server to which the authorization request will be sent.

Deprecated: Use BackendRefs instead. | +| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs references a Kubernetes object that represents the
backend server to which the authorization request will be sent. | +| `backendSettings` | _[ClusterSettings](#clustersettings)_ | false | BackendSettings holds configuration for managing the connection
to the backend. | | `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. | @@ -1954,22 +1977,9 @@ _Appears in:_ | `xForwardedClientCert` | _[XForwardedClientCert](#xforwardedclientcert)_ | false | XForwardedClientCert configures how Envoy Proxy handle the x-forwarded-client-cert (XFCC) HTTP header.

x-forwarded-client-cert (XFCC) is an HTTP header used to forward the certificate
information of part or all of the clients or proxies that a request has flowed through,
on its way from the client to the server.

Envoy proxy may choose to sanitize/append/forward the XFCC header before proxying the request.

If not set, the default behavior is sanitizing the XFCC header. | | `withUnderscoresAction` | _[WithUnderscoresAction](#withunderscoresaction)_ | false | WithUnderscoresAction configures the action to take when an HTTP header with underscores
is encountered. The default action is to reject the request. | | `preserveXRequestID` | _boolean_ | false | PreserveXRequestID configures Envoy to keep the X-Request-ID header if passed for a request that is edge
(Edge request is the request from external clients to front Envoy) and not reset it, which is the current Envoy behaviour.
It defaults to false. | +| `earlyRequestHeaders` | _[HTTPHeaderFilter](#httpheaderfilter)_ | false | EarlyRequestHeaders defines settings for early request header modification, before envoy performs
routing, tracing and built-in header manipulation. | -#### HealthCheck - - - -HealthCheck configuration to decide which endpoints -are healthy and can be used for routing. - -_Appears in:_ -- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `active` | _[ActiveHealthCheck](#activehealthcheck)_ | false | Active health check configuration | -| `passive` | _[PassiveHealthCheck](#passivehealthcheck)_ | false | Passive passive check configuration | #### HealthCheckSettings @@ -2076,7 +2086,8 @@ _Appears in:_ | 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. | +| `path` | _string_ | false | 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. | +| `jsonPath` | _string_ | false | JSONPath specifies the locations of the target document/field where the operation will be performed
Refer to https://datatracker.ietf.org/doc/rfc9535/ 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](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#json-v1-apiextensions-k8s-io)_ | false | Value is the new value of the path location. The value is only used by
the `add` and `replace` operations. | @@ -2384,20 +2395,6 @@ _Appears in:_ | `value` | _string_ | true | Value defines the hard-coded value to add to each span. | -#### LoadBalancer - - - -LoadBalancer defines the load balancer policy to be applied. - -_Appears in:_ -- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) - -| 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 @@ -2533,9 +2530,11 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | +| `backendRef` | _[BackendObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.BackendObjectReference)_ | false | BackendRef references a Kubernetes object that represents the
backend server to which the authorization request will be sent.

Deprecated: Use BackendRefs instead. | +| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs references a Kubernetes object that represents the
backend server to which the authorization request will be sent. | +| `backendSettings` | _[ClusterSettings](#clustersettings)_ | false | BackendSettings holds configuration for managing the connection
to the backend. | | `host` | _string_ | false | Host define the extension service hostname.
Deprecated: Use BackendRefs instead. | | `port` | _integer_ | false | Port defines the port the extension service is exposed on.
Deprecated: Use BackendRefs instead. | -| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs references a Kubernetes object that represents the
backend server to which the access log will be sent.
Only Service kind is supported for now. | | `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/). | @@ -2890,9 +2889,11 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | +| `backendRef` | _[BackendObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.BackendObjectReference)_ | false | BackendRef references a Kubernetes object that represents the
backend server to which the authorization request will be sent.

Deprecated: Use BackendRefs instead. | +| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs references a Kubernetes object that represents the
backend server to which the authorization request will be sent. | +| `backendSettings` | _[ClusterSettings](#clustersettings)_ | false | BackendSettings holds configuration for managing the connection
to the backend. | | `host` | _string_ | false | Host define the service hostname.
Deprecated: Use BackendRefs instead. | | `port` | _integer_ | false | Port defines the port the service is exposed on.
Deprecated: Use BackendRefs instead. | -| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs references a Kubernetes object that represents the
backend server to which the metric will be sent.
Only Service kind is supported for now. | #### ProxyPrometheusProvider @@ -2910,19 +2911,6 @@ _Appears in:_ | `compression` | _[Compression](#compression)_ | false | Configure the compression on Prometheus endpoint. Compression is useful in situations when bandwidth is scarce and large payloads can be effectively compressed at the expense of higher CPU load. | -#### ProxyProtocol - - - -ProxyProtocol defines the configuration related to the proxy protocol -when communicating with the backend. - -_Appears in:_ -- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) - -| Field | Type | Required | Description | -| --- | --- | --- | --- | -| `version` | _[ProxyProtocolVersion](#proxyprotocolversion)_ | true | Version of ProxyProtol
Valid ProxyProtocolVersion values are
"V1"
"V2" | #### ProxyProtocolVersion @@ -3528,21 +3516,6 @@ _Appears in:_ | `idleTimeout` | _[Duration](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ | false | IdleTimeout for a TCP connection. Idle time is defined as a period in which there are no
bytes sent or received on either the upstream or downstream connection.
Default: 1 hour. | -#### TCPKeepalive - - - -TCPKeepalive define the TCP Keepalive configuration. - -_Appears in:_ -- [BackendTrafficPolicySpec](#backendtrafficpolicyspec) -- [ClientTrafficPolicySpec](#clienttrafficpolicyspec) - -| 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](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.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](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.Duration)_ | false | The duration between keep-alive probes.
Defaults to `75s`. | #### TCPTimeout @@ -3619,19 +3592,6 @@ _Appears in:_ | `matchLabels` | _object (keys:string, values:string)_ | true | MatchLabels are the set of label selectors for identifying the targeted resource | -#### 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 @@ -3645,10 +3605,12 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | +| `backendRef` | _[BackendObjectReference](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.BackendObjectReference)_ | false | BackendRef references a Kubernetes object that represents the
backend server to which the authorization request will be sent.

Deprecated: Use BackendRefs instead. | +| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs references a Kubernetes object that represents the
backend server to which the authorization request will be sent. | +| `backendSettings` | _[ClusterSettings](#clustersettings)_ | false | BackendSettings holds configuration for managing the connection
to the backend. | | `type` | _[TracingProviderType](#tracingprovidertype)_ | true | Type defines the tracing provider type. | | `host` | _string_ | false | Host define the provider service hostname.
Deprecated: Use BackendRefs instead. | | `port` | _integer_ | false | Port defines the port the provider service is exposed on.
Deprecated: Use BackendRefs instead. | -| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs references a Kubernetes object that represents the
backend server to which the trace will be sent.
Only Service kind is supported for now. | | `zipkin` | _[ZipkinTracingProvider](#zipkintracingprovider)_ | false | Zipkin defines the Zipkin tracing provider configuration | diff --git a/test/cel-validation/backendtrafficpolicy_test.go b/test/cel-validation/backendtrafficpolicy_test.go index 903d3fa19f1..2755295336d 100644 --- a/test/cel-validation/backendtrafficpolicy_test.go +++ b/test/cel-validation/backendtrafficpolicy_test.go @@ -197,10 +197,12 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - LoadBalancer: &egv1a1.LoadBalancer{ - Type: egv1a1.ConsistentHashLoadBalancerType, - ConsistentHash: &egv1a1.ConsistentHash{ - Type: "SourceIP", + ClusterSettings: egv1a1.ClusterSettings{ + LoadBalancer: &egv1a1.LoadBalancer{ + Type: egv1a1.ConsistentHashLoadBalancerType, + ConsistentHash: &egv1a1.ConsistentHash{ + Type: "SourceIP", + }, }, }, } @@ -220,8 +222,10 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - LoadBalancer: &egv1a1.LoadBalancer{ - Type: egv1a1.ConsistentHashLoadBalancerType, + ClusterSettings: egv1a1.ClusterSettings{ + LoadBalancer: &egv1a1.LoadBalancer{ + Type: egv1a1.ConsistentHashLoadBalancerType, + }, }, } }, @@ -242,12 +246,14 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - LoadBalancer: &egv1a1.LoadBalancer{ - Type: egv1a1.ConsistentHashLoadBalancerType, - ConsistentHash: &egv1a1.ConsistentHash{ - Type: "Header", - Header: &egv1a1.Header{ - Name: "name", + ClusterSettings: egv1a1.ClusterSettings{ + LoadBalancer: &egv1a1.LoadBalancer{ + Type: egv1a1.ConsistentHashLoadBalancerType, + ConsistentHash: &egv1a1.ConsistentHash{ + Type: "Header", + Header: &egv1a1.Header{ + Name: "name", + }, }, }, }, @@ -268,10 +274,12 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - LoadBalancer: &egv1a1.LoadBalancer{ - Type: egv1a1.ConsistentHashLoadBalancerType, - ConsistentHash: &egv1a1.ConsistentHash{ - Type: "Header", + ClusterSettings: egv1a1.ClusterSettings{ + LoadBalancer: &egv1a1.LoadBalancer{ + Type: egv1a1.ConsistentHashLoadBalancerType, + ConsistentHash: &egv1a1.ConsistentHash{ + Type: "Header", + }, }, }, } @@ -293,12 +301,14 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - LoadBalancer: &egv1a1.LoadBalancer{ - Type: egv1a1.ConsistentHashLoadBalancerType, - ConsistentHash: &egv1a1.ConsistentHash{ - Type: "Cookie", - Cookie: &egv1a1.Cookie{ - Name: "name", + ClusterSettings: egv1a1.ClusterSettings{ + LoadBalancer: &egv1a1.LoadBalancer{ + Type: egv1a1.ConsistentHashLoadBalancerType, + ConsistentHash: &egv1a1.ConsistentHash{ + Type: "Cookie", + Cookie: &egv1a1.Cookie{ + Name: "name", + }, }, }, }, @@ -319,10 +329,12 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - LoadBalancer: &egv1a1.LoadBalancer{ - Type: egv1a1.ConsistentHashLoadBalancerType, - ConsistentHash: &egv1a1.ConsistentHash{ - Type: "Cookie", + ClusterSettings: egv1a1.ClusterSettings{ + LoadBalancer: &egv1a1.LoadBalancer{ + Type: egv1a1.ConsistentHashLoadBalancerType, + ConsistentHash: &egv1a1.ConsistentHash{ + Type: "Cookie", + }, }, }, } @@ -345,8 +357,10 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - LoadBalancer: &egv1a1.LoadBalancer{ - Type: egv1a1.LeastRequestLoadBalancerType, + ClusterSettings: egv1a1.ClusterSettings{ + LoadBalancer: &egv1a1.LoadBalancer{ + Type: egv1a1.LeastRequestLoadBalancerType, + }, }, } }, @@ -365,11 +379,13 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - LoadBalancer: &egv1a1.LoadBalancer{ - Type: egv1a1.LeastRequestLoadBalancerType, - SlowStart: &egv1a1.SlowStart{ - Window: &metav1.Duration{ - Duration: 10000000, + ClusterSettings: egv1a1.ClusterSettings{ + LoadBalancer: &egv1a1.LoadBalancer{ + Type: egv1a1.LeastRequestLoadBalancerType, + SlowStart: &egv1a1.SlowStart{ + Window: &metav1.Duration{ + Duration: 10000000, + }, }, }, }, @@ -390,11 +406,13 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - LoadBalancer: &egv1a1.LoadBalancer{ - Type: egv1a1.RoundRobinLoadBalancerType, - SlowStart: &egv1a1.SlowStart{ - Window: &metav1.Duration{ - Duration: 10000000, + ClusterSettings: egv1a1.ClusterSettings{ + LoadBalancer: &egv1a1.LoadBalancer{ + Type: egv1a1.RoundRobinLoadBalancerType, + SlowStart: &egv1a1.SlowStart{ + Window: &metav1.Duration{ + Duration: 10000000, + }, }, }, }, @@ -415,11 +433,13 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - LoadBalancer: &egv1a1.LoadBalancer{ - Type: egv1a1.RandomLoadBalancerType, - SlowStart: &egv1a1.SlowStart{ - Window: &metav1.Duration{ - Duration: 10000000, + ClusterSettings: egv1a1.ClusterSettings{ + LoadBalancer: &egv1a1.LoadBalancer{ + Type: egv1a1.RandomLoadBalancerType, + SlowStart: &egv1a1.SlowStart{ + Window: &metav1.Duration{ + Duration: 10000000, + }, }, }, }, @@ -442,11 +462,13 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - LoadBalancer: &egv1a1.LoadBalancer{ - Type: egv1a1.ConsistentHashLoadBalancerType, - SlowStart: &egv1a1.SlowStart{ - Window: &metav1.Duration{ - Duration: 10000000, + ClusterSettings: egv1a1.ClusterSettings{ + LoadBalancer: &egv1a1.LoadBalancer{ + Type: egv1a1.ConsistentHashLoadBalancerType, + SlowStart: &egv1a1.SlowStart{ + Window: &metav1.Duration{ + Duration: 10000000, + }, }, }, }, @@ -606,11 +628,13 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - CircuitBreaker: &egv1a1.CircuitBreaker{ - MaxConnections: valMax, - MaxPendingRequests: valMin, - MaxParallelRequests: nil, - MaxParallelRetries: nil, + ClusterSettings: egv1a1.ClusterSettings{ + CircuitBreaker: &egv1a1.CircuitBreaker{ + MaxConnections: valMax, + MaxPendingRequests: valMin, + MaxParallelRequests: nil, + MaxParallelRetries: nil, + }, }, } }, @@ -631,12 +655,14 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - CircuitBreaker: &egv1a1.CircuitBreaker{ - MaxConnections: valOverMax, - MaxPendingRequests: valUnderMin, - MaxParallelRequests: valOverMax, - MaxRequestsPerConnection: valUnderMin, - MaxParallelRetries: valOverMax, + ClusterSettings: egv1a1.ClusterSettings{ + CircuitBreaker: &egv1a1.CircuitBreaker{ + MaxConnections: valOverMax, + MaxPendingRequests: valUnderMin, + MaxParallelRequests: valOverMax, + MaxRequestsPerConnection: valUnderMin, + MaxParallelRetries: valOverMax, + }, }, } }, @@ -661,11 +687,13 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - HealthCheck: &egv1a1.HealthCheck{ - Active: &egv1a1.ActiveHealthCheck{ - Type: egv1a1.ActiveHealthCheckerTypeHTTP, - HTTP: &egv1a1.HTTPActiveHealthChecker{ - Path: "", + ClusterSettings: egv1a1.ClusterSettings{ + HealthCheck: &egv1a1.HealthCheck{ + Active: &egv1a1.ActiveHealthCheck{ + Type: egv1a1.ActiveHealthCheckerTypeHTTP, + HTTP: &egv1a1.HTTPActiveHealthChecker{ + Path: "", + }, }, }, }, @@ -688,12 +716,14 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - HealthCheck: &egv1a1.HealthCheck{ - Active: &egv1a1.ActiveHealthCheck{ - UnhealthyThreshold: ptr.To[uint32](0), - Type: egv1a1.ActiveHealthCheckerTypeHTTP, - HTTP: &egv1a1.HTTPActiveHealthChecker{ - Path: "/healthz", + ClusterSettings: egv1a1.ClusterSettings{ + HealthCheck: &egv1a1.HealthCheck{ + Active: &egv1a1.ActiveHealthCheck{ + UnhealthyThreshold: ptr.To[uint32](0), + Type: egv1a1.ActiveHealthCheckerTypeHTTP, + HTTP: &egv1a1.HTTPActiveHealthChecker{ + Path: "/healthz", + }, }, }, }, @@ -716,12 +746,14 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - HealthCheck: &egv1a1.HealthCheck{ - Active: &egv1a1.ActiveHealthCheck{ - HealthyThreshold: ptr.To[uint32](0), - Type: egv1a1.ActiveHealthCheckerTypeHTTP, - HTTP: &egv1a1.HTTPActiveHealthChecker{ - Path: "/healthz", + ClusterSettings: egv1a1.ClusterSettings{ + HealthCheck: &egv1a1.HealthCheck{ + Active: &egv1a1.ActiveHealthCheck{ + HealthyThreshold: ptr.To[uint32](0), + Type: egv1a1.ActiveHealthCheckerTypeHTTP, + HTTP: &egv1a1.HTTPActiveHealthChecker{ + Path: "/healthz", + }, }, }, }, @@ -744,10 +776,12 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - HealthCheck: &egv1a1.HealthCheck{ - Active: &egv1a1.ActiveHealthCheck{ - Type: egv1a1.ActiveHealthCheckerTypeHTTP, - TCP: &egv1a1.TCPActiveHealthChecker{}, + ClusterSettings: egv1a1.ClusterSettings{ + HealthCheck: &egv1a1.HealthCheck{ + Active: &egv1a1.ActiveHealthCheck{ + Type: egv1a1.ActiveHealthCheckerTypeHTTP, + TCP: &egv1a1.TCPActiveHealthChecker{}, + }, }, }, } @@ -756,6 +790,35 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { `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`, }, }, + { + desc: "grpc settings with non-gRPC health checker type", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + PolicyTargetReferences: egv1a1.PolicyTargetReferences{ + TargetRef: &gwapiv1a2.LocalPolicyTargetReferenceWithSectionName{ + LocalPolicyTargetReference: gwapiv1a2.LocalPolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + }, + ClusterSettings: egv1a1.ClusterSettings{ + HealthCheck: &egv1a1.HealthCheck{ + Active: &egv1a1.ActiveHealthCheck{ + Type: egv1a1.ActiveHealthCheckerTypeHTTP, + GRPC: &egv1a1.GRPCActiveHealthChecker{}, + }, + }, + }, + } + }, + wantErrors: []string{ + `If Health Checker type is HTTP, http field needs to be set.`, + `The grpc field can only be set if the Health Checker type is GRPC.`, + }, + }, + { desc: "invalid http expected statuses", mutate: func(btp *egv1a1.BackendTrafficPolicy) { @@ -769,12 +832,14 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - HealthCheck: &egv1a1.HealthCheck{ - Active: &egv1a1.ActiveHealthCheck{ - Type: egv1a1.ActiveHealthCheckerTypeHTTP, - HTTP: &egv1a1.HTTPActiveHealthChecker{ - Path: "/healthz", - ExpectedStatuses: []egv1a1.HTTPStatus{99, 200}, + ClusterSettings: egv1a1.ClusterSettings{ + HealthCheck: &egv1a1.HealthCheck{ + Active: &egv1a1.ActiveHealthCheck{ + Type: egv1a1.ActiveHealthCheckerTypeHTTP, + HTTP: &egv1a1.HTTPActiveHealthChecker{ + Path: "/healthz", + ExpectedStatuses: []egv1a1.HTTPStatus{99, 200}, + }, }, }, }, @@ -797,12 +862,14 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - HealthCheck: &egv1a1.HealthCheck{ - Active: &egv1a1.ActiveHealthCheck{ - Type: egv1a1.ActiveHealthCheckerTypeHTTP, - HTTP: &egv1a1.HTTPActiveHealthChecker{ - Path: "/healthz", - ExpectedStatuses: []egv1a1.HTTPStatus{100, 200, 201}, + ClusterSettings: egv1a1.ClusterSettings{ + HealthCheck: &egv1a1.HealthCheck{ + Active: &egv1a1.ActiveHealthCheck{ + Type: egv1a1.ActiveHealthCheckerTypeHTTP, + HTTP: &egv1a1.HTTPActiveHealthChecker{ + Path: "/healthz", + ExpectedStatuses: []egv1a1.HTTPStatus{100, 200, 201}, + }, }, }, }, @@ -823,12 +890,14 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - HealthCheck: &egv1a1.HealthCheck{ - Active: &egv1a1.ActiveHealthCheck{ - Type: egv1a1.ActiveHealthCheckerTypeHTTP, - HTTP: &egv1a1.HTTPActiveHealthChecker{ - Path: "/healthz", - ExpectedStatuses: []egv1a1.HTTPStatus{200, 300, 601}, + ClusterSettings: egv1a1.ClusterSettings{ + HealthCheck: &egv1a1.HealthCheck{ + Active: &egv1a1.ActiveHealthCheck{ + Type: egv1a1.ActiveHealthCheckerTypeHTTP, + HTTP: &egv1a1.HTTPActiveHealthChecker{ + Path: "/healthz", + ExpectedStatuses: []egv1a1.HTTPStatus{200, 300, 601}, + }, }, }, }, @@ -851,14 +920,16 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - HealthCheck: &egv1a1.HealthCheck{ - Active: &egv1a1.ActiveHealthCheck{ - Type: egv1a1.ActiveHealthCheckerTypeHTTP, - HTTP: &egv1a1.HTTPActiveHealthChecker{ - Path: "/healthz", - ExpectedResponse: &egv1a1.ActiveHealthCheckPayload{ - Type: egv1a1.ActiveHealthCheckPayloadTypeText, - Binary: []byte{'f', 'o', 'o'}, + ClusterSettings: egv1a1.ClusterSettings{ + HealthCheck: &egv1a1.HealthCheck{ + Active: &egv1a1.ActiveHealthCheck{ + Type: egv1a1.ActiveHealthCheckerTypeHTTP, + HTTP: &egv1a1.HTTPActiveHealthChecker{ + Path: "/healthz", + ExpectedResponse: &egv1a1.ActiveHealthCheckPayload{ + Type: egv1a1.ActiveHealthCheckPayloadTypeText, + Binary: []byte{'f', 'o', 'o'}, + }, }, }, }, @@ -882,14 +953,16 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - HealthCheck: &egv1a1.HealthCheck{ - Active: &egv1a1.ActiveHealthCheck{ - Type: egv1a1.ActiveHealthCheckerTypeHTTP, - HTTP: &egv1a1.HTTPActiveHealthChecker{ - Path: "/healthz", - ExpectedResponse: &egv1a1.ActiveHealthCheckPayload{ - Type: egv1a1.ActiveHealthCheckPayloadTypeBinary, - Text: ptr.To("foo"), + ClusterSettings: egv1a1.ClusterSettings{ + HealthCheck: &egv1a1.HealthCheck{ + Active: &egv1a1.ActiveHealthCheck{ + Type: egv1a1.ActiveHealthCheckerTypeHTTP, + HTTP: &egv1a1.HTTPActiveHealthChecker{ + Path: "/healthz", + ExpectedResponse: &egv1a1.ActiveHealthCheckPayload{ + Type: egv1a1.ActiveHealthCheckPayloadTypeBinary, + Text: ptr.To("foo"), + }, }, }, }, @@ -913,17 +986,19 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - HealthCheck: &egv1a1.HealthCheck{ - 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"), + ClusterSettings: egv1a1.ClusterSettings{ + HealthCheck: &egv1a1.HealthCheck{ + 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"), + }, }, }, }, @@ -947,17 +1022,19 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - HealthCheck: &egv1a1.HealthCheck{ - 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'}, + ClusterSettings: egv1a1.ClusterSettings{ + HealthCheck: &egv1a1.HealthCheck{ + 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'}, + }, }, }, }, @@ -982,13 +1059,15 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - Timeout: &egv1a1.Timeout{ - TCP: &egv1a1.TCPTimeout{ - ConnectTimeout: &d, - }, - HTTP: &egv1a1.HTTPTimeout{ - ConnectionIdleTimeout: &d, - MaxConnectionDuration: &d, + ClusterSettings: egv1a1.ClusterSettings{ + Timeout: &egv1a1.Timeout{ + TCP: &egv1a1.TCPTimeout{ + ConnectTimeout: &d, + }, + HTTP: &egv1a1.HTTPTimeout{ + ConnectionIdleTimeout: &d, + MaxConnectionDuration: &d, + }, }, }, } @@ -1078,12 +1157,36 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - Connection: &egv1a1.BackendConnection{ - BufferLimit: ptr.To(resource.MustParse("1Mi")), + ClusterSettings: egv1a1.ClusterSettings{ + Connection: &egv1a1.BackendConnection{ + BufferLimit: ptr.To(resource.MustParse("1Mi")), + }, }, } }, }, + { + desc: "connectionBufferLimitBytes given as a number", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + PolicyTargetReferences: egv1a1.PolicyTargetReferences{ + TargetRef: &gwapiv1a2.LocalPolicyTargetReferenceWithSectionName{ + LocalPolicyTargetReference: gwapiv1a2.LocalPolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + }, + ClusterSettings: egv1a1.ClusterSettings{ + Connection: &egv1a1.BackendConnection{ + BufferLimit: ptr.To(resource.MustParse("12345678")), + }, + }, + } + }, + wantErrors: []string{}, + }, { desc: "invalid connectionBufferLimitBytes format", mutate: func(btp *egv1a1.BackendTrafficPolicy) { @@ -1097,13 +1200,15 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { }, }, }, - Connection: &egv1a1.BackendConnection{ - BufferLimit: ptr.To(resource.MustParse("1m")), + ClusterSettings: egv1a1.ClusterSettings{ + Connection: &egv1a1.BackendConnection{ + BufferLimit: ptr.To(resource.MustParse("1m")), + }, }, } }, wantErrors: []string{ - "spec.connection.bufferLimit: Invalid value: \"\": BufferLimit must be of the format \"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$\"", + "spec.connection.bufferLimit: Invalid value: \"1m\": spec.connection.bufferLimit in body should match '^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$', : Invalid value: \"\"", }, }, { diff --git a/test/cel-validation/clienttrafficpolicy_test.go b/test/cel-validation/clienttrafficpolicy_test.go index 4d98efd0aa2..b57adf7d025 100644 --- a/test/cel-validation/clienttrafficpolicy_test.go +++ b/test/cel-validation/clienttrafficpolicy_test.go @@ -312,7 +312,7 @@ func TestClientTrafficPolicyTarget(t *testing.T) { } }, wantErrors: []string{ - "spec.connection.bufferLimit: Invalid value: \"\": bufferLimit must be of the format \"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$\"", + "spec.connection.bufferLimit: Invalid value: \"15m\": spec.connection.bufferLimit in body should match '^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$', : Invalid value: \"\"", }, }, { @@ -334,7 +334,7 @@ func TestClientTrafficPolicyTarget(t *testing.T) { } }, wantErrors: []string{ - "spec.http2.initialStreamWindowSize: Invalid value: \"\": initialStreamWindowSize must be of the format \"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$\"", + "spec.http2.initialStreamWindowSize: Invalid value: \"15m\": spec.http2.initialStreamWindowSize in body should match '^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$'", }, }, { @@ -356,7 +356,7 @@ func TestClientTrafficPolicyTarget(t *testing.T) { } }, wantErrors: []string{ - "spec.http2.InitialConnectionWindowSize: Invalid value: \"\": initialConnectionWindowSize must be of the format \"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$\"", + "spec.http2.initialConnectionWindowSize: Invalid value: \"15m\": spec.http2.initialConnectionWindowSize in body should match '^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$'", }, }, { diff --git a/test/cel-validation/envoyextensionpolicy_test.go b/test/cel-validation/envoyextensionpolicy_test.go index b199ed49d72..5e0e1f37ad9 100644 --- a/test/cel-validation/envoyextensionpolicy_test.go +++ b/test/cel-validation/envoyextensionpolicy_test.go @@ -284,11 +284,13 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) { sp.Spec = egv1a1.EnvoyExtensionPolicySpec{ ExtProc: []egv1a1.ExtProc{ { - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "grpc-proc-service", - Port: ptr.To(gwapiv1.PortNumber(80)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "grpc-proc-service", + Port: ptr.To(gwapiv1.PortNumber(80)), + }, }, }, }, @@ -313,12 +315,14 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) { sp.Spec = egv1a1.EnvoyExtensionPolicySpec{ ExtProc: []egv1a1.ExtProc{ { - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Group: ptr.To(gwapiv1.Group("unsupported")), - Name: "grpc-proc-service", - Port: ptr.To(gwapiv1.PortNumber(80)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Group: ptr.To(gwapiv1.Group("unsupported")), + Name: "grpc-proc-service", + Port: ptr.To(gwapiv1.PortNumber(80)), + }, }, }, }, @@ -335,7 +339,7 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) { }, } }, - wantErrors: []string{"spec.extProc[0].backendRefs: Invalid value: \"array\": BackendRefs only supports Core and gateway.envoyproxy.io group"}, + wantErrors: []string{"spec.extProc[0]: Invalid value: \"object\": BackendRefs only supports Core and gateway.envoyproxy.io group"}, }, { desc: "ExtProc with invalid BackendRef Kind", @@ -343,12 +347,14 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) { sp.Spec = egv1a1.EnvoyExtensionPolicySpec{ ExtProc: []egv1a1.ExtProc{ { - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Kind: ptr.To(gwapiv1.Kind("unsupported")), - Name: "grpc-proc-service", - Port: ptr.To(gwapiv1.PortNumber(80)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Kind: ptr.To(gwapiv1.Kind("unsupported")), + Name: "grpc-proc-service", + Port: ptr.To(gwapiv1.PortNumber(80)), + }, }, }, }, @@ -365,7 +371,7 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) { }, } }, - wantErrors: []string{"spec.extProc[0].backendRefs: Invalid value: \"array\": BackendRefs only supports Service and Backend kind"}, + wantErrors: []string{"spec.extProc[0]: Invalid value: \"object\": BackendRefs only supports Service and Backend kind"}, }, { desc: "ExtProc with invalid fields", @@ -373,11 +379,13 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) { sp.Spec = egv1a1.EnvoyExtensionPolicySpec{ ExtProc: []egv1a1.ExtProc{ { - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "grpc-proc-service", - Port: ptr.To(gwapiv1.PortNumber(80)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "grpc-proc-service", + Port: ptr.To(gwapiv1.PortNumber(80)), + }, }, }, }, diff --git a/test/cel-validation/envoyproxy_test.go b/test/cel-validation/envoyproxy_test.go index 4d914a7e9a6..76ba7434048 100644 --- a/test/cel-validation/envoyproxy_test.go +++ b/test/cel-validation/envoyproxy_test.go @@ -488,11 +488,13 @@ func TestEnvoyProxyProvider(t *testing.T) { { Type: egv1a1.ProxyAccessLogSinkTypeALS, ALS: &egv1a1.ALSEnvoyProxyAccessLog{ - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "fake-service", - Port: ptr.To(gwapiv1.PortNumber(9000)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "fake-service", + Port: ptr.To(gwapiv1.PortNumber(9000)), + }, }, }, }, @@ -519,11 +521,13 @@ func TestEnvoyProxyProvider(t *testing.T) { { Type: egv1a1.ProxyAccessLogSinkTypeALS, ALS: &egv1a1.ALSEnvoyProxyAccessLog{ - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "fake-service", - Port: ptr.To(gwapiv1.PortNumber(9000)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "fake-service", + Port: ptr.To(gwapiv1.PortNumber(9000)), + }, }, }, }, @@ -552,11 +556,13 @@ func TestEnvoyProxyProvider(t *testing.T) { { Type: egv1a1.ProxyAccessLogSinkTypeALS, ALS: &egv1a1.ALSEnvoyProxyAccessLog{ - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "fake-service", - Kind: ptr.To(gwapiv1.Kind("foo")), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "fake-service", + Kind: ptr.To(gwapiv1.Kind("foo")), + }, }, }, }, @@ -584,11 +590,13 @@ func TestEnvoyProxyProvider(t *testing.T) { { Type: egv1a1.ProxyAccessLogSinkTypeALS, ALS: &egv1a1.ALSEnvoyProxyAccessLog{ - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "fake-service", - Group: ptr.To(gwapiv1.Group("foo")), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "fake-service", + Group: ptr.To(gwapiv1.Group("foo")), + }, }, }, }, @@ -626,7 +634,7 @@ func TestEnvoyProxyProvider(t *testing.T) { }, } }, - wantErrors: []string{"Invalid value: \"null\""}, + wantErrors: []string{"Invalid value: \"object\": must have at least one backend in backendRefs"}, }, { desc: "invalid-accesslog-ALS-empty-backendrefs", @@ -640,44 +648,8 @@ func TestEnvoyProxyProvider(t *testing.T) { { Type: egv1a1.ProxyAccessLogSinkTypeALS, ALS: &egv1a1.ALSEnvoyProxyAccessLog{ - BackendRefs: []egv1a1.BackendRef{}, - Type: egv1a1.ALSEnvoyProxyAccessLogTypeHTTP, - }, - }, - }, - }, - }, - }, - }, - } - }, - wantErrors: []string{"should have at least 1 items"}, - }, - { - desc: "invalid-accesslog-ALS-multi-backendrefs", - mutate: func(envoy *egv1a1.EnvoyProxy) { - envoy.Spec = egv1a1.EnvoyProxySpec{ - Telemetry: &egv1a1.ProxyTelemetry{ - AccessLog: &egv1a1.ProxyAccessLog{ - Settings: []egv1a1.ProxyAccessLogSetting{ - { - Sinks: []egv1a1.ProxyAccessLogSink{ - { - Type: egv1a1.ProxyAccessLogSinkTypeALS, - ALS: &egv1a1.ALSEnvoyProxyAccessLog{ - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "fake-service", - Port: ptr.To(gwapiv1.PortNumber(8080)), - }, - }, - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "fake-service", - Port: ptr.To(gwapiv1.PortNumber(8080)), - }, - }, + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{}, }, Type: egv1a1.ALSEnvoyProxyAccessLogTypeHTTP, }, @@ -689,7 +661,7 @@ func TestEnvoyProxyProvider(t *testing.T) { }, } }, - wantErrors: []string{"must have at most 1 items"}, + wantErrors: []string{"must have at least one backend in backendRefs"}, }, { desc: "accesslog-OpenTelemetry", @@ -735,11 +707,13 @@ func TestEnvoyProxyProvider(t *testing.T) { { Type: egv1a1.ProxyAccessLogSinkTypeOpenTelemetry, OpenTelemetry: &egv1a1.OpenTelemetryEnvoyProxyAccessLog{ - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "fake-service", - Kind: ptr.To(gwapiv1.Kind("foo")), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "fake-service", + Kind: ptr.To(gwapiv1.Kind("foo")), + }, }, }, }, @@ -752,7 +726,7 @@ func TestEnvoyProxyProvider(t *testing.T) { }, } }, - wantErrors: []string{"only support Service Kind."}, + wantErrors: []string{"Invalid value: \"object\": BackendRefs only supports Service kind."}, }, { desc: "invalid-accesslog-backendref-group", @@ -770,11 +744,13 @@ func TestEnvoyProxyProvider(t *testing.T) { { Type: egv1a1.ProxyAccessLogSinkTypeOpenTelemetry, OpenTelemetry: &egv1a1.OpenTelemetryEnvoyProxyAccessLog{ - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "fake-service", - Group: ptr.To(gwapiv1.Group("foo")), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "fake-service", + Group: ptr.To(gwapiv1.Group("foo")), + }, }, }, }, @@ -805,12 +781,14 @@ func TestEnvoyProxyProvider(t *testing.T) { { Type: egv1a1.ProxyAccessLogSinkTypeOpenTelemetry, OpenTelemetry: &egv1a1.OpenTelemetryEnvoyProxyAccessLog{ - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "fake-service", - Kind: ptr.To(gwapiv1.Kind("Service")), - Port: ptr.To(gwapiv1.PortNumber(8080)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "fake-service", + Kind: ptr.To(gwapiv1.Kind("Service")), + Port: ptr.To(gwapiv1.PortNumber(8080)), + }, }, }, }, @@ -824,49 +802,6 @@ func TestEnvoyProxyProvider(t *testing.T) { } }, }, - { - desc: "multi-accesslog-backendref", - mutate: func(envoy *egv1a1.EnvoyProxy) { - envoy.Spec = egv1a1.EnvoyProxySpec{ - Telemetry: &egv1a1.ProxyTelemetry{ - AccessLog: &egv1a1.ProxyAccessLog{ - Settings: []egv1a1.ProxyAccessLogSetting{ - { - Format: &egv1a1.ProxyAccessLogFormat{ - Type: "Text", - Text: ptr.To("[%START_TIME%]"), - }, - Sinks: []egv1a1.ProxyAccessLogSink{ - { - Type: egv1a1.ProxyAccessLogSinkTypeOpenTelemetry, - OpenTelemetry: &egv1a1.OpenTelemetryEnvoyProxyAccessLog{ - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "fake-service", - Kind: ptr.To(gwapiv1.Kind("Service")), - Port: ptr.To(gwapiv1.PortNumber(8080)), - }, - }, - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "fake-service", - Kind: ptr.To(gwapiv1.Kind("Service")), - Port: ptr.To(gwapiv1.PortNumber(8080)), - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - } - }, - wantErrors: []string{"must have at most 1 items"}, - }, { desc: "accesslog-backendref-empty-kind", mutate: func(envoy *egv1a1.EnvoyProxy) { @@ -883,11 +818,13 @@ func TestEnvoyProxyProvider(t *testing.T) { { Type: egv1a1.ProxyAccessLogSinkTypeOpenTelemetry, OpenTelemetry: &egv1a1.OpenTelemetryEnvoyProxyAccessLog{ - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "fake-service", - Port: ptr.To(gwapiv1.PortNumber(8080)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "fake-service", + Port: ptr.To(gwapiv1.PortNumber(8080)), + }, }, }, }, @@ -993,11 +930,13 @@ func TestEnvoyProxyProvider(t *testing.T) { { Type: egv1a1.MetricSinkTypeOpenTelemetry, OpenTelemetry: &egv1a1.ProxyOpenTelemetrySink{ - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "fake-service", - Port: ptr.To(gwapiv1.PortNumber(8080)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "fake-service", + Port: ptr.To(gwapiv1.PortNumber(8080)), + }, }, }, }, @@ -1010,39 +949,6 @@ func TestEnvoyProxyProvider(t *testing.T) { }, wantErrors: []string{}, }, - { - desc: "ProxyMetrics-sinks-multi-backendref", - mutate: func(envoy *egv1a1.EnvoyProxy) { - envoy.Spec = egv1a1.EnvoyProxySpec{ - Telemetry: &egv1a1.ProxyTelemetry{ - Metrics: &egv1a1.ProxyMetrics{ - Sinks: []egv1a1.ProxyMetricSink{ - { - Type: egv1a1.MetricSinkTypeOpenTelemetry, - OpenTelemetry: &egv1a1.ProxyOpenTelemetrySink{ - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "fake-service", - Port: ptr.To(gwapiv1.PortNumber(8080)), - }, - }, - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "fake-service", - Port: ptr.To(gwapiv1.PortNumber(8080)), - }, - }, - }, - }, - }, - }, - }, - }, - } - }, - wantErrors: []string{"must have at most 1 items"}, - }, { desc: "ProxyMetrics-sinks-backendref-empty-kind", mutate: func(envoy *egv1a1.EnvoyProxy) { @@ -1053,11 +959,13 @@ func TestEnvoyProxyProvider(t *testing.T) { { Type: egv1a1.MetricSinkTypeOpenTelemetry, OpenTelemetry: &egv1a1.ProxyOpenTelemetrySink{ - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "fake-service", - Port: ptr.To(gwapiv1.PortNumber(8080)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "fake-service", + Port: ptr.To(gwapiv1.PortNumber(8080)), + }, }, }, }, @@ -1080,12 +988,14 @@ func TestEnvoyProxyProvider(t *testing.T) { { Type: egv1a1.MetricSinkTypeOpenTelemetry, OpenTelemetry: &egv1a1.ProxyOpenTelemetrySink{ - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "fake-service", - Kind: ptr.To(gwapiv1.Kind("foo")), - Port: ptr.To(gwapiv1.PortNumber(8080)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "fake-service", + Kind: ptr.To(gwapiv1.Kind("foo")), + Port: ptr.To(gwapiv1.PortNumber(8080)), + }, }, }, }, @@ -1096,7 +1006,7 @@ func TestEnvoyProxyProvider(t *testing.T) { }, } }, - wantErrors: []string{"only support Service Kind."}, + wantErrors: []string{"only supports Service Kind."}, }, { desc: "ProxyMetrics-sinks-invalid-backendref-group", @@ -1108,12 +1018,14 @@ func TestEnvoyProxyProvider(t *testing.T) { { Type: egv1a1.MetricSinkTypeOpenTelemetry, OpenTelemetry: &egv1a1.ProxyOpenTelemetrySink{ - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "fake-service", - Group: ptr.To(gwapiv1.Group("foo")), - Port: ptr.To(gwapiv1.PortNumber(8080)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "fake-service", + Group: ptr.To(gwapiv1.Group("foo")), + Port: ptr.To(gwapiv1.PortNumber(8080)), + }, }, }, }, @@ -1134,11 +1046,13 @@ func TestEnvoyProxyProvider(t *testing.T) { Tracing: &egv1a1.ProxyTracing{ Provider: egv1a1.TracingProvider{ Type: egv1a1.TracingProviderTypeOpenTelemetry, - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "fake-service", - Kind: ptr.To(gwapiv1.Kind("foo")), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "fake-service", + Kind: ptr.To(gwapiv1.Kind("foo")), + }, }, }, }, @@ -1147,7 +1061,7 @@ func TestEnvoyProxyProvider(t *testing.T) { }, } }, - wantErrors: []string{"only support Service Kind."}, + wantErrors: []string{"only supports Service Kind."}, }, { desc: "tracing-backendref-empty-kind", @@ -1157,11 +1071,13 @@ func TestEnvoyProxyProvider(t *testing.T) { Tracing: &egv1a1.ProxyTracing{ Provider: egv1a1.TracingProvider{ Type: egv1a1.TracingProviderTypeOpenTelemetry, - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "fake-service", - Port: ptr.To(gwapiv1.PortNumber(8080)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "fake-service", + Port: ptr.To(gwapiv1.PortNumber(8080)), + }, }, }, }, @@ -1179,42 +1095,14 @@ func TestEnvoyProxyProvider(t *testing.T) { Tracing: &egv1a1.ProxyTracing{ Provider: egv1a1.TracingProvider{ Type: egv1a1.TracingProviderTypeOpenTelemetry, - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "fake-service", - Kind: ptr.To(gwapiv1.Kind("Service")), - Port: ptr.To(gwapiv1.PortNumber(8080)), - }, - }, - }, - }, - }, - }, - } - }, - }, - { - desc: "tracing-multi-backendref", - mutate: func(envoy *egv1a1.EnvoyProxy) { - envoy.Spec = egv1a1.EnvoyProxySpec{ - Telemetry: &egv1a1.ProxyTelemetry{ - Tracing: &egv1a1.ProxyTracing{ - Provider: egv1a1.TracingProvider{ - Type: egv1a1.TracingProviderTypeOpenTelemetry, - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "fake-service", - Kind: ptr.To(gwapiv1.Kind("Service")), - Port: ptr.To(gwapiv1.PortNumber(8080)), - }, - }, - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "fake-service", - Kind: ptr.To(gwapiv1.Kind("Service")), - Port: ptr.To(gwapiv1.PortNumber(8080)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "fake-service", + Kind: ptr.To(gwapiv1.Kind("Service")), + Port: ptr.To(gwapiv1.PortNumber(8080)), + }, }, }, }, @@ -1223,7 +1111,6 @@ func TestEnvoyProxyProvider(t *testing.T) { }, } }, - wantErrors: []string{"must have at most 1 items"}, }, { desc: "tracing-empty-backend", diff --git a/test/cel-validation/securitypolicy_test.go b/test/cel-validation/securitypolicy_test.go index 24f229dd6f1..2ca001cd0c2 100644 --- a/test/cel-validation/securitypolicy_test.go +++ b/test/cel-validation/securitypolicy_test.go @@ -426,9 +426,15 @@ func TestSecurityPolicyTarget(t *testing.T) { sp.Spec = egv1a1.SecurityPolicySpec{ ExtAuth: &egv1a1.ExtAuth{ GRPC: &egv1a1.GRPCExtAuthService{ - BackendRef: &gwapiv1.BackendObjectReference{ - Name: "grpc-auth-service", - Port: ptr.To(gwapiv1.PortNumber(80)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "grpc-auth-service", + Port: ptr.To(gwapiv1.PortNumber(15001)), + }, + }, + }, }, }, }, @@ -451,12 +457,14 @@ func TestSecurityPolicyTarget(t *testing.T) { sp.Spec = egv1a1.SecurityPolicySpec{ ExtAuth: &egv1a1.ExtAuth{ GRPC: &egv1a1.GRPCExtAuthService{ - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "grpc-auth-service", - Kind: ptr.To(gwapiv1a2.Kind("Service")), - Port: ptr.To(gwapiv1.PortNumber(80)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "grpc-auth-service", + Kind: ptr.To(gwapiv1a2.Kind("Service")), + Port: ptr.To(gwapiv1.PortNumber(80)), + }, }, }, }, @@ -501,9 +509,15 @@ func TestSecurityPolicyTarget(t *testing.T) { sp.Spec = egv1a1.SecurityPolicySpec{ ExtAuth: &egv1a1.ExtAuth{ HTTP: &egv1a1.HTTPExtAuthService{ - BackendRef: &gwapiv1.BackendObjectReference{ - Name: "http-auth-service", - Port: ptr.To(gwapiv1.PortNumber(15001)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "http-auth-service", + Port: ptr.To(gwapiv1.PortNumber(15001)), + }, + }, + }, }, }, }, @@ -526,12 +540,14 @@ func TestSecurityPolicyTarget(t *testing.T) { sp.Spec = egv1a1.SecurityPolicySpec{ ExtAuth: &egv1a1.ExtAuth{ HTTP: &egv1a1.HTTPExtAuthService{ - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "grpc-auth-service", - Kind: ptr.To(gwapiv1a2.Kind("Service")), - Port: ptr.To(gwapiv1.PortNumber(80)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "grpc-auth-service", + Kind: ptr.To(gwapiv1a2.Kind("Service")), + Port: ptr.To(gwapiv1.PortNumber(80)), + }, }, }, }, @@ -576,15 +592,19 @@ func TestSecurityPolicyTarget(t *testing.T) { sp.Spec = egv1a1.SecurityPolicySpec{ ExtAuth: &egv1a1.ExtAuth{ GRPC: &egv1a1.GRPCExtAuthService{ - BackendRef: &gwapiv1.BackendObjectReference{ - Name: "grpc-auth-service", - Port: ptr.To(gwapiv1.PortNumber(80)), + BackendCluster: egv1a1.BackendCluster{ + 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)), + BackendCluster: egv1a1.BackendCluster{ + BackendRef: &gwapiv1.BackendObjectReference{ + Name: "http-auth-service", + Port: ptr.To(gwapiv1.PortNumber(15001)), + }, }, }, }, @@ -609,10 +629,16 @@ func TestSecurityPolicyTarget(t *testing.T) { 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)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Group: ptr.To(gwapiv1.Group("unsupported")), + Name: "http-auth-service", + Port: ptr.To(gwapiv1.PortNumber(15001)), + }, + }, + }, }, }, }, @@ -628,7 +654,7 @@ func TestSecurityPolicyTarget(t *testing.T) { } }, 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", + " BackendRefs only supports Core and gateway.envoyproxy.io group.", }, }, { @@ -637,10 +663,12 @@ func TestSecurityPolicyTarget(t *testing.T) { 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)), + BackendCluster: egv1a1.BackendCluster{ + BackendRef: &gwapiv1.BackendObjectReference{ + Kind: ptr.To(gwapiv1.Kind("unsupported")), + Name: "http-auth-service", + Port: ptr.To(gwapiv1.PortNumber(15001)), + }, }, }, }, @@ -656,7 +684,8 @@ func TestSecurityPolicyTarget(t *testing.T) { } }, 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", + "BackendRefs must be used, backendRef is not supported.", + "Exactly one backendRef can be specified in backendRefs.", }, }, { @@ -665,12 +694,14 @@ func TestSecurityPolicyTarget(t *testing.T) { sp.Spec = egv1a1.SecurityPolicySpec{ ExtAuth: &egv1a1.ExtAuth{ HTTP: &egv1a1.HTTPExtAuthService{ - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "grpc-auth-service", - Kind: ptr.To(gwapiv1a2.Kind("unsupported")), - Port: ptr.To(gwapiv1.PortNumber(80)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "grpc-auth-service", + Kind: ptr.To(gwapiv1a2.Kind("unsupported")), + Port: ptr.To(gwapiv1.PortNumber(80)), + }, }, }, }, @@ -687,7 +718,7 @@ func TestSecurityPolicyTarget(t *testing.T) { }, } }, - wantErrors: []string{" only support Service kind"}, + wantErrors: []string{"BackendRefs only supports Service and Backend kind."}, }, { desc: "grpc extAuth service invalid Group", @@ -695,10 +726,16 @@ func TestSecurityPolicyTarget(t *testing.T) { 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)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Group: ptr.To(gwapiv1.Group("unsupported")), + Name: "http-auth-service", + Port: ptr.To(gwapiv1.PortNumber(15001)), + }, + }, + }, }, }, }, @@ -714,7 +751,7 @@ func TestSecurityPolicyTarget(t *testing.T) { } }, 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", + "BackendRefs only supports Core and gateway.envoyproxy.io group.", }, }, { @@ -723,10 +760,12 @@ func TestSecurityPolicyTarget(t *testing.T) { 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)), + BackendCluster: egv1a1.BackendCluster{ + BackendRef: &gwapiv1.BackendObjectReference{ + Kind: ptr.To(gwapiv1.Kind("unsupported")), + Name: "http-auth-service", + Port: ptr.To(gwapiv1.PortNumber(15001)), + }, }, }, }, @@ -742,7 +781,8 @@ func TestSecurityPolicyTarget(t *testing.T) { } }, 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", + "BackendRefs must be used, backendRef is not supported.", + "Exactly one backendRef can be specified in backendRefs.", }, }, { @@ -751,12 +791,14 @@ func TestSecurityPolicyTarget(t *testing.T) { sp.Spec = egv1a1.SecurityPolicySpec{ ExtAuth: &egv1a1.ExtAuth{ GRPC: &egv1a1.GRPCExtAuthService{ - BackendRefs: []egv1a1.BackendRef{ - { - BackendObjectReference: gwapiv1.BackendObjectReference{ - Name: "grpc-auth-service", - Kind: ptr.To(gwapiv1a2.Kind("unsupported")), - Port: ptr.To(gwapiv1.PortNumber(80)), + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "grpc-auth-service", + Kind: ptr.To(gwapiv1a2.Kind("unsupported")), + Port: ptr.To(gwapiv1.PortNumber(80)), + }, }, }, }, @@ -773,7 +815,9 @@ func TestSecurityPolicyTarget(t *testing.T) { }, } }, - wantErrors: []string{" only support Service kind"}, + wantErrors: []string{ + "spec.extAuth.grpc: Invalid value: \"object\": BackendRefs only supports Service and Backend kind.", + }, }, // JWT @@ -918,6 +962,76 @@ func TestSecurityPolicyTarget(t *testing.T) { }, wantErrors: []string{}, }, + { + desc: "ext-auth-grpc-backend", + mutate: func(sp *egv1a1.SecurityPolicy) { + sp.Spec = egv1a1.SecurityPolicySpec{ + PolicyTargetReferences: egv1a1.PolicyTargetReferences{ + TargetSelectors: []egv1a1.TargetSelector{ + { + Group: ptr.To(gwapiv1a2.Group("gateway.networking.k8s.io")), + Kind: "HTTPRoute", + MatchLabels: map[string]string{ + "eg/namespace": "reference-apps", + }, + }, + }, + }, + ExtAuth: &egv1a1.ExtAuth{ + GRPC: &egv1a1.GRPCExtAuthService{ + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "grpc-auth-backend", + Kind: ptr.To(gwapiv1a2.Kind("Backend")), + Port: ptr.To(gwapiv1.PortNumber(8080)), + Group: ptr.To(gwapiv1a2.Group("gateway.envoyproxy.io")), + }, + }, + }, + }, + }, + }, + } + }, + wantErrors: []string{}, + }, + { + desc: "ext-auth-http-backend", + mutate: func(sp *egv1a1.SecurityPolicy) { + sp.Spec = egv1a1.SecurityPolicySpec{ + PolicyTargetReferences: egv1a1.PolicyTargetReferences{ + TargetSelectors: []egv1a1.TargetSelector{ + { + Group: ptr.To(gwapiv1a2.Group("gateway.networking.k8s.io")), + Kind: "HTTPRoute", + MatchLabels: map[string]string{ + "eg/namespace": "reference-apps", + }, + }, + }, + }, + ExtAuth: &egv1a1.ExtAuth{ + HTTP: &egv1a1.HTTPExtAuthService{ + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{ + { + BackendObjectReference: gwapiv1.BackendObjectReference{ + Name: "http-auth-backend", + Kind: ptr.To(gwapiv1a2.Kind("Backend")), + Port: ptr.To(gwapiv1.PortNumber(80)), + Group: ptr.To(gwapiv1a2.Group("gateway.envoyproxy.io")), + }, + }, + }, + }, + }, + }, + } + }, + wantErrors: []string{}, + }, } for _, tc := range cases { diff --git a/test/e2e/testdata/cookie-based-session-persistence.yaml b/test/e2e/testdata/cookie-based-session-persistence.yaml new file mode 100644 index 00000000000..60819e18098 --- /dev/null +++ b/test/e2e/testdata/cookie-based-session-persistence.yaml @@ -0,0 +1,29 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: cookie-based-session-persistence + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - matches: + - path: + type: PathPrefix + value: /v1 + backendRefs: + - name: infra-backend-v1 + port: 8080 + - matches: + - path: + type: PathPrefix + value: /v2 + backendRefs: + - name: infra-backend-v1 + port: 8080 + sessionPersistence: + sessionName: Session-A + type: Cookie + absoluteTimeout: 10s + cookieConfig: + lifetimeType: Permanent diff --git a/test/e2e/testdata/ext-auth-http-backend-securitypolicy.yaml b/test/e2e/testdata/ext-auth-http-backend-securitypolicy.yaml new file mode 100644 index 00000000000..ebee7ce0c1e --- /dev/null +++ b/test/e2e/testdata/ext-auth-http-backend-securitypolicy.yaml @@ -0,0 +1,56 @@ +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: http-ext-auth-backend + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + hostnames: ["www.example.com"] + rules: + - matches: + - path: + type: PathPrefix + value: /myapp # This is the path that will be protected by ext auth + backendRefs: + - name: infra-backend-v1 + port: 8080 +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: http-without-ext-auth-backend + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + hostnames: ["www.example.com"] + rules: + - matches: + - path: + type: PathPrefix + value: /public # This is the path that will be public + backendRefs: + - name: infra-backend-v1 + port: 8080 +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: SecurityPolicy +metadata: + name: ext-auth-backend + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: http-ext-auth-backend + extAuth: + http: + backendRefs: + - name: backend-fqdn # should add namespace here because envoy will locate in envoy-gateway-system namespace + kind: Backend + group: gateway.envoyproxy.io + namespace: gateway-conformance-infra + port: 9002 + headersToBackend: ["x-current-user"] diff --git a/test/e2e/testdata/ext-auth-http-backend.yaml b/test/e2e/testdata/ext-auth-http-backend.yaml new file mode 100644 index 00000000000..fe5185a7e11 --- /dev/null +++ b/test/e2e/testdata/ext-auth-http-backend.yaml @@ -0,0 +1,103 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: http-ext-auth-backend + namespace: gateway-conformance-infra +data: + http-ext-auth.js: | + const Http = require("http"); + const path = require("path"); + + const tokens = { + "token1": "user1", + "token2": "user2", + "token3": "user3" + }; + + const server = new Http.Server((req, res) => { + const authorization = req.headers["authorization"] || ""; + const extracted = authorization.split(" "); + if (extracted.length === 2 && extracted[0] === "Bearer") { + const user = checkToken(extracted[1]); + console.log(`token: "${extracted[1]}" user: "${user}`); + if (user !== undefined) { + // The authorization server returns a response with "x-current-user" header for a successful + // request. + res.writeHead(200, { "x-current-user": user }); + return res.end(); + } + } + res.writeHead(403); + res.end(); + }); + + const port = process.env.PORT || 9002; + server.listen(port); + console.log(`starting HTTP server on: ${port}`); + + function checkToken(token) { + return tokens[token]; + } +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: http-ext-auth-backend + namespace: gateway-conformance-infra +spec: + replicas: 1 + selector: + matchLabels: + app: http-ext-auth-backend + template: + metadata: + labels: + app: http-ext-auth-backend + spec: + containers: + - name: http-ext-auth-backend + command: + - node + - /usr/src/app/http-ext-auth.js + image: node:19-bullseye + ports: + - containerPort: 9002 + volumeMounts: + - name: http-ext-auth-backend + mountPath: /usr/src/app + readinessProbe: + httpGet: + httpHeaders: + - name: authorization + value: "Bearer token1" + port: 9002 + volumes: + - name: http-ext-auth-backend + configMap: + name: http-ext-auth-backend +--- +apiVersion: v1 +kind: Service +metadata: + name: http-ext-auth-backend + namespace: gateway-conformance-infra +spec: + selector: + app: http-ext-auth-backend + ports: + - protocol: TCP + port: 9002 + targetPort: 9002 +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: Backend +metadata: + name: backend-fqdn + namespace: gateway-conformance-infra +spec: + endpoints: + - fqdn: + # should add namespace here because envoy will locate in envoy-gateway-system namespace + hostname: http-ext-auth-backend.gateway-conformance-infra + port: 9002 diff --git a/test/e2e/testdata/header-based-session-persistence.yaml b/test/e2e/testdata/header-based-session-persistence.yaml new file mode 100644 index 00000000000..4c6030a99df --- /dev/null +++ b/test/e2e/testdata/header-based-session-persistence.yaml @@ -0,0 +1,30 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: header-based-session-persistence + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - matches: + - path: + type: PathPrefix + value: /v1 + backendRefs: + - name: infra-backend-v1 + port: 8080 + - matches: + - path: + type: PathPrefix + value: /v2 + backendRefs: + - name: infra-backend-v1 + port: 8080 + sessionPersistence: + sessionName: Session-A + type: Header + # Actually, absoluteTimeout is not necessary for Header based session persistence. + # But, we have to add it, otherwise the gateway-api validation (mistakenly) rejects it. + # https://github.com/kubernetes-sigs/gateway-api/issues/3214 + absoluteTimeout: 10s diff --git a/test/e2e/testdata/header-settings.yaml b/test/e2e/testdata/header-settings.yaml new file mode 100644 index 00000000000..dab686f29c7 --- /dev/null +++ b/test/e2e/testdata/header-settings.yaml @@ -0,0 +1,47 @@ +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: ClientTrafficPolicy +metadata: + name: early-header-modifier-ctp + namespace: gateway-conformance-infra +spec: + targetRefs: + - group: gateway.networking.k8s.io + kind: Gateway + name: same-namespace + headers: + earlyRequestHeaders: + add: + - name: "early-added-header" + value: "early" + set: + - name: "early-set-header" + value: "early" + remove: + - "early-removed-header" +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: http-with-early-headers + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - matches: + - path: + type: PathPrefix + value: /early-header + filters: + - type: RequestHeaderModifier + requestHeaderModifier: + add: + - name: early-added-header + value: late + - name: early-set-header + value: late + - name: early-removed-header + value: late + backendRefs: + - name: infra-backend-v1 + port: 8080 diff --git a/test/e2e/testdata/multi-referencegrants-same-namespace-services.yaml b/test/e2e/testdata/multi-referencegrants-same-namespace-services.yaml new file mode 100644 index 00000000000..948503bea3d --- /dev/null +++ b/test/e2e/testdata/multi-referencegrants-same-namespace-services.yaml @@ -0,0 +1,148 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: multireferencegrants-ns +--- +apiVersion: v1 +kind: Service +metadata: + name: app-backend-v1 + namespace: multireferencegrants-ns +spec: + selector: + app: app-backend-v1 + ports: + - protocol: TCP + port: 8080 + targetPort: 3000 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: app-backend-v1 + namespace: multireferencegrants-ns + labels: + app: app-backend-v1 +spec: + replicas: 1 + selector: + matchLabels: + app: app-backend-v1 + template: + metadata: + labels: + app: app-backend-v1 + spec: + containers: + - name: app-backend-v1 + image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: SERVICE_NAME + value: app-backend-v1 + resources: + requests: + cpu: 10m +--- +apiVersion: v1 +kind: Service +metadata: + name: app-backend-v2 + namespace: multireferencegrants-ns +spec: + selector: + app: app-backend-v2 + ports: + - protocol: TCP + port: 8080 + targetPort: 3000 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: app-backend-v2 + namespace: multireferencegrants-ns + labels: + app: app-backend-v2 +spec: + replicas: 1 + selector: + matchLabels: + app: app-backend-v2 + template: + metadata: + labels: + app: app-backend-v2 + spec: + containers: + - name: app-backend-v2 + image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: SERVICE_NAME + value: app-backend-v2 + resources: + requests: + cpu: 10m +--- +apiVersion: v1 +kind: Service +metadata: + name: app-backend-v3 + namespace: multireferencegrants-ns +spec: + selector: + app: app-backend-v3 + ports: + - protocol: TCP + port: 8080 + targetPort: 3000 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: app-backend-v3 + namespace: multireferencegrants-ns + labels: + app: app-backend-v3 +spec: + replicas: 1 + selector: + matchLabels: + app: app-backend-v3 + template: + metadata: + labels: + app: app-backend-v3 + spec: + containers: + - name: app-backend-v3 + image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: SERVICE_NAME + value: app-backend-v3 + resources: + requests: + cpu: 10m diff --git a/test/e2e/testdata/multi-referencegrants-same-namespace.yaml b/test/e2e/testdata/multi-referencegrants-same-namespace.yaml new file mode 100644 index 00000000000..f9940185e5c --- /dev/null +++ b/test/e2e/testdata/multi-referencegrants-same-namespace.yaml @@ -0,0 +1,92 @@ +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: HTTPRoute +metadata: + name: multi-referencegrant-same-namespace + namespace: gateway-conformance-infra +spec: + hostnames: + - multireferencegrant.local + parentRefs: + - group: gateway.networking.k8s.io + kind: Gateway + name: same-namespace + namespace: gateway-conformance-infra + rules: + - backendRefs: + - group: "" + kind: Service + name: app-backend-v3 + namespace: multireferencegrants-ns + port: 8080 + weight: 1 + matches: + - path: + type: PathPrefix + value: /v3/echo + - backendRefs: + - group: "" + kind: Service + name: app-backend-v2 + namespace: multireferencegrants-ns + port: 8080 + weight: 1 + matches: + - path: + type: PathPrefix + value: /v2/echo + - backendRefs: + - group: "" + kind: Service + name: app-backend-v1 + namespace: multireferencegrants-ns + port: 8080 + weight: 1 + matches: + - path: + type: PathPrefix + value: /v1/echo +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: ReferenceGrant +metadata: + name: app-backend-v1-rg + namespace: multireferencegrants-ns +spec: + from: + - group: gateway.networking.k8s.io + kind: HTTPRoute + namespace: gateway-conformance-infra + to: + - group: "" + kind: Service + name: app-backend-v1 +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: ReferenceGrant +metadata: + name: app-backend-v2-rg + namespace: multireferencegrants-ns +spec: + from: + - group: gateway.networking.k8s.io + kind: HTTPRoute + namespace: gateway-conformance-infra + to: + - group: "" + kind: Service + name: app-backend-v2 +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: ReferenceGrant +metadata: + name: app-backend-v3-rg + namespace: multireferencegrants-ns +spec: + from: + - group: gateway.networking.k8s.io + kind: HTTPRoute + namespace: gateway-conformance-infra + to: + - group: "" + kind: Service + name: app-backend-v3 diff --git a/test/e2e/testdata/wasm-http.yaml b/test/e2e/testdata/wasm-http.yaml index d251d5943e9..2bc1aae0ab3 100644 --- a/test/e2e/testdata/wasm-http.yaml +++ b/test/e2e/testdata/wasm-http.yaml @@ -51,5 +51,5 @@ spec: code: type: HTTP http: - url: https://raw.githubusercontent.com/envoyproxy/envoy/main/examples/wasm-cc/lib/envoy_filter_http_wasm_example.wasm + url: https://raw.githubusercontent.com/envoyproxy/examples/main/wasm-cc/lib/envoy_filter_http_wasm_example.wasm sha256: 79c9f85128bb0177b6511afa85d587224efded376ac0ef76df56595f1e6315c0 diff --git a/test/e2e/tests/ext_auth_http_backend.go b/test/e2e/tests/ext_auth_http_backend.go new file mode 100644 index 00000000000..7032bdc2ae0 --- /dev/null +++ b/test/e2e/tests/ext_auth_http_backend.go @@ -0,0 +1,155 @@ +// 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 ( + "testing" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" + gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" + gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + + "github.com/envoyproxy/gateway/internal/gatewayapi" +) + +func init() { + ConformanceTests = append(ConformanceTests, HTTPBackendExtAuthTest) +} + +// HTTPBackendExtAuthTest tests ExtAuth authentication for a http route with ExtAuth configured. +// Almost like HTTPExtAuthTest, but the security policy reference to the backend service. +var HTTPBackendExtAuthTest = suite.ConformanceTest{ + ShortName: "HTTPBackendExtAuth", + Description: "Test ExtAuth authentication with backend", + Manifests: []string{"testdata/ext-auth-http-backend.yaml", "testdata/ext-auth-http-backend-securitypolicy.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "http-ext-auth-backend", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + + ancestorRef := gwapiv1a2.ParentReference{ + Group: gatewayapi.GroupPtr(gwapiv1.GroupName), + Kind: gatewayapi.KindPtr(gatewayapi.KindGateway), + Namespace: gatewayapi.NamespacePtr(gwNN.Namespace), + Name: gwapiv1.ObjectName(gwNN.Name), + } + SecurityPolicyMustBeAccepted(t, suite.Client, types.NamespacedName{Name: "ext-auth-backend", Namespace: ns}, suite.ControllerName, ancestorRef) + + podReady := corev1.PodCondition{Type: corev1.PodReady, Status: corev1.ConditionTrue} + + // Wait for the http ext auth service pod to be ready + WaitForPods(t, suite.Client, ns, map[string]string{"app": "http-ext-auth-backend"}, corev1.PodRunning, podReady) + + t.Run("http route with ext auth backend ref", func(t *testing.T) { + expectedResponse := http.ExpectedResponse{ + Request: http.Request{ + Host: "www.example.com", + Path: "/myapp", + Headers: map[string]string{ + "Authorization": "Bearer token2", + }, + }, + // Verify that the http headers returned by the ext auth service + // are added to the original request before sending it to the backend + ExpectedRequest: &http.ExpectedRequest{ + Request: http.Request{ + Host: "www.example.com", + Path: "/myapp", + Headers: map[string]string{ + "x-current-user": "user2", + }, + }, + }, + Response: http.Response{ + StatusCode: 200, + }, + Namespace: ns, + } + + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse) + }) + + t.Run("without Authorization header", func(t *testing.T) { + expectedResponse := http.ExpectedResponse{ + Request: http.Request{ + Host: "www.example.com", + Path: "/myapp", + }, + Response: http.Response{ + StatusCode: 403, + }, + 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) + } + }) + + t.Run("invalid credential", func(t *testing.T) { + expectedResponse := http.ExpectedResponse{ + Request: http.Request{ + Host: "www.example.com", + Path: "/myapp", + Headers: map[string]string{ + "Authorization": "Bearer invalid-token", + }, + }, + Response: http.Response{ + StatusCode: 403, + }, + 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) + } + }) + + t.Run("http route without ext auth authentication", func(t *testing.T) { + expectedResponse := http.ExpectedResponse{ + Request: http.Request{ + Host: "www.example.com", + Path: "/public", + }, + Response: http.Response{ + StatusCode: 200, + }, + 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/header_settings.go b/test/e2e/tests/header_settings.go new file mode 100644 index 00000000000..32f0d731089 --- /dev/null +++ b/test/e2e/tests/header_settings.go @@ -0,0 +1,75 @@ +// 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 ( + "testing" + + "k8s.io/apimachinery/pkg/types" + gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" + gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" + + "github.com/envoyproxy/gateway/internal/gatewayapi" +) + +func init() { + ConformanceTests = append(ConformanceTests, HeaderSettingsTest) +} + +var HeaderSettingsTest = suite.ConformanceTest{ + ShortName: "HeaderSettings", + Description: "Modify headers before regular processing", + Manifests: []string{"testdata/header-settings.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + t.Run("Early header modifications should apply", func(t *testing.T) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "http-with-early-headers", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + + ancestorRef := gwapiv1a2.ParentReference{ + Group: gatewayapi.GroupPtr(gwapiv1.GroupName), + Kind: gatewayapi.KindPtr(gatewayapi.KindGateway), + Namespace: gatewayapi.NamespacePtr(gwNN.Namespace), + Name: gwapiv1.ObjectName(gwNN.Name), + } + ClientTrafficPolicyMustBeAccepted(t, suite.Client, types.NamespacedName{Name: "early-header-modifier-ctp", Namespace: ns}, suite.ControllerName, ancestorRef) + + expected := http.ExpectedResponse{ + Request: http.Request{ + Path: "/early-header", + Headers: map[string]string{ + "early-added-header": "client", + "early-set-header": "client", + "early-removed-header": "client", + }, + }, + ExpectedRequest: &http.ExpectedRequest{ + Request: http.Request{ + Path: "/early-header", + Headers: map[string]string{ + "early-added-header": "client,early,late", // client, early and late are all added to header + "early-set-header": "early,late", // early set overwrites client value + "early-removed-header": "late", // removed by early, so only late value exists + }, + }, + }, + Response: http.Response{ + StatusCode: 200, + }, + Namespace: ns, + } + + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expected) + }) + }, +} diff --git a/test/e2e/tests/referencegrants.go b/test/e2e/tests/referencegrants.go new file mode 100644 index 00000000000..903e64598bc --- /dev/null +++ b/test/e2e/tests/referencegrants.go @@ -0,0 +1,79 @@ +// 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 ( + "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/suite" +) + +func init() { + ConformanceTests = append(ConformanceTests, MultiReferenceGrantsSameNamespaceTest) +} + +var MultiReferenceGrantsSameNamespaceTest = suite.ConformanceTest{ + ShortName: "MultiReferenceGrantsSameNamespace", + Description: "Test for multiple reference grants in the same namespace", + Manifests: []string{"testdata/multi-referencegrants-same-namespace-services.yaml", "testdata/multi-referencegrants-same-namespace.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + resourceNS := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "multi-referencegrant-same-namespace", Namespace: resourceNS} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: resourceNS} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + + targetHost := "multireferencegrant.local" + targetNS := "multireferencegrants-ns" + testcases := []http.ExpectedResponse{ + { + Request: http.Request{ + Host: targetHost, + Path: "/v1/echo", + }, + Response: http.Response{ + StatusCode: 200, + }, + Backend: "app-backend-v1", + Namespace: targetNS, + }, + { + Request: http.Request{ + Host: targetHost, + Path: "/v2/echo", + }, + Response: http.Response{ + StatusCode: 200, + }, + Backend: "app-backend-v2", + Namespace: targetNS, + }, + { + Request: http.Request{ + Host: targetHost, + Path: "/v3/echo", + }, + Response: http.Response{ + StatusCode: 200, + }, + Backend: "app-backend-v3", + Namespace: targetNS, + }, + } + + for i, tc := range testcases { + t.Run(tc.GetTestCaseName(i), func(t *testing.T) { + t.Parallel() + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc) + }) + } + }, +} diff --git a/test/e2e/tests/session_persistence.go b/test/e2e/tests/session_persistence.go new file mode 100644 index 00000000000..7c1d90880ab --- /dev/null +++ b/test/e2e/tests/session_persistence.go @@ -0,0 +1,189 @@ +// 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 ( + "fmt" + "net/http" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "k8s.io/apimachinery/pkg/types" + httputils "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" +) + +func init() { + ConformanceTests = append(ConformanceTests, HeaderBasedSessionPersistenceTest) + ConformanceTests = append(ConformanceTests, CookieBasedSessionPersistenceTest) +} + +var HeaderBasedSessionPersistenceTest = suite.ConformanceTest{ + ShortName: "HeaderBasedSessionPersistence", + Description: "Test that the session persistence filter is correctly configured with header based session persistence", + Manifests: []string{"testdata/header-based-session-persistence.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + t.Run("traffic is routed based on header based session persistence", func(t *testing.T) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "header-based-session-persistence", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + req := httputils.MakeRequest(t, &httputils.ExpectedResponse{ + Request: httputils.Request{ + Path: "/v2", + }, + }, gwAddr, "HTTP", "http") + + pod := "" + // We make 10 requests to the gateway and expect them to be routed to the same pod. + for i := 0; i < 10; i++ { + captReq, res, err := suite.RoundTripper.CaptureRoundTrip(req) + if err != nil { + t.Fatalf("failed to make request: %v", err) + } + + if i == 0 { + // First request, capture the pod name and header. + sessionHeader, ok := res.Headers["Session-A"] + if !ok { + t.Fatalf("expected header Session-A to be set: %v", res.Headers) + } + + if captReq.Pod == "" { + t.Fatalf("expected pod to be set") + } + pod = captReq.Pod + req.Headers["Session-A"] = sessionHeader + continue + } + + t.Logf("request is received from pod %s", captReq.Pod) + + if captReq.Pod != pod { + t.Fatalf("expected pod to be the same as previous requests") + } + } + }) + t.Run("session persistence is configured per route", func(t *testing.T) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "header-based-session-persistence", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + req := httputils.MakeRequest(t, &httputils.ExpectedResponse{ + Request: httputils.Request{ + // /v1 path does not have the session persistence. + Path: "/v1", + }, + }, gwAddr, "HTTP", "http") + + _, res, err := suite.RoundTripper.CaptureRoundTrip(req) + if err != nil { + t.Fatalf("failed to make request: %v", err) + } + + if h, ok := res.Headers["Session-A"]; ok { + t.Fatalf("expected header Session-A to not be set: %v", h) + } + }) + }, +} + +var CookieBasedSessionPersistenceTest = suite.ConformanceTest{ + ShortName: "CookieBasedSessionPersistence", + Description: "Test that the session persistence filter is correctly configured with cookie based session persistence", + Manifests: []string{"testdata/cookie-based-session-persistence.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + t.Run("traffic is routed based on cookie based session persistence", func(t *testing.T) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "cookie-based-session-persistence", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + req := httputils.MakeRequest(t, &httputils.ExpectedResponse{ + Request: httputils.Request{ + Path: "/v2", + }, + }, gwAddr, "HTTP", "http") + + pod := "" + // We make 10 requests to the gateway and expect them to be routed to the same pod. + for i := 0; i < 10; i++ { + captReq, res, err := suite.RoundTripper.CaptureRoundTrip(req) + if err != nil { + t.Fatalf("failed to make request: %v", err) + } + + if i == 0 { + // First request, capture the pod name and cookie. + if captReq.Pod == "" { + t.Fatalf("expected pod to be set") + } + + cookie, err := parseCookie(res.Headers, "Session-A") + if err != nil { + t.Fatalf("failed to parse cookie: %v", err) + } + + // Check the cookie is set correctly. + if diff := cmp.Diff(cookie, &http.Cookie{ + Name: "Session-A", + MaxAge: 10, + Path: "/v2", + HttpOnly: true, + }, cmpopts.IgnoreFields(http.Cookie{}, "Value", "Raw"), // Ignore the value as it is random. + ); diff != "" { + t.Fatalf("unexpected cookie: %v", diff) + } + + pod = captReq.Pod + req.Headers["Cookie"] = []string{fmt.Sprintf("Session-A=%s", cookie.Value)} + continue + } + + t.Logf("request is received from pod %s", captReq.Pod) + + if captReq.Pod != pod { + t.Fatalf("expected pod to be the same as previous requests") + } + } + }) + t.Run("session persistence is configured per route", func(t *testing.T) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "cookie-based-session-persistence", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + req := httputils.MakeRequest(t, &httputils.ExpectedResponse{ + Request: httputils.Request{ + // /v1 path does not have the session persistence. + Path: "/v1", + }, + }, gwAddr, "HTTP", "http") + + _, res, err := suite.RoundTripper.CaptureRoundTrip(req) + if err != nil { + t.Fatalf("failed to make request: %v", err) + } + + if _, ok := res.Headers["Set-Cookie"]; ok { + t.Fatal("expected the envoy not to response set-cookie back") + } + }) + }, +} + +func parseCookie(headers map[string][]string, cookieName string) (*http.Cookie, error) { + parser := &http.Response{Header: headers} + for _, c := range parser.Cookies() { + if c.Name == cookieName { + return c, nil + } + } + return nil, fmt.Errorf("cookie %s not found: headers: %v", cookieName, headers) +} diff --git a/tools/linter/golangci-lint/.golangci.yml b/tools/linter/golangci-lint/.golangci.yml index 3a83d0841a4..c0155b32447 100644 --- a/tools/linter/golangci-lint/.golangci.yml +++ b/tools/linter/golangci-lint/.golangci.yml @@ -4,6 +4,7 @@ run: linters: enable: - bodyclose + - copyloopvar - depguard - errorlint - exportloopref @@ -114,6 +115,8 @@ linters-settings: - suite-extra-assert-call unparam: check-exported: false + copyloopvar: + check-alias: true issues: exclude-rules: diff --git a/tools/src/buf/go.mod b/tools/src/buf/go.mod index de4034e91b6..639ff08144c 100644 --- a/tools/src/buf/go.mod +++ b/tools/src/buf/go.mod @@ -2,51 +2,71 @@ module local go 1.22.5 -require github.com/bufbuild/buf v1.35.1 +require github.com/bufbuild/buf v1.37.0 require ( - buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240508200655-46a4cf4ba109.2 // indirect - buf.build/gen/go/bufbuild/registry/connectrpc/go v1.16.2-20240610164129-660609bc46d3.1 // indirect - buf.build/gen/go/bufbuild/registry/protocolbuffers/go v1.34.2-20240610164129-660609bc46d3.2 // indirect + buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240717164558-a6c49f84cc0f.2 // indirect + buf.build/gen/go/bufbuild/registry/connectrpc/go v1.16.2-20240801134127-09fbc17f7c9e.1 // indirect + buf.build/gen/go/bufbuild/registry/protocolbuffers/go v1.34.2-20240801134127-09fbc17f7c9e.2 // indirect connectrpc.com/connect v1.16.2 // indirect - connectrpc.com/otelconnect v0.7.0 // indirect + connectrpc.com/otelconnect v0.7.1 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/Microsoft/hcsshim v0.12.5 // indirect github.com/antlr4-go/antlr/v4 v4.13.0 // indirect github.com/bufbuild/protocompile v0.14.0 // indirect github.com/bufbuild/protoplugin v0.0.0-20240323223605-e2735f6c31ee // indirect - github.com/bufbuild/protovalidate-go v0.6.2 // indirect - github.com/bufbuild/protoyaml-go v0.1.9 // indirect + github.com/bufbuild/protovalidate-go v0.6.3 // indirect + github.com/bufbuild/protoyaml-go v0.1.10 // indirect + github.com/containerd/cgroups/v3 v3.0.3 // indirect + github.com/containerd/containerd v1.7.20 // indirect + github.com/containerd/continuity v0.4.3 // indirect + github.com/containerd/errdefs v0.1.0 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect + github.com/containerd/ttrpc v1.2.5 // indirect + github.com/containerd/typeurl/v2 v2.2.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/cli v26.1.4+incompatible // indirect + github.com/docker/cli v27.1.2+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect - github.com/docker/docker v27.0.0+incompatible // indirect + github.com/docker/docker v27.1.2+incompatible // indirect github.com/docker/docker-credential-helpers v0.8.2 // 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.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-chi/chi/v5 v5.0.14 // indirect + github.com/go-chi/chi/v5 v5.1.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/gofrs/uuid/v5 v5.2.0 // indirect + github.com/gofrs/uuid/v5 v5.3.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/google/cel-go v0.20.1 // indirect - github.com/google/go-containerregistry v0.19.2 // indirect - github.com/google/pprof v0.0.0-20240622144329-c177fd99eaa9 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/google/cel-go v0.21.0 // indirect + github.com/google/go-containerregistry v0.20.2 // indirect + github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jdx/go-netrc v1.0.0 // indirect github.com/klauspost/compress v1.17.9 // 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/docker-image-spec v1.3.1 // indirect + github.com/moby/locker v1.0.1 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/sys/mount v0.3.4 // indirect + github.com/moby/sys/mountinfo v0.7.2 // indirect + github.com/moby/sys/sequential v0.6.0 // indirect + github.com/moby/sys/user v0.3.0 // indirect + github.com/moby/sys/userns v0.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 // indirect + github.com/opencontainers/runtime-spec v1.2.0 // 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 @@ -57,25 +77,27 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect github.com/vbatts/tar-split v0.11.5 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.50.0 // indirect - go.opentelemetry.io/otel v1.25.0 // indirect + go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect + go.opentelemetry.io/otel v1.28.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 // indirect - go.opentelemetry.io/otel/metric v1.25.0 // indirect - go.opentelemetry.io/otel/sdk v1.25.0 // indirect - go.opentelemetry.io/otel/trace v1.25.0 // indirect + go.opentelemetry.io/otel/metric v1.28.0 // indirect + go.opentelemetry.io/otel/sdk v1.28.0 // indirect + go.opentelemetry.io/otel/trace v1.28.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/crypto v0.24.0 // indirect - golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect - golang.org/x/mod v0.18.0 // indirect - golang.org/x/net v0.26.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/term v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240617180043-68d350f18fd4 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240617180043-68d350f18fd4 // indirect + golang.org/x/crypto v0.26.0 // indirect + golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa // indirect + golang.org/x/mod v0.20.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.24.0 // indirect + golang.org/x/term v0.23.0 // indirect + golang.org/x/text v0.17.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240812133136-8ffd90a71988 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240812133136-8ffd90a71988 // indirect + google.golang.org/grpc v1.65.0 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/tools/src/buf/go.sum b/tools/src/buf/go.sum index c6d949c31f1..3dbec1398c9 100644 --- a/tools/src/buf/go.sum +++ b/tools/src/buf/go.sum @@ -1,31 +1,38 @@ -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240508200655-46a4cf4ba109.2 h1:cFrEG/pJch6t62+jqndcPXeTNkYcztS4tBRgNkR+drw= -buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240508200655-46a4cf4ba109.2/go.mod h1:ylS4c28ACSI59oJrOdW4pHS4n0Hw4TgSPHn8rpHl4Yw= -buf.build/gen/go/bufbuild/registry/connectrpc/go v1.16.2-20240610164129-660609bc46d3.1 h1:PmSlGbLLyhKIAm46ROmzdGVaaYgDdFsQNA+VftjuCLs= -buf.build/gen/go/bufbuild/registry/connectrpc/go v1.16.2-20240610164129-660609bc46d3.1/go.mod h1:4ptL49VoWyYwajT6j4zu5vmQ/k/om4tGMB9atY2FhEo= -buf.build/gen/go/bufbuild/registry/protocolbuffers/go v1.34.2-20240610164129-660609bc46d3.2 h1:y1+UxFIWzj/eF2RCPqt9egR7Rt9vgQkXNUzSdmR6iEU= -buf.build/gen/go/bufbuild/registry/protocolbuffers/go v1.34.2-20240610164129-660609bc46d3.2/go.mod h1:psseUmlKRo9v5LZJtR/aTpdTLuyp9o3X7rnLT87SZEo= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240717164558-a6c49f84cc0f.2 h1:SZRVx928rbYZ6hEKUIN+vtGDkl7uotABRWGY4OAg5gM= +buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.34.2-20240717164558-a6c49f84cc0f.2/go.mod h1:ylS4c28ACSI59oJrOdW4pHS4n0Hw4TgSPHn8rpHl4Yw= +buf.build/gen/go/bufbuild/registry/connectrpc/go v1.16.2-20240801134127-09fbc17f7c9e.1 h1:IV4si5SvDJSGQ/kpcnmOFKDKh8erG6zPy+NhmxlYdxM= +buf.build/gen/go/bufbuild/registry/connectrpc/go v1.16.2-20240801134127-09fbc17f7c9e.1/go.mod h1:4isTSbIhQ6wERY99Kvds0UuOcFMUoPDBPZfaAKrUnSE= +buf.build/gen/go/bufbuild/registry/protocolbuffers/go v1.34.2-20240801134127-09fbc17f7c9e.2 h1:7fUEOBrfNd50BMAls2tLn9RhttbDIfxRXML99YaLqKY= +buf.build/gen/go/bufbuild/registry/protocolbuffers/go v1.34.2-20240801134127-09fbc17f7c9e.2/go.mod h1:psseUmlKRo9v5LZJtR/aTpdTLuyp9o3X7rnLT87SZEo= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= connectrpc.com/connect v1.16.2 h1:ybd6y+ls7GOlb7Bh5C8+ghA6SvCBajHwxssO2CGFjqE= connectrpc.com/connect v1.16.2/go.mod h1:n2kgwskMHXC+lVqb18wngEpF95ldBHXjZYJussz5FRc= -connectrpc.com/otelconnect v0.7.0 h1:ZH55ZZtcJOTKWWLy3qmL4Pam4RzRWBJFOqTPyAqCXkY= -connectrpc.com/otelconnect v0.7.0/go.mod h1:Bt2ivBymHZHqxvo4HkJ0EwHuUzQN6k2l0oH+mp/8nwc= +connectrpc.com/otelconnect v0.7.1 h1:scO5pOb0i4yUE66CnNrHeK1x51yq0bE0ehPg6WvzXJY= +connectrpc.com/otelconnect v0.7.1/go.mod h1:dh3bFgHBTb2bkqGCeVVOtHJreSns7uu9wwL2Tbz17ms= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= 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/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/Microsoft/hcsshim v0.12.5 h1:bpTInLlDy/nDRWFVcefDZZ1+U8tS+rz3MxjKgu9boo0= +github.com/Microsoft/hcsshim v0.12.5/go.mod h1:tIUGego4G1EN5Hb6KC90aDYiUI2dqLSTTOCjVNpOgZ8= 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.35.1 h1:aiCi/YFOg7eXKZeveWb2ZhnmLFwUMM/FnDCM0roFp+M= -github.com/bufbuild/buf v1.35.1/go.mod h1:SM7b5QW3FkQPNkkqIa/9UWzLOoe51la+GGZpEgH9b68= +github.com/bufbuild/buf v1.37.0 h1:lKQ2LahOOMzLFFAg1IMQj12gPhAfLWGr6z6jfP6p7Bw= +github.com/bufbuild/buf v1.37.0/go.mod h1:uFHazPjAiKVpyK9Td/4FeMzQb8v5X7M4fo255kw/W6U= github.com/bufbuild/protocompile v0.14.0 h1:z3DW4IvXE5G/uTOnSQn+qwQQxvhckkTWLS/0No/o7KU= github.com/bufbuild/protocompile v0.14.0/go.mod h1:N6J1NYzkspJo3ZwyL4Xjvli86XOj1xq4qAasUFxGups= github.com/bufbuild/protoplugin v0.0.0-20240323223605-e2735f6c31ee h1:E6ET8YUcYJ1lAe6ctR3as7yqzW2BNItDFnaB5zQq/8M= github.com/bufbuild/protoplugin v0.0.0-20240323223605-e2735f6c31ee/go.mod h1:HjGFxsck9RObrTJp2hXQZfWhPgZqnR6sR1U5fCA/Kus= -github.com/bufbuild/protovalidate-go v0.6.2 h1:U/V3CGF0kPlR12v41rjO4DrYZtLcS4ZONLmWN+rJVCQ= -github.com/bufbuild/protovalidate-go v0.6.2/go.mod h1:4BR3rKEJiUiTy+sqsusFn2ladOf0kYmA2Reo6BHSBgQ= -github.com/bufbuild/protoyaml-go v0.1.9 h1:anV5UtF1Mlvkkgp4NWA6U/zOnJFng8Orq4Vf3ZUQHBU= -github.com/bufbuild/protoyaml-go v0.1.9/go.mod h1:KCBItkvZOK/zwGueLdH1Wx1RLyFn5rCH7YjQrdty2Wc= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/bufbuild/protovalidate-go v0.6.3 h1:wxQyzW035zM16Binbaz/nWAzS12dRIXhZdSUWRY7Fv0= +github.com/bufbuild/protovalidate-go v0.6.3/go.mod h1:J4PtwP9Z2YAGgB0+o+tTWEDtLtXvz/gfhFZD8pbzM/U= +github.com/bufbuild/protoyaml-go v0.1.10 h1:gMwDSHNoInt0D6vvTUxAJSWvp87MJraTN7dxsR7C2z4= +github.com/bufbuild/protoyaml-go v0.1.10/go.mod h1:KCBItkvZOK/zwGueLdH1Wx1RLyFn5rCH7YjQrdty2Wc= +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/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= @@ -35,12 +42,29 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= +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/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= +github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= +github.com/containerd/containerd v1.7.20 h1:Sl6jQYk3TRavaU83h66QMbI2Nqg9Jm6qzwX57Vsn1SQ= +github.com/containerd/containerd v1.7.20/go.mod h1:52GsS5CwquuqPuLncsXwG0t2CiUce+KsNHJZQJvAgR0= +github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= +github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= +github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM= +github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= 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/containerd/ttrpc v1.2.5 h1:IFckT1EFQoFBMG4c3sMdT8EP3/aKfumK1msY+Ze4oLU= +github.com/containerd/ttrpc v1.2.5/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= +github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso= +github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g= github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.4/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/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -48,18 +72,22 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/cli v26.1.4+incompatible h1:I8PHdc0MtxEADqYJZvhBrW9bo8gawKwwenxRM7/rLu8= -github.com/docker/cli v26.1.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v27.1.2+incompatible h1:nYviRv5Y+YAKx3dFrTvS1ErkyVVunKOhoweCTE1BsnI= +github.com/docker/cli v27.1.2+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 v27.0.0+incompatible h1:JRugTYuelmWlW0M3jakcIadDx2HUoUO6+Tf2C5jVfwA= -github.com/docker/docker v27.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.2+incompatible h1:AhGzR1xaQIy53qCkxARaFluI00WPGtXn0AJuoQsVYTY= +github.com/docker/docker v27.1.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/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/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/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= @@ -67,8 +95,8 @@ github.com/felixge/fgprof v0.9.4 h1:ocDNwMFlnA0NU0zSB3I52xkO4sFXk80VK9lXjLClu88= github.com/felixge/fgprof v0.9.4/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM= 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.14 h1:PyEwo2Vudraa0x/Wl6eDRRW2NXBvekgfxyydcM0WGE0= -github.com/go-chi/chi/v5 v5.0.14/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= +github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -77,24 +105,47 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= -github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gofrs/uuid/v5 v5.2.0 h1:qw1GMx6/y8vhVsx626ImfKMuS5CvJmhIKKtuyvfajMM= -github.com/gofrs/uuid/v5 v5.2.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= +github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= +github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= +github.com/gofrs/uuid/v5 v5.3.0 h1:m0mUMr+oVYUdxpMLgSYCZiXe7PuVPnI94+OMeVBNedk= +github.com/gofrs/uuid/v5 v5.3.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= 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/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84= -github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg= +github.com/google/cel-go v0.21.0 h1:cl6uW/gxN+Hy50tNYvI691+sXxioCnstFzLp2WO4GCI= +github.com/google/cel-go v0.21.0/go.mod h1:rHUlWCcBKgyEk+eV03RPdZUekPp6YcJwV0FxuUksYxc= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-containerregistry v0.19.2 h1:TannFKE1QSajsP6hPWb5oJNgKe1IKjHukIKDUmvsV6w= -github.com/google/go-containerregistry v0.19.2/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI= +github.com/google/go-containerregistry v0.20.2 h1:B1wPJ1SN/S7pB+ZAimcciVD+r+yV/l/DSArMxlbwseo= +github.com/google/go-containerregistry v0.20.2/go.mod h1:z38EKdKh4h7IP2gSfUUqEvalZBqs6AoLeWfUy34nQC8= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= -github.com/google/pprof v0.0.0-20240622144329-c177fd99eaa9 h1:ouFdLLCOyCfnxGpQTMZKHLyHr/D1GFbQzEsJxumO16E= -github.com/google/pprof v0.0.0-20240622144329-c177fd99eaa9/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= +github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k= +github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= @@ -122,6 +173,20 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= +github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/mount v0.3.4 h1:yn5jq4STPztkkzSKpZkLcmjue+bZJ0u2AuQY1iNI1Ww= +github.com/moby/sys/mount v0.3.4/go.mod h1:KcQJMbQdJHPlq5lcYT+/CjatWM4PuxKe+XLSVS4J6Os= +github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= +github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= +github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= +github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= +github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= +github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= +github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= +github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= @@ -130,17 +195,26 @@ 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 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk= +github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= +github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= 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.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +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/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po= github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -166,24 +240,26 @@ github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinC 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/contrib/instrumentation/net/http/otelhttp v0.50.0 h1:cEPbyTSEHlQR89XVlyo78gqluF8Y3oMeBkXGWzQsfXY= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.50.0/go.mod h1:DKdbWcT4GH1D0Y3Sqt/PFXt2naRKDWtU+eE6oLdFNA8= -go.opentelemetry.io/otel v1.25.0 h1:gldB5FfhRl7OJQbUHt/8s0a7cE8fbsPAtdpRaApKy4k= -go.opentelemetry.io/otel v1.25.0/go.mod h1:Wa2ds5NOXEMkCmUou1WA7ZBfLTHWIsp034OVD7AO+Vg= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= 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.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM= -go.opentelemetry.io/otel/metric v1.25.0 h1:LUKbS7ArpFL/I2jJHdJcqMGxkRdxpPHE0VU/D4NuEwA= -go.opentelemetry.io/otel/metric v1.25.0/go.mod h1:rkDLUSd2lC5lq2dFNrX9LGAbINP5B7WBkC78RXCpH5s= -go.opentelemetry.io/otel/sdk v1.25.0 h1:PDryEJPC8YJZQSyLY5eqLeafHtG+X7FWnf3aXMtxbqo= -go.opentelemetry.io/otel/sdk v1.25.0/go.mod h1:oFgzCM2zdsxKzz6zwpTZYLLQsFwc+K0daArPdIhuxkw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= +go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= go.opentelemetry.io/otel/sdk/metric v1.19.0 h1:EJoTO5qysMsYCa+w4UghwFV/ptQgqSL/8Ni+hx+8i1k= go.opentelemetry.io/otel/sdk/metric v1.19.0/go.mod h1:XjG0jQyFJrv2PbMvwND7LwCEhsJzCzV5210euduKcKY= -go.opentelemetry.io/otel/trace v1.25.0 h1:tqukZGLwQYRIFtSQM2u2+yfMVTgGVeqRLPUYx1Dq6RM= -go.opentelemetry.io/otel/trace v1.25.0/go.mod h1:hCCs70XM/ljO+BeQkyFnbK28SBIJ/Emuha+ccrCRT7I= -go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= -go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +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.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.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -195,25 +271,38 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= -golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= -golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI= +golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 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.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= -golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 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.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +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-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.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.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-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= @@ -223,32 +312,55 @@ golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= 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.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 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.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= -golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= 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-20240617180043-68d350f18fd4 h1:MuYw1wJzT+ZkybKfaOXKp5hJiZDn2iHaXRw0mRYdHSc= -google.golang.org/genproto/googleapis/api v0.0.0-20240617180043-68d350f18fd4/go.mod h1:px9SlOOZBg1wM1zdnr8jEL4CNGUBZ+ZKYtNPApNQc4c= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240617180043-68d350f18fd4 h1:Di6ANFilr+S60a4S61ZM00vLdw0IrQOSMS2/6mrnOU0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240617180043-68d350f18fd4/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= -google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= -google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= +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/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +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/googleapis/api v0.0.0-20240812133136-8ffd90a71988 h1:+/tmTy5zAieooKIXfzDm9KiA3Bv6JBwriRN9LY+yayk= +google.golang.org/genproto/googleapis/api v0.0.0-20240812133136-8ffd90a71988/go.mod h1:4+X6GvPs+25wZKbQq9qyAXrwIRExv7w0Ea6MgZLZiDM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240812133136-8ffd90a71988 h1:V71AcdLZr2p8dC9dbOIMCpqi4EmRl8wUwnJzXXLmbmc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240812133136-8ffd90a71988/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +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= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -259,3 +371,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/tools/src/golangci-lint/go.mod b/tools/src/golangci-lint/go.mod index 9442b7aa814..ce5cce24914 100644 --- a/tools/src/golangci-lint/go.mod +++ b/tools/src/golangci-lint/go.mod @@ -2,7 +2,7 @@ module local go 1.22.5 -require github.com/golangci/golangci-lint v1.59.1 +require github.com/golangci/golangci-lint v1.60.1 require ( 4d63.com/gocheckcompilerdirectives v1.2.1 // indirect @@ -11,11 +11,11 @@ require ( github.com/Abirdcfly/dupword v0.0.14 // indirect github.com/Antonboom/errname v0.1.13 // indirect github.com/Antonboom/nilnil v0.1.9 // indirect - github.com/Antonboom/testifylint v1.3.1 // indirect - github.com/BurntSushi/toml v1.4.0 // indirect - github.com/Crocmagnon/fatcontext v0.2.2 // indirect + github.com/Antonboom/testifylint v1.4.3 // indirect + github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect + github.com/Crocmagnon/fatcontext v0.4.0 // indirect github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect - github.com/GaijinEntertainment/go-exhaustruct/v3 v3.2.0 // indirect + github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect github.com/OpenPeeDeeP/depguard/v2 v2.2.0 // indirect github.com/alecthomas/go-check-sumtype v0.1.4 // indirect @@ -27,7 +27,7 @@ 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/v4 v4.2.1 // indirect + github.com/bombsimon/wsl/v4 v4.4.1 // indirect github.com/breml/bidichk v0.2.7 // indirect github.com/breml/errchkjson v0.3.6 // indirect github.com/butuzov/ireturn v0.3.0 // indirect @@ -60,7 +60,7 @@ require ( github.com/go-viper/mapstructure/v2 v2.0.0 // 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/gofrs/flock v0.12.1 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect github.com/golangci/gofmt v0.0.0-20231018234816-f50ced29576e // indirect @@ -82,7 +82,7 @@ require ( github.com/jgautheron/goconst v1.7.1 // 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.6.1 // indirect + github.com/jjti/go-spancheck v0.6.2 // indirect github.com/julz/importas v0.1.0 // indirect github.com/karamaru-alpha/copyloopvar v1.1.0 // indirect github.com/kisielk/errcheck v1.7.0 // indirect @@ -104,12 +104,11 @@ require ( 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/mgechev/revive v1.3.7 // indirect + github.com/mgechev/revive v1.3.9 // 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/moricho/tparallel v0.3.2 // indirect github.com/nakabonne/nestif v0.3.1 // 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.16.2 // indirect @@ -117,7 +116,7 @@ require ( github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/polyfloyd/go-errorlint v1.5.2 // indirect + github.com/polyfloyd/go-errorlint v1.6.0 // 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 @@ -127,22 +126,22 @@ require ( github.com/quasilyte/gogrep v0.5.0 // indirect github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect - github.com/ryancurrah/gomodguard v1.3.2 // indirect + github.com/ryancurrah/gomodguard v1.3.3 // indirect github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect github.com/sanposhiho/wastedassign/v2 v2.0.7 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect - github.com/sashamelentyev/usestdlibvars v1.26.0 // indirect + github.com/sashamelentyev/usestdlibvars v1.27.0 // indirect github.com/securego/gosec/v2 v2.20.1-0.20240525090044-5f0084eb01a9 // 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 - github.com/sivchari/tenv v1.7.1 // indirect + github.com/sivchari/tenv v1.10.0 // indirect github.com/sonatard/noctx v0.0.2 // indirect github.com/sourcegraph/go-diff v0.7.0 // 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/cobra v1.8.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.12.0 // indirect @@ -151,7 +150,6 @@ require ( github.com/stretchr/objx v0.5.2 // indirect github.com/stretchr/testify v1.9.0 // indirect 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.16 // indirect github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 // indirect @@ -160,31 +158,30 @@ require ( github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect github.com/ultraware/funlen v0.1.0 // indirect github.com/ultraware/whitespace v0.1.1 // indirect - github.com/uudashr/gocognit v1.1.2 // indirect + github.com/uudashr/gocognit v1.1.3 // indirect github.com/xen0n/gosmopolitan v1.2.2 // indirect github.com/yagipy/maintidx v1.0.0 // indirect github.com/yeya24/promlinter v0.3.0 // indirect github.com/ykadowak/zerologlint v0.1.5 // indirect gitlab.com/bosi/decorder v0.4.2 // indirect go-simpler.org/musttag v0.12.2 // indirect - go-simpler.org/sloglint v0.7.1 // indirect + go-simpler.org/sloglint v0.7.2 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/automaxprocs v1.5.3 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.24.0 // indirect golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc // indirect golang.org/x/exp/typeparams v0.0.0-20240314144324-c7f7c6466f7f // indirect - golang.org/x/mod v0.18.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/mod v0.20.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.23.0 // indirect golang.org/x/text v0.15.0 // indirect - golang.org/x/tools v0.22.0 // indirect + golang.org/x/tools v0.24.0 // indirect google.golang.org/protobuf v1.33.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.7 // indirect + honnef.co/go/tools v0.5.0 // indirect mvdan.cc/gofumpt v0.6.0 // indirect mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f // indirect ) diff --git a/tools/src/golangci-lint/go.sum b/tools/src/golangci-lint/go.sum index d5558afe589..81ac837888f 100644 --- a/tools/src/golangci-lint/go.sum +++ b/tools/src/golangci-lint/go.sum @@ -43,18 +43,18 @@ github.com/Antonboom/errname v0.1.13 h1:JHICqsewj/fNckzrfVSe+T33svwQxmjC+1ntDsHO github.com/Antonboom/errname v0.1.13/go.mod h1:uWyefRYRN54lBg6HseYCFhs6Qjcy41Y3Jl/dVhA87Ns= github.com/Antonboom/nilnil v0.1.9 h1:eKFMejSxPSA9eLSensFmjW2XTgTwJMjZ8hUHtV4s/SQ= github.com/Antonboom/nilnil v0.1.9/go.mod h1:iGe2rYwCq5/Me1khrysB4nwI7swQvjclR8/YRPl5ihQ= -github.com/Antonboom/testifylint v1.3.1 h1:Uam4q1Q+2b6H7gvk9RQFw6jyVDdpzIirFOOrbs14eG4= -github.com/Antonboom/testifylint v1.3.1/go.mod h1:NV0hTlteCkViPW9mSR4wEMfwp+Hs1T3dY60bkvSfhpM= +github.com/Antonboom/testifylint v1.4.3 h1:ohMt6AHuHgttaQ1xb6SSnxCeK4/rnK7KKzbvs7DmEck= +github.com/Antonboom/testifylint v1.4.3/go.mod h1:+8Q9+AOLsz5ZiQiiYujJKs9mNz398+M6UgslP4qgJLA= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= -github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= +github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Crocmagnon/fatcontext v0.2.2 h1:OrFlsDdOj9hW/oBEJBNSuH7QWf+E9WPVHw+x52bXVbk= -github.com/Crocmagnon/fatcontext v0.2.2/go.mod h1:WSn/c/+MMNiD8Pri0ahRj0o9jVpeowzavOQplBJw6u0= +github.com/Crocmagnon/fatcontext v0.4.0 h1:4ykozu23YHA0JB6+thiuEv7iT6xq995qS1vcuWZq0tg= +github.com/Crocmagnon/fatcontext v0.4.0/go.mod h1:ZtWrXkgyfsYPzS6K3O88va6t2GEglG93vnII/F94WC0= 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.2.0 h1:sATXp1x6/axKxz2Gjxv8MALP0bXaNRfQinEwyfMcx8c= -github.com/GaijinEntertainment/go-exhaustruct/v3 v3.2.0/go.mod h1:Nl76DrGNJTA1KJ0LePKBw/vznBX1EHbAZX8mwjR82nI= +github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0 h1:/fTUt5vmbkAcMBt4YQiuC23cV0kEsN1MVMNqeOW43cU= +github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0/go.mod h1:ONJg5sxcbsdQQ4pOW8TGdTidT2TMAUy/2Xhr8mrYaao= github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/OpenPeeDeeP/depguard/v2 v2.2.0 h1:vDfG60vDtIuf0MEOhmLlLLSzqaRM8EMcgJPdp74zmpA= @@ -90,8 +90,8 @@ 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/v4 v4.2.1 h1:Cxg6u+XDWff75SIFFmNsqnIOgob+Q9hG6y/ioKbRFiM= -github.com/bombsimon/wsl/v4 v4.2.1/go.mod h1:Xu/kDxGZTofQcDGCtQe9KCzhHphIe0fDuyWTxER9Feo= +github.com/bombsimon/wsl/v4 v4.4.1 h1:jfUaCkN+aUpobrMO24zwyAMwMAV5eSziCkOKEauOLdw= +github.com/bombsimon/wsl/v4 v4.4.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= @@ -119,7 +119,7 @@ github.com/ckaznocha/intrange v0.1.2 h1:3Y4JAxcMntgb/wABQ6e8Q8leMd26JbX2790lIss9 github.com/ckaznocha/intrange v0.1.2/go.mod h1:RWffCw/vKBwHeOEwWdCikAtY0q4gGt8VhJZEEA5n+RE= 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/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4/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.13.4 h1:61UGkmpoAcxHM2hhNkZEf5SzwQtWJXTSws7jaPyqwlw= @@ -190,8 +190,8 @@ github.com/go-xmlfmt/xmlfmt v1.1.2 h1:Nea7b4icn8s57fTx1M5AI4qQT5HEM3rVUO8MuE6g80 github.com/go-xmlfmt/xmlfmt v1.1.2/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= +github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -226,8 +226,8 @@ github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9 github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= 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.59.1 h1:CRRLu1JbhK5avLABFJ/OHVSQ0Ie5c4ulsOId1h3TTks= -github.com/golangci/golangci-lint v1.59.1/go.mod h1:jX5Oif4C7P0j9++YB2MMJmoNrb01NJ8ITqKWNLewThg= +github.com/golangci/golangci-lint v1.60.1 h1:DRKNqNTQRLBJZ1il5u4fvgLQCjQc7QFs0DbhksJtVJE= +github.com/golangci/golangci-lint v1.60.1/go.mod h1:jDIPN1rYaIA+ijp9OZcUmUCoQOtZ76pOlFbi15FlLJY= github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs= github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo= github.com/golangci/modinfo v0.3.4 h1:oU5huX3fbxqQXdfspamej74DFX0kyGLkw1ppvXoJ8GA= @@ -301,8 +301,8 @@ github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjz 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.6.1 h1:ZK/wE5Kyi1VX3PJpUO2oEgeoI4FWOUm7Shb2Gbv5obI= -github.com/jjti/go-spancheck v0.6.1/go.mod h1:vF1QkOO159prdo6mHRxak2CpzDpHAfKiPUDP/NeRnX8= +github.com/jjti/go-spancheck v0.6.2 h1:iYtoxqPMzHUPp7St+5yA8+cONdyXD3ug6KK15n7Pklk= +github.com/jjti/go-spancheck v0.6.2/go.mod h1:+X7lvIrR5ZdUTkxFYqzJ0abr8Sb5LOo80uOhWNqIrYA= 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= @@ -368,8 +368,8 @@ github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/Qd 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/mgechev/revive v1.3.7 h1:502QY0vQGe9KtYJ9FpxMz9rL+Fc/P13CI5POL4uHCcE= -github.com/mgechev/revive v1.3.7/go.mod h1:RJ16jUbF0OWC3co/+XTxmFNgEpUPwnnA0BRllX2aDNA= +github.com/mgechev/revive v1.3.9 h1:18Y3R4a2USSBF+QZKFQwVkBROUda7uoBlkEuBD+YD1A= +github.com/mgechev/revive v1.3.9/go.mod h1:+uxEIr5UH0TjXWHTno3xh4u7eg6jDpXKzQccA9UGhHU= 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= @@ -379,14 +379,12 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/moricho/tparallel v0.3.1 h1:fQKD4U1wRMAYNngDonW5XupoB/ZGJHdpzrWqgyg9krA= -github.com/moricho/tparallel v0.3.1/go.mod h1:leENX2cUv7Sv2qDgdi0D0fCftN8fRC67Bcn8pqzeYNI= +github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI= +github.com/moricho/tparallel v0.3.2/go.mod h1:OQ+K3b4Ln3l2TZveGCywybl68glfLEwFGqvnjok8b+U= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= 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.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= @@ -416,8 +414,8 @@ 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/polyfloyd/go-errorlint v1.5.2 h1:SJhVik3Umsjh7mte1vE0fVZ5T1gznasQG3PV7U5xFdA= -github.com/polyfloyd/go-errorlint v1.5.2/go.mod h1:sH1QC1pxxi0fFecsVIzBmxtrgd9IF/SkJpA6wqyKAJs= +github.com/polyfloyd/go-errorlint v1.6.0 h1:tftWV9DE7txiFzPpztTAwyoRLKNj9gpVm2cg8/OwcYY= +github.com/polyfloyd/go-errorlint v1.6.0/go.mod h1:HR7u8wuP1kb1NeN1zqTd1ZMlqUKPPHF+Id4vIPvDqVw= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -456,8 +454,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR 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.2 h1:CuG27ulzEB1Gu5Dk5gP8PFxSOZ3ptSdP5iI/3IXxM18= -github.com/ryancurrah/gomodguard v1.3.2/go.mod h1:LqdemiFomEjcxOqirbQCb3JFvSxH2JUYMerTFd3sF2o= +github.com/ryancurrah/gomodguard v1.3.3 h1:eiSQdJVNr9KTNxY2Niij8UReSwR8Xrte3exBrAZfqpg= +github.com/ryancurrah/gomodguard v1.3.3/go.mod h1:rsKQjj4l3LXe8N344Ow7agAy5p9yjsWOtRzUMYmA0QY= github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU= github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= github.com/sanposhiho/wastedassign/v2 v2.0.7 h1:J+6nrY4VW+gC9xFzUc+XjPD3g3wF3je/NsJFwFK7Uxc= @@ -466,8 +464,8 @@ github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6Ng github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= 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.26.0 h1:LONR2hNVKxRmzIrZR0PhSF3mhCAzvnr+DcUiHgREfXE= -github.com/sashamelentyev/usestdlibvars v1.26.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= +github.com/sashamelentyev/usestdlibvars v1.27.0 h1:t/3jZpSXtRPRf2xr0m63i32ZrusyurIGT9E5wAvXQnI= +github.com/sashamelentyev/usestdlibvars v1.27.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= github.com/securego/gosec/v2 v2.20.1-0.20240525090044-5f0084eb01a9 h1:rnO6Zp1YMQwv8AyxzuwsVohljJgp4L0ZqiCgtACsPsc= github.com/securego/gosec/v2 v2.20.1-0.20240525090044-5f0084eb01a9/go.mod h1:dg7lPlu/xK/Ut9SedURCoZbVCR4yC7fM65DtH9/CDHs= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= @@ -481,8 +479,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE= github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4= -github.com/sivchari/tenv v1.7.1 h1:PSpuD4bu6fSmtWMxSGWcvqUUgIn7k3yOJhOIzVWn8Ak= -github.com/sivchari/tenv v1.7.1/go.mod h1:64yStXKSOxDfX47NlhVwND4dHwfZDdbp2Lyl018Icvg= +github.com/sivchari/tenv v1.10.0 h1:g/hzMA+dBCKqGXgW8AV/1xIWhAvDrx0zFKNR48NFMg0= +github.com/sivchari/tenv v1.10.0/go.mod h1:tdY24masnVoZFxYrHv/nD6Tc8FbkEtAQEEziXpyMgqY= 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= @@ -491,8 +489,8 @@ 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= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -521,8 +519,6 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= -github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c h1:+aPplBwWcHBo6q9xrfWdMrT9o4kltkmmvpemgIjep/8= -github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c/go.mod h1:SbErYREK7xXdsRiigaQiQkI9McGRzYMvlKYaP3Nimdk= github.com/tdakkota/asciicheck v0.2.0 h1:o8jvnUANo0qXtnslk2d3nMKTFNlOnJjRrNcj0j9qkHM= github.com/tdakkota/asciicheck v0.2.0/go.mod h1:Qb7Y9EgjCLJGup51gDHFzbI08/gbGhL/UVhYIPWG2rg= github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA= @@ -543,8 +539,8 @@ github.com/ultraware/funlen v0.1.0 h1:BuqclbkY6pO+cvxoq7OsktIXZpgBSkYTQtmwhAK81v github.com/ultraware/funlen v0.1.0/go.mod h1:XJqmOQja6DpxarLj6Jj1U7JuoS8PvL4nEqDaQhy22p4= github.com/ultraware/whitespace v0.1.1 h1:bTPOGejYFulW3PkcrqkeQwOd6NKOOXvmGD9bo/Gk8VQ= github.com/ultraware/whitespace v0.1.1/go.mod h1:XcP1RLD81eV4BW8UhQlpaR+SDc2givTvyI8a586WjW8= -github.com/uudashr/gocognit v1.1.2 h1:l6BAEKJqQH2UpKAPKdMfZf5kE4W/2xk8pfU1OVLvniI= -github.com/uudashr/gocognit v1.1.2/go.mod h1:aAVdLURqcanke8h3vg35BC++eseDm66Z7KmchI5et4k= +github.com/uudashr/gocognit v1.1.3 h1:l+a111VcDbKfynh+airAy/DJQKaXh2m9vkoysMPSZyM= +github.com/uudashr/gocognit v1.1.3/go.mod h1:aKH8/e8xbTRBwjbCkwZ8qt4l2EpKXl31KMHgSS+lZ2U= github.com/xen0n/gosmopolitan v1.2.2 h1:/p2KTnMzwRexIW8GlKawsTWOxn7UHA+jCMF/V8HHtvU= github.com/xen0n/gosmopolitan v1.2.2/go.mod h1:7XX7Mj61uLYrj0qmeN0zi7XDon9JRAEhYQqAPLVNTeg= github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= @@ -566,8 +562,8 @@ go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ= go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= go-simpler.org/musttag v0.12.2 h1:J7lRc2ysXOq7eM8rwaTYnNrHd5JwjppzB6mScysB2Cs= go-simpler.org/musttag v0.12.2/go.mod h1:uN1DVIasMTQKk6XSik7yrJoEysGtR2GRqvWnI9S7TYM= -go-simpler.org/sloglint v0.7.1 h1:qlGLiqHbN5islOxjeLXoPtUdZXb669RW+BDQ+xOSNoU= -go-simpler.org/sloglint v0.7.1/go.mod h1:OlaVDRh/FKKd4X4sIMbsz8st97vomydceL146Fthh/c= +go-simpler.org/sloglint v0.7.2 h1:Wc9Em/Zeuu7JYpl+oKoYOsQSy2X560aVueCW/m6IijY= +go-simpler.org/sloglint v0.7.2/go.mod h1:US+9C80ppl7VsThQclkM7BkCHQAzuz8kHLsW3ppuluo= 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= @@ -635,8 +631,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.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= -golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.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= @@ -675,8 +671,8 @@ 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.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= 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= @@ -696,8 +692,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.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.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= @@ -743,7 +739,6 @@ golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220702020025-31831981b65f/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.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -752,8 +747,8 @@ 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.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= +golang.org/x/sys v0.23.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= @@ -830,14 +825,13 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 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.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= -golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= 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= @@ -923,8 +917,8 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks 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= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -945,8 +939,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.4.7 h1:9MDAWxMoSnB6QoSqiVr7P5mtkT9pOc1kSxchzPCnqJs= -honnef.co/go/tools v0.4.7/go.mod h1:+rnGS1THNh8zMwnd2oVOTL9QF6vmfyG6ZXBULae2uc0= +honnef.co/go/tools v0.5.0 h1:29uoiIormS3Z6R+t56STz/oI4v+mB51TSmEOdJPgRnE= +honnef.co/go/tools v0.5.0/go.mod h1:e9irvo83WDG9/irijV44wr3tbhcFeRnfpVlRqVwpzMs= mvdan.cc/gofumpt v0.6.0 h1:G3QvahNDmpD+Aek/bNOLrFR2XC6ZAdo62dZu65gmwGo= mvdan.cc/gofumpt v0.6.0/go.mod h1:4L0wf+kgIPZtcCWXynNS2e6bhmj73umwnuXSZarixzA= mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f h1:lMpcwN6GxNbWtbpI1+xzFLSW8XzX0u72NttUGVFjO3U= diff --git a/tools/src/kind/go.mod b/tools/src/kind/go.mod index ee24990f491..0d7c7342b1e 100644 --- a/tools/src/kind/go.mod +++ b/tools/src/kind/go.mod @@ -2,21 +2,20 @@ module github.com/envoyproxy/gateway/tools/src/kind go 1.22.5 -require sigs.k8s.io/kind v0.23.0 +require sigs.k8s.io/kind v0.24.0 require ( - github.com/BurntSushi/toml v1.0.0 // indirect - github.com/alessio/shellescape v1.4.1 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect + github.com/alessio/shellescape v1.4.2 // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 // indirect - github.com/inconshreveable/mousetrap v1.0.0 // indirect - github.com/mattn/go-isatty v0.0.14 // indirect - github.com/pelletier/go-toml v1.9.4 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/pelletier/go-toml v1.9.5 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/spf13/cobra v1.4.0 // indirect + github.com/spf13/cobra v1.8.0 // indirect github.com/spf13/pflag v1.0.5 // 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 + sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/tools/src/kind/go.sum b/tools/src/kind/go.sum index 2a0488c95c2..e811249cb1e 100644 --- a/tools/src/kind/go.sum +++ b/tools/src/kind/go.sum @@ -1,44 +1,42 @@ -github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU= -github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0= -github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= -github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -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/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/alessio/shellescape v1.4.2 h1:MHPfaU+ddJ0/bYWpgIeUnQUqKrlJ1S7BfEYPM4uEoM0= +github.com/alessio/shellescape v1.4.2/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= +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/safetext v0.0.0-20220905092116-b49f7bc46da2 h1:SJ+NtwL6QaZ21U+IrK7d0gGgpjGGvd2kz+FzTHVzdqI= github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2/go.mod h1:Tv1PlzqC9t8wNnpPdctvtSUOPUUg4SHeE6vR1Ir2hmg= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 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-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +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/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/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= -github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= 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/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -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/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= 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/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.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= 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= -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.23.0 h1:8fyDGWbWTeCcCTwA04v4Nfr45KKxbSPH1WO9K+jVrBg= -sigs.k8s.io/kind v0.23.0/go.mod h1:ZQ1iZuJLh3T+O8fzhdi3VWcFTzsdXtNv2ppsHc8JQ7s= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/kind v0.24.0 h1:g4y4eu0qa+SCeKESLpESgMmVFBebL0BDa6f777OIWrg= +sigs.k8s.io/kind v0.24.0/go.mod h1:t7ueEpzPYJvHA8aeLtI52rtFftNgUYUaCwvxjk7phfw= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=