diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index ce15ada7e85b..4fcd67ccb912 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@379614612a29c9e28f31f39a59013eb8012a51f0 # v3.24.3 + uses: github/codeql-action/init@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@379614612a29c9e28f31f39a59013eb8012a51f0 # v3.24.3 + uses: github/codeql-action/autobuild@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@379614612a29c9e28f31f39a59013eb8012a51f0 # v3.24.3 + uses: github/codeql-action/analyze@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 5596fb786381..12aa55a5b744 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@379614612a29c9e28f31f39a59013eb8012a51f0 # v3.24.3 + uses: github/codeql-action/upload-sarif@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 with: sarif_file: results.sarif diff --git a/LOGO.md b/LOGO.md new file mode 100644 index 000000000000..53e7f5256c4e --- /dev/null +++ b/LOGO.md @@ -0,0 +1,66 @@ +# Creative Brief - [Envoy Gateway] + +## Purpose / Background + +Envoy Gateway is an open-source initiative designed to streamline the deployment and management of Envoy Proxy as an API gateway. It offers a simple, expressive API that integrates seamlessly with Kubernetes, providing a user-friendly interface with sensible defaults and powerful customization options. The project aims to make application accessibility a trivial task for developers and simplify management for infrastructure administrators. + +## Target Date + +2024.03.01 + +## Target Audience + +- Application Developers +- Kubernetes Operators +- Infrastructure Administrators +- Open Source Community + +## Primary Stakeholders + +- Envoy Gateway Core Team +- Commercial API Gateway Vendors +- End Users (Businesses/Developers) + +## Perception + +Envoy Gateway is perceived as an intuitive, powerful, and flexible solution that democratizes access to advanced API gateway capabilities. The logo should reflect the project's ease of use, adaptability, and the robust foundation it provides for both simple and complex use cases. + +## Magnetic Idea + +The logo should convey the concept of "powerful simplicity" and "connectivity for all," highlighting the project's commitment to making advanced technology accessible to a broader audience. + +## Terminology Associated with this Brand Includes + +- Expressive API +- Kubernetes-Native +- Extensibility +- Batteries Included(EnvoyProxy) +- All Environments +- Simplified Management +- Kubernetes Gateway API + +## Competition: (Please list any competitors and/or potential members whose branding we should be aware of) + +- Gloo Edge +- Traefik +- NGINX Ingress Controller +- Kong + +## Design Suggestions + +The logo should be a variation of the Envoy Proxy logo also shares the same color palette. embody the project's core values of simplicity, power, and flexibility. A modern, clean design with elements that suggest connectivity, integration, and extension would be ideal. The use of familiar shapes or symbols that resonate with the target audience, such as abstract representations of gateways, bridges, or nodes, could be effective. + +## Creative Considerations & Distribution + +The logo must be versatile, scalable, and adaptable to various media, maintaining its integrity in both color and monochrome. It should be easily identifiable at different sizes, from large banners to small icons, and compatible with digital, print, and merchandise applications. + +## Primary Deliverables + +- Print-Ready Logo Artwork Files: SVG +- Screen-Optimized Logo Artwork Files: PNG + +## Additional Deliverables + +- Logo Usage Guidelines: PDF +- PowerPoint Template: PPTX +- Any Font Licenses and Files Needed diff --git a/api/v1alpha1/backendtrafficpolicy_types.go b/api/v1alpha1/backendtrafficpolicy_types.go index 41325dc09913..d72ee66923bf 100644 --- a/api/v1alpha1/backendtrafficpolicy_types.go +++ b/api/v1alpha1/backendtrafficpolicy_types.go @@ -16,7 +16,7 @@ const ( ) // +kubebuilder:object:root=true -// +kubebuilder:resource:shortName=btp +// +kubebuilder:resource:categories=envoy-gateway,shortName=btp // +kubebuilder:subresource:status // +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.conditions[?(@.type=="Accepted")].reason` // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` diff --git a/api/v1alpha1/clienttrafficpolicy_types.go b/api/v1alpha1/clienttrafficpolicy_types.go index 3037e4b0c041..836f5b687d6f 100644 --- a/api/v1alpha1/clienttrafficpolicy_types.go +++ b/api/v1alpha1/clienttrafficpolicy_types.go @@ -16,7 +16,7 @@ const ( ) // +kubebuilder:object:root=true -// +kubebuilder:resource:shortName=ctp +// +kubebuilder:resource:categories=envoy-gateway,shortName=ctp // +kubebuilder:subresource:status // +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.conditions[?(@.type=="Accepted")].reason` // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` diff --git a/api/v1alpha1/envoygateway_helpers.go b/api/v1alpha1/envoygateway_helpers.go index 25866ed12034..09077991c875 100644 --- a/api/v1alpha1/envoygateway_helpers.go +++ b/api/v1alpha1/envoygateway_helpers.go @@ -104,12 +104,12 @@ func DefaultEnvoyGatewayLogging() *EnvoyGatewayLogging { // GetEnvoyGatewayTelemetry returns the EnvoyGatewayTelemetry of EnvoyGateway or a default EnvoyGatewayTelemetry if unspecified. func (e *EnvoyGateway) GetEnvoyGatewayTelemetry() *EnvoyGatewayTelemetry { if e.Telemetry != nil { - if e.Telemetry.Metrics.Prometheus == nil { - e.Telemetry.Metrics.Prometheus = DefaultEnvoyGatewayPrometheus() - } if e.Telemetry.Metrics == nil { e.Telemetry.Metrics = DefaultEnvoyGatewayMetrics() } + if e.Telemetry.Metrics.Prometheus == nil { + e.Telemetry.Metrics.Prometheus = DefaultEnvoyGatewayPrometheus() + } return e.Telemetry } e.Telemetry = DefaultEnvoyGatewayTelemetry() diff --git a/api/v1alpha1/envoypatchpolicy_types.go b/api/v1alpha1/envoypatchpolicy_types.go index d9d45ec8f447..e646977286e8 100644 --- a/api/v1alpha1/envoypatchpolicy_types.go +++ b/api/v1alpha1/envoypatchpolicy_types.go @@ -17,7 +17,7 @@ const ( ) // +kubebuilder:object:root=true -// +kubebuilder:resource:shortName=epp +// +kubebuilder:resource:categories=envoy-gateway,shortName=epp // +kubebuilder:subresource:status // +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.conditions[?(@.type=="Programmed")].reason` // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` diff --git a/api/v1alpha1/envoyproxy_helpers.go b/api/v1alpha1/envoyproxy_helpers.go index cca9121f3f70..c34611271531 100644 --- a/api/v1alpha1/envoyproxy_helpers.go +++ b/api/v1alpha1/envoyproxy_helpers.go @@ -12,6 +12,7 @@ import ( autoscalingv2 "k8s.io/api/autoscaling/v2" v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" "k8s.io/utils/ptr" ) @@ -120,3 +121,13 @@ func (logging *ProxyLogging) GetEnvoyProxyComponentLevel() string { return strings.Join(args, ",") } + +// DefaultShutdownManagerContainerResourceRequirements returns a new ResourceRequirements with default settings. +func DefaultShutdownManagerContainerResourceRequirements() *v1.ResourceRequirements { + return &v1.ResourceRequirements{ + Requests: v1.ResourceList{ + v1.ResourceCPU: resource.MustParse(DefaultShutdownManagerCPUResourceRequests), + v1.ResourceMemory: resource.MustParse(DefaultShutdownManagerMemoryResourceRequests), + }, + } +} diff --git a/api/v1alpha1/envoyproxy_types.go b/api/v1alpha1/envoyproxy_types.go index 6f971644f5df..a8bb15057175 100644 --- a/api/v1alpha1/envoyproxy_types.go +++ b/api/v1alpha1/envoyproxy_types.go @@ -15,7 +15,7 @@ const ( ) // +kubebuilder:object:root=true -// +kubebuilder:resource:shortName=eproxy +// +kubebuilder:resource:categories=envoy-gateway,shortName=eproxy // +kubebuilder:subresource:status // EnvoyProxy is the schema for the envoyproxies API. @@ -81,6 +81,11 @@ type EnvoyProxySpec struct { // // +optional MergeGateways *bool `json:"mergeGateways,omitempty"` + + // Shutdown defines configuration for graceful envoy shutdown process. + // + // +optional + Shutdown *ShutdownConfig `json:"shutdown,omitempty"` } type ProxyTelemetry struct { @@ -115,6 +120,20 @@ type EnvoyProxyProvider struct { Kubernetes *EnvoyProxyKubernetesProvider `json:"kubernetes,omitempty"` } +// ShutdownConfig defines configuration for graceful envoy shutdown process. +type ShutdownConfig struct { + // DrainTimeout defines the graceful drain timeout. This should be less than the pod's terminationGracePeriodSeconds. + // If unspecified, defaults to 600 seconds. + // + // +optional + DrainTimeout *metav1.Duration `json:"drainTimeout,omitempty"` + // MinDrainDuration defines the minimum drain duration allowing time for endpoint deprogramming to complete. + // If unspecified, defaults to 5 seconds. + // + // +optional + MinDrainDuration *metav1.Duration `json:"minDrainDuration,omitempty"` +} + // EnvoyProxyKubernetesProvider defines configuration for the Kubernetes resource // provider. type EnvoyProxyKubernetesProvider struct { diff --git a/api/v1alpha1/jwt_types.go b/api/v1alpha1/jwt_types.go index 43e222743384..4948669a2923 100644 --- a/api/v1alpha1/jwt_types.go +++ b/api/v1alpha1/jwt_types.go @@ -19,6 +19,7 @@ type JWT struct { } // JWTProvider defines how a JSON Web Token (JWT) can be verified. +// +kubebuilder:validation:XValidation:rule="(has(self.recomputeRoute) && self.recomputeRoute) ? size(self.claimToHeaders) > 0 : true", message="claimToHeaders must be specified if recomputeRoute is enabled" type JWTProvider struct { // Name defines a unique name for the JWT provider. A name can have a variety of forms, // including RFC1123 subdomains, RFC 1123 labels, or RFC 1035 labels. @@ -52,8 +53,17 @@ type JWTProvider struct { // For examples, following config: // The claim must be of type; string, int, double, bool. Array type claims are not supported // + // +optional ClaimToHeaders []ClaimToHeader `json:"claimToHeaders,omitempty"` + // RecomputeRoute clears the route cache and recalculates the routing decision. + // This field must be enabled if the headers generated from the claim are used for + // route matching decisions. If the recomputation selects a new route, features targeting + // the new matched route will be applied. + // + // +optional + RecomputeRoute *bool `json:"recomputeRoute,omitempty"` + // ExtractFrom defines different ways to extract the JWT token from HTTP request. // If empty, it defaults to extract JWT token from the Authorization HTTP request header using Bearer schema // or access_token from query parameters. diff --git a/api/v1alpha1/kubernetes_helpers.go b/api/v1alpha1/kubernetes_helpers.go index 3dc553dea331..cd9ec84257cb 100644 --- a/api/v1alpha1/kubernetes_helpers.go +++ b/api/v1alpha1/kubernetes_helpers.go @@ -6,9 +6,14 @@ package v1alpha1 import ( + "encoding/json" + "fmt" + + jsonpatch "github.com/evanphx/json-patch" appv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/utils/ptr" ) @@ -121,3 +126,39 @@ func (hpa *KubernetesHorizontalPodAutoscalerSpec) setDefault() { hpa.Metrics = DefaultEnvoyProxyHpaMetrics() } } + +// ApplyMergePatch applies a merge patch to a deployment based on the merge type +func (deployment *KubernetesDeploymentSpec) ApplyMergePatch(old *appv1.Deployment) (*appv1.Deployment, error) { + if deployment.Patch == nil { + return old, nil + } + + var patchedJSON []byte + var err error + + // Serialize the current deployment to JSON + originalJSON, err := json.Marshal(old) + if err != nil { + return nil, fmt.Errorf("error marshaling original deployment: %w", err) + } + + switch { + case deployment.Patch.Type == nil || *deployment.Patch.Type == StrategicMerge: + patchedJSON, err = strategicpatch.StrategicMergePatch(originalJSON, deployment.Patch.Value.Raw, appv1.Deployment{}) + case *deployment.Patch.Type == JSONMerge: + patchedJSON, err = jsonpatch.MergePatch(originalJSON, deployment.Patch.Value.Raw) + default: + return nil, fmt.Errorf("unsupported merge type: %s", *deployment.Patch.Type) + } + if err != nil { + return nil, fmt.Errorf("error applying merge patch: %w", err) + } + + // Deserialize the patched JSON into a new deployment object + var patchedDeployment appv1.Deployment + if err := json.Unmarshal(patchedJSON, &patchedDeployment); err != nil { + return nil, fmt.Errorf("error unmarshaling patched deployment: %w", err) + } + + return &patchedDeployment, nil +} diff --git a/api/v1alpha1/securitypolicy_types.go b/api/v1alpha1/securitypolicy_types.go index 6d90536ae918..bb96b2ce688d 100644 --- a/api/v1alpha1/securitypolicy_types.go +++ b/api/v1alpha1/securitypolicy_types.go @@ -16,7 +16,7 @@ const ( ) // +kubebuilder:object:root=true -// +kubebuilder:resource:shortName=sp +// +kubebuilder:resource:categories=envoy-gateway,shortName=sp // +kubebuilder:subresource:status // +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.conditions[?(@.type=="Accepted")].reason` // +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` diff --git a/api/v1alpha1/shared_types.go b/api/v1alpha1/shared_types.go index 970c62ba6a1d..d0df95a96015 100644 --- a/api/v1alpha1/shared_types.go +++ b/api/v1alpha1/shared_types.go @@ -9,6 +9,7 @@ import ( appv1 "k8s.io/api/apps/v1" autoscalingv2 "k8s.io/api/autoscaling/v2" corev1 "k8s.io/api/core/v1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" ) const ( @@ -20,6 +21,12 @@ const ( DefaultDeploymentMemoryResourceRequests = "512Mi" // DefaultEnvoyProxyImage is the default image used by envoyproxy DefaultEnvoyProxyImage = "envoyproxy/envoy:distroless-dev" + // DefaultShutdownManagerCPUResourceRequests for shutdown manager cpu resource + DefaultShutdownManagerCPUResourceRequests = "10m" + // DefaultShutdownManagerMemoryResourceRequests for shutdown manager memory resource + DefaultShutdownManagerMemoryResourceRequests = "32Mi" + // DefaultShutdownManagerImage is the default image used for the shutdown manager. + DefaultShutdownManagerImage = "envoyproxy/gateway-dev:latest" // DefaultRateLimitImage is the default image used by ratelimit. DefaultRateLimitImage = "envoyproxy/ratelimit:master" // HTTPProtocol is the common-used http protocol. @@ -52,6 +59,11 @@ const ( // KubernetesDeploymentSpec defines the desired state of the Kubernetes deployment resource. type KubernetesDeploymentSpec struct { + // Patch defines how to perform the patch operation to deployment + // + // +optional + Patch *KubernetesPatchSpec `json:"patch,omitempty"` + // Replicas is the number of desired pods. Defaults to 1. // // +optional @@ -370,3 +382,25 @@ type KubernetesHorizontalPodAutoscalerSpec struct { // +kubebuilder:validation:Maximum=600 // +kubebuilder:validation:ExclusiveMaximum=true type HTTPStatus int + +// MergeType defines the type of merge operation +type MergeType string + +const ( + // StrategicMerge indicates a strategic merge patch type + StrategicMerge MergeType = "StrategicMerge" + // JSONMerge indicates a JSON merge patch type + JSONMerge MergeType = "JSONMerge" +) + +// KubernetesPatchSpec defines how to perform the patch operation +type KubernetesPatchSpec struct { + // Type is the type of merge operation to perform + // + // By default, StrategicMerge is used as the patch type. + // +optional + Type *MergeType `json:"type,omitempty"` + + // Object contains the raw configuration for merged object + Value apiextensionsv1.JSON `json:"value"` +} diff --git a/api/v1alpha1/validation/envoyproxy_validate.go b/api/v1alpha1/validation/envoyproxy_validate.go index a61973dcaafd..6dc7e116c895 100644 --- a/api/v1alpha1/validation/envoyproxy_validate.go +++ b/api/v1alpha1/validation/envoyproxy_validate.go @@ -73,6 +73,10 @@ func validateProvider(spec *egv1a1.EnvoyProxySpec) []error { if spec.Provider.Type != egv1a1.ProviderTypeKubernetes { errs = append(errs, fmt.Errorf("unsupported provider type %v", spec.Provider.Type)) } + validateDeploymentErrs := validateDeployment(spec) + if len(validateDeploymentErrs) != 0 { + errs = append(errs, validateDeploymentErrs...) + } validateServiceErrs := validateService(spec) if len(validateServiceErrs) != 0 { errs = append(errs, validateServiceErrs...) @@ -81,6 +85,21 @@ func validateProvider(spec *egv1a1.EnvoyProxySpec) []error { return errs } +func validateDeployment(spec *egv1a1.EnvoyProxySpec) []error { + var errs []error + if spec.Provider.Kubernetes != nil && spec.Provider.Kubernetes.EnvoyDeployment != nil { + if patch := spec.Provider.Kubernetes.EnvoyDeployment.Patch; patch != nil { + if patch.Value.Raw == nil { + errs = append(errs, fmt.Errorf("envoy deployment patch object cannot be empty")) + } + if patch.Type != nil && *patch.Type != egv1a1.JSONMerge && *patch.Type != egv1a1.StrategicMerge { + errs = append(errs, fmt.Errorf("unsupported envoy deployment patch type %s", *patch.Type)) + } + } + } + return errs +} + // TODO: remove this function if CEL validation became stable func validateService(spec *egv1a1.EnvoyProxySpec) []error { var errs []error diff --git a/api/v1alpha1/validation/envoyproxy_validate_test.go b/api/v1alpha1/validation/envoyproxy_validate_test.go index f13e8a921fbb..f476a5767af0 100644 --- a/api/v1alpha1/validation/envoyproxy_validate_test.go +++ b/api/v1alpha1/validation/envoyproxy_validate_test.go @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" + v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" @@ -447,6 +448,97 @@ func TestValidateEnvoyProxy(t *testing.T) { }, }, expected: true, + }, { + name: "should invalid when patch type is empty", + proxy: &egv1a1.EnvoyProxy{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test", + }, + Spec: egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + EnvoyDeployment: &egv1a1.KubernetesDeploymentSpec{ + Patch: &egv1a1.KubernetesPatchSpec{ + Value: v1.JSON{ + Raw: []byte{}, + }, + }, + }, + }, + }, + }, + }, + expected: true, + }, { + name: "should invalid when patch object is empty", + proxy: &egv1a1.EnvoyProxy{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test", + }, + Spec: egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + EnvoyDeployment: &egv1a1.KubernetesDeploymentSpec{ + Patch: &egv1a1.KubernetesPatchSpec{ + Type: ptr.To(egv1a1.StrategicMerge), + }, + }, + }, + }, + }, + }, + expected: false, + }, { + name: "should valid when patch type and object are both not empty", + proxy: &egv1a1.EnvoyProxy{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test", + }, + Spec: egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + EnvoyDeployment: &egv1a1.KubernetesDeploymentSpec{ + Patch: &egv1a1.KubernetesPatchSpec{ + Type: ptr.To(egv1a1.StrategicMerge), + Value: v1.JSON{ + Raw: []byte("{}"), + }, + }, + }, + }, + }, + }, + }, + expected: true, + }, { + name: "should valid when patch type is empty and object is not empty", + proxy: &egv1a1.EnvoyProxy{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test", + Name: "test", + }, + Spec: egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: egv1a1.ProviderTypeKubernetes, + Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{ + EnvoyDeployment: &egv1a1.KubernetesDeploymentSpec{ + Patch: &egv1a1.KubernetesPatchSpec{ + Value: v1.JSON{ + Raw: []byte("{}"), + }, + }, + }, + }, + }, + }, + }, + expected: true, }, } diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index d38d710885d3..237b4921293b 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -1341,6 +1341,11 @@ func (in *EnvoyProxySpec) DeepCopyInto(out *EnvoyProxySpec) { *out = new(bool) **out = **in } + if in.Shutdown != nil { + in, out := &in.Shutdown, &out.Shutdown + *out = new(ShutdownConfig) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyProxySpec. @@ -2026,6 +2031,11 @@ func (in *JWTProvider) DeepCopyInto(out *JWTProvider) { *out = make([]ClaimToHeader, len(*in)) copy(*out, *in) } + if in.RecomputeRoute != nil { + in, out := &in.RecomputeRoute, &out.RecomputeRoute + *out = new(bool) + **out = **in + } if in.ExtractFrom != nil { in, out := &in.ExtractFrom, &out.ExtractFrom *out = new(JWTExtractor) @@ -2105,6 +2115,11 @@ func (in *KubernetesDeployMode) DeepCopy() *KubernetesDeployMode { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *KubernetesDeploymentSpec) DeepCopyInto(out *KubernetesDeploymentSpec) { *out = *in + if in.Patch != nil { + in, out := &in.Patch, &out.Patch + *out = new(KubernetesPatchSpec) + (*in).DeepCopyInto(*out) + } if in.Replicas != nil { in, out := &in.Replicas, &out.Replicas *out = new(int32) @@ -2181,6 +2196,27 @@ func (in *KubernetesHorizontalPodAutoscalerSpec) DeepCopy() *KubernetesHorizonta return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubernetesPatchSpec) DeepCopyInto(out *KubernetesPatchSpec) { + *out = *in + if in.Type != nil { + in, out := &in.Type, &out.Type + *out = new(MergeType) + **out = **in + } + in.Value.DeepCopyInto(&out.Value) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesPatchSpec. +func (in *KubernetesPatchSpec) DeepCopy() *KubernetesPatchSpec { + if in == nil { + return nil + } + out := new(KubernetesPatchSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *KubernetesPodSpec) DeepCopyInto(out *KubernetesPodSpec) { *out = *in @@ -3245,6 +3281,31 @@ func (in *SecurityPolicyStatus) DeepCopy() *SecurityPolicyStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ShutdownConfig) DeepCopyInto(out *ShutdownConfig) { + *out = *in + if in.DrainTimeout != nil { + in, out := &in.DrainTimeout, &out.DrainTimeout + *out = new(v1.Duration) + **out = **in + } + if in.MinDrainDuration != nil { + in, out := &in.MinDrainDuration, &out.MinDrainDuration + *out = new(v1.Duration) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ShutdownConfig. +func (in *ShutdownConfig) DeepCopy() *ShutdownConfig { + if in == nil { + return nil + } + out := new(ShutdownConfig) + 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 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 680f1b19e9fb..858405b5c464 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -8,6 +8,8 @@ metadata: spec: group: gateway.envoyproxy.io names: + categories: + - envoy-gateway kind: BackendTrafficPolicy listKind: BackendTrafficPolicyList plural: backendtrafficpolicies 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 83141a9c569c..7378c7c07919 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml @@ -8,6 +8,8 @@ metadata: spec: group: gateway.envoyproxy.io names: + categories: + - envoy-gateway kind: ClientTrafficPolicy listKind: ClientTrafficPolicyList plural: clienttrafficpolicies 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 55590b7d7f0c..f157a84cd37a 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoypatchpolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoypatchpolicies.yaml @@ -8,6 +8,8 @@ metadata: spec: group: gateway.envoyproxy.io names: + categories: + - envoy-gateway kind: EnvoyPatchPolicy listKind: EnvoyPatchPolicyList plural: envoypatchpolicies 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 abb86ce60dd3..437f90927d0d 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -8,6 +8,8 @@ metadata: spec: group: gateway.envoyproxy.io names: + categories: + - envoy-gateway kind: EnvoyProxy listKind: EnvoyProxyList plural: envoyproxies @@ -2012,6 +2014,22 @@ spec: - name type: object type: array + patch: + description: Patch defines how to perform the patch operation + to deployment + properties: + type: + description: "Type is the type of merge operation + to perform \n By default, StrategicMerge is used + as the patch type." + type: string + value: + description: Object contains the raw configuration + for merged object + x-kubernetes-preserve-unknown-fields: true + required: + - value + type: object pod: description: Pod defines the desired specification of pod. @@ -6615,6 +6633,21 @@ spec: required: - type type: object + shutdown: + description: Shutdown defines configuration for graceful envoy shutdown + process. + properties: + drainTimeout: + description: DrainTimeout defines the graceful drain timeout. + This should be less than the pod's terminationGracePeriodSeconds. + If unspecified, defaults to 600 seconds. + type: string + minDrainDuration: + description: MinDrainDuration defines the minimum drain duration + allowing time for endpoint deprogramming to complete. If unspecified, + defaults to 5 seconds. + type: string + type: object telemetry: description: Telemetry defines telemetry parameters for managed proxies. properties: 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 7feb835b9387..fe4edffe69f2 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -8,6 +8,8 @@ metadata: spec: group: gateway.envoyproxy.io names: + categories: + - envoy-gateway kind: SecurityPolicy listKind: SecurityPolicyList plural: securitypolicies @@ -461,6 +463,13 @@ spec: maxLength: 253 minLength: 1 type: string + recomputeRoute: + description: RecomputeRoute clears the route cache and recalculates + the routing decision. This field must be enabled if the + headers generated from the claim are used for route matching + decisions. If the recomputation selects a new route, features + targeting the new matched route will be applied. + type: boolean remoteJWKS: description: RemoteJWKS defines how to fetch and cache JSON Web Key Sets (JWKS) from a remote HTTP/HTTPS endpoint. @@ -479,6 +488,11 @@ spec: - name - remoteJWKS type: object + x-kubernetes-validations: + - message: claimToHeaders must be specified if recomputeRoute + is enabled + rule: '(has(self.recomputeRoute) && self.recomputeRoute) ? + size(self.claimToHeaders) > 0 : true' maxItems: 4 minItems: 1 type: array diff --git a/examples/kubernetes/application.yaml b/examples/kubernetes/application.yaml index 27df9d63dd52..f5fa1b75cb32 100644 --- a/examples/kubernetes/application.yaml +++ b/examples/kubernetes/application.yaml @@ -37,7 +37,7 @@ spec: spec: serviceAccountName: backend containers: - - image: gcr.io/k8s-staging-ingressconformance/echoserver:v20221109-7ee2f3e + - image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e imagePullPolicy: IfNotPresent name: backend ports: diff --git a/examples/kubernetes/http-routing.yaml b/examples/kubernetes/http-routing.yaml index bbfc6cec8e08..2aadf48b6fc1 100644 --- a/examples/kubernetes/http-routing.yaml +++ b/examples/kubernetes/http-routing.yaml @@ -56,7 +56,7 @@ spec: spec: containers: - name: example-backend - image: gcr.io/k8s-staging-ingressconformance/echoserver:v20221109-7ee2f3e + image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e env: - name: POD_NAME valueFrom: @@ -119,7 +119,7 @@ spec: spec: containers: - name: foo-backend - image: gcr.io/k8s-staging-ingressconformance/echoserver:v20221109-7ee2f3e + image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e env: - name: POD_NAME valueFrom: @@ -186,7 +186,7 @@ spec: spec: containers: - name: bar-backend - image: gcr.io/k8s-staging-ingressconformance/echoserver:v20221109-7ee2f3e + image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e env: - name: POD_NAME valueFrom: @@ -233,7 +233,7 @@ spec: spec: containers: - name: bar-canary-backend - image: gcr.io/k8s-staging-ingressconformance/echoserver:v20221109-7ee2f3e + image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e env: - name: POD_NAME valueFrom: diff --git a/examples/kubernetes/mergepatch.yaml b/examples/kubernetes/mergepatch.yaml new file mode 100644 index 000000000000..20cf575c752b --- /dev/null +++ b/examples/kubernetes/mergepatch.yaml @@ -0,0 +1,115 @@ +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyProxy +metadata: + name: mergepatch + namespace: envoy-gateway-system +spec: + provider: + type: Kubernetes + kubernetes: + envoyDeployment: + merge: + type: StrategicMerge + object: + spec: + template: + spec: + hostNetwork: true + dnsPolicy: ClusterFirstWithHostNet +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: GatewayClass +metadata: + name: eg +spec: + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parametersRef: + group: gateway.envoyproxy.io + kind: EnvoyProxy + name: mergepatch + namespace: envoy-gateway-system +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: eg +spec: + gatewayClassName: eg + listeners: + - name: http + protocol: HTTP + port: 80 +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: backend +--- +apiVersion: v1 +kind: Service +metadata: + name: backend + labels: + app: backend + service: backend +spec: + ports: + - name: http + port: 3000 + targetPort: 3000 + selector: + app: backend +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: backend +spec: + replicas: 1 + selector: + matchLabels: + app: backend + version: v1 + template: + metadata: + labels: + app: backend + version: v1 + spec: + serviceAccountName: backend + containers: + - image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e + imagePullPolicy: IfNotPresent + name: backend + ports: + - containerPort: 3000 + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: backend +spec: + parentRefs: + - name: eg + hostnames: + - "www.example.com" + rules: + - backendRefs: + - group: "" + kind: Service + name: backend + port: 3000 + weight: 1 + matches: + - path: + type: PathPrefix + value: / diff --git a/examples/kubernetes/quickstart.yaml b/examples/kubernetes/quickstart.yaml index e70a4df59968..dcc84ef11c22 100644 --- a/examples/kubernetes/quickstart.yaml +++ b/examples/kubernetes/quickstart.yaml @@ -54,7 +54,7 @@ spec: spec: serviceAccountName: backend containers: - - image: gcr.io/k8s-staging-ingressconformance/echoserver:v20221109-7ee2f3e + - image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e imagePullPolicy: IfNotPresent name: backend ports: diff --git a/examples/kubernetes/tcp-routing.yaml b/examples/kubernetes/tcp-routing.yaml index cc203bd1cf38..619e66624350 100644 --- a/examples/kubernetes/tcp-routing.yaml +++ b/examples/kubernetes/tcp-routing.yaml @@ -70,7 +70,7 @@ spec: version: v1 spec: containers: - - image: gcr.io/k8s-staging-ingressconformance/echoserver:v20221109-7ee2f3e + - image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e imagePullPolicy: IfNotPresent name: backend-1 ports: @@ -104,7 +104,7 @@ spec: version: v1 spec: containers: - - image: gcr.io/k8s-staging-ingressconformance/echoserver:v20221109-7ee2f3e + - image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e imagePullPolicy: IfNotPresent name: backend-2 ports: diff --git a/examples/kubernetes/tls-passthrough.yaml b/examples/kubernetes/tls-passthrough.yaml index cde29cb0a749..2fd44e67d730 100644 --- a/examples/kubernetes/tls-passthrough.yaml +++ b/examples/kubernetes/tls-passthrough.yaml @@ -28,7 +28,7 @@ spec: spec: containers: - name: passthrough-echoserver - image: gcr.io/k8s-staging-ingressconformance/echoserver:v20221109-7ee2f3e + image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e ports: - containerPort: 8443 env: diff --git a/examples/kubernetes/tls-termination.yaml b/examples/kubernetes/tls-termination.yaml index 0ffc34c4637f..14eb84af022e 100644 --- a/examples/kubernetes/tls-termination.yaml +++ b/examples/kubernetes/tls-termination.yaml @@ -63,7 +63,7 @@ spec: spec: serviceAccountName: backend containers: - - image: gcr.io/k8s-staging-ingressconformance/echoserver:v20221109-7ee2f3e + - image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e imagePullPolicy: IfNotPresent name: backend ports: diff --git a/go.mod b/go.mod index 03c3b870e4fa..920e7c6f6c3b 100644 --- a/go.mod +++ b/go.mod @@ -23,15 +23,16 @@ require ( github.com/stretchr/testify v1.8.4 github.com/telepresenceio/watchable v0.0.0-20220726211108-9bb86f92afa7 github.com/tsaarni/certyaml v0.9.3 - go.opentelemetry.io/otel v1.23.1 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.23.1 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.23.1 + go.opentelemetry.io/otel v1.24.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.24.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.24.0 go.opentelemetry.io/otel/exporters/prometheus v0.45.0 - go.opentelemetry.io/otel/metric v1.23.1 - go.opentelemetry.io/otel/sdk/metric v1.23.1 + go.opentelemetry.io/otel/metric v1.24.0 + go.opentelemetry.io/otel/sdk/metric v1.24.0 go.opentelemetry.io/proto/otlp v1.1.0 go.uber.org/zap v1.26.0 golang.org/x/exp v0.0.0-20231006140011-7918f672742d + golang.org/x/sys v0.17.0 google.golang.org/grpc v1.61.1 google.golang.org/protobuf v1.32.0 gopkg.in/yaml.v3 v3.0.1 @@ -58,7 +59,7 @@ require ( github.com/chai2010/gettext-go v1.0.2 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect - github.com/evanphx/json-patch v5.7.0+incompatible // indirect + github.com/evanphx/json-patch v5.9.0+incompatible github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect @@ -101,15 +102,14 @@ require ( github.com/sirupsen/logrus v1.9.0 // indirect github.com/tsaarni/x500dn v1.0.0 // indirect github.com/xlab/treeprint v1.2.0 // indirect - go.opentelemetry.io/otel/sdk v1.23.1 // indirect - go.opentelemetry.io/otel/trace v1.23.1 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/mod v0.14.0 // indirect golang.org/x/net v0.20.0 // indirect golang.org/x/oauth2 v0.16.0 // indirect golang.org/x/sync v0.6.0 // indirect - golang.org/x/sys v0.16.0 // indirect golang.org/x/term v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect diff --git a/go.sum b/go.sum index 25bd45172f1a..3e6ac5c9f8f8 100644 --- a/go.sum +++ b/go.sum @@ -102,8 +102,8 @@ github.com/envoyproxy/ratelimit v1.4.1-0.20230427142404-e2a87f41d3a7 h1:yz9/p/8Q github.com/envoyproxy/ratelimit v1.4.1-0.20230427142404-e2a87f41d3a7/go.mod h1:NmJBO+gDMvSQWvcSWq8wmlgkDmHHAkx1SCxEGva5hKU= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI= -github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls= +github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.0.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= @@ -486,22 +486,22 @@ go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qL go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opentelemetry.io/otel v1.23.1 h1:Za4UzOqJYS+MUczKI320AtqZHZb7EqxO00jAHE0jmQY= -go.opentelemetry.io/otel v1.23.1/go.mod h1:Td0134eafDLcTS4y+zQ26GE8u3dEuRBiBCTUIRHaikA= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.23.1 h1:ZqRWZJGHXV/1yCcEEVJ6/Uz2JtM79DNS8OZYa3vVY/A= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.23.1/go.mod h1:D7ynngPWlGJrqyGSDOdscuv7uqttfCE3jcBvffDv9y4= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.23.1 h1:q/Nj5/2TZRIt6PderQ9oU0M00fzoe8UZuINGw6ETGTw= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.23.1/go.mod h1:DTE9yAu6r08jU3xa68GiSeI7oRcSEQ2RpKbbQGO+dWM= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.24.0 h1:f2jriWfOdldanBwS9jNBdeOKAQN7b4ugAMaNu1/1k9g= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.24.0/go.mod h1:B+bcQI1yTY+N0vqMpoZbEN7+XU4tNM0DmUiOwebFJWI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.24.0 h1:mM8nKi6/iFQ0iqst80wDHU2ge198Ye/TfN0WBS5U24Y= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.24.0/go.mod h1:0PrIIzDteLSmNyxqcGYRL4mDIo8OTuBAOI/Bn1URxac= go.opentelemetry.io/otel/exporters/prometheus v0.45.0 h1:BeIK2KGho0oCWa7LxEGSqfDZbs7Fpv/Viz+FS4P8CXE= go.opentelemetry.io/otel/exporters/prometheus v0.45.0/go.mod h1:UVJZPLnfDSvHj+eJuZE+E1GjIBD267mEMfAAHJdghWg= -go.opentelemetry.io/otel/metric v1.23.1 h1:PQJmqJ9u2QaJLBOELl1cxIdPcpbwzbkjfEyelTl2rlo= -go.opentelemetry.io/otel/metric v1.23.1/go.mod h1:mpG2QPlAfnK8yNhNJAxDZruU9Y1/HubbC+KyH8FaCWI= -go.opentelemetry.io/otel/sdk v1.23.1 h1:O7JmZw0h76if63LQdsBMKQDWNb5oEcOThG9IrxscV+E= -go.opentelemetry.io/otel/sdk v1.23.1/go.mod h1:LzdEVR5am1uKOOwfBWFef2DCi1nu3SA8XQxx2IerWFk= -go.opentelemetry.io/otel/sdk/metric v1.23.1 h1:T9/8WsYg+ZqIpMWwdISVVrlGb/N0Jr1OHjR/alpKwzg= -go.opentelemetry.io/otel/sdk/metric v1.23.1/go.mod h1:8WX6WnNtHCgUruJ4TJ+UssQjMtpxkpX0zveQC8JG/E0= -go.opentelemetry.io/otel/trace v1.23.1 h1:4LrmmEd8AU2rFvU1zegmvqW7+kWarxtNOPyeL6HmYY8= -go.opentelemetry.io/otel/trace v1.23.1/go.mod h1:4IpnpJFwr1mo/6HL8XIPJaE9y0+u1KcVmuW7dwFSVrI= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY= @@ -609,8 +609,8 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= diff --git a/internal/cmd/egctl/config.go b/internal/cmd/egctl/config.go index 83fafa69c70e..67ca0526443b 100644 --- a/internal/cmd/egctl/config.go +++ b/internal/cmd/egctl/config.go @@ -25,6 +25,7 @@ import ( "github.com/envoyproxy/gateway/internal/cmd/options" "github.com/envoyproxy/gateway/internal/infrastructure/kubernetes/proxy" kube "github.com/envoyproxy/gateway/internal/kubernetes" + "github.com/envoyproxy/gateway/internal/utils" ) var ( @@ -36,8 +37,9 @@ var ( ) const ( - adminPort = 19000 // TODO: make this configurable until EG support - containerName = "envoy" // TODO: make this configurable until EG support + adminPort = 19000 // TODO: make this configurable until EG support + rateLimitDebugPort = 6070 // TODO: make this configurable until EG support + containerName = "envoy" // TODO: make this configurable until EG support ) type aggregatedConfigDump map[string]map[string]protoreflect.ProtoMessage @@ -79,7 +81,7 @@ func retrieveConfigDump(args []string, includeEds bool, configType envoyConfigTy for _, pod := range pods { pod := pod go func() { - fw, err := portForwarder(cli, pod) + fw, err := portForwarder(cli, pod, adminPort) if err != nil { errs = errors.Join(errs, err) return @@ -168,7 +170,8 @@ func fetchRunningEnvoyPods(c kube.CLIClient, nn types.NamespacedName, labelSelec podsNamespacedNames := []types.NamespacedName{} for _, pod := range pods { - podNsName := types.NamespacedName{Namespace: pod.Namespace, Name: pod.Name} + pod := pod + podNsName := utils.NamespacedName(&pod) if pod.Status.Phase != "Running" { return podsNamespacedNames, fmt.Errorf("pod %s is not running", podNsName) } @@ -180,8 +183,8 @@ func fetchRunningEnvoyPods(c kube.CLIClient, nn types.NamespacedName, labelSelec } // portForwarder returns a port forwarder instance for a single Pod. -func portForwarder(cli kube.CLIClient, nn types.NamespacedName) (kube.PortForwarder, error) { - fw, err := kube.NewLocalPortForwarder(cli, nn, 0, adminPort) +func portForwarder(cli kube.CLIClient, nn types.NamespacedName, port int) (kube.PortForwarder, error) { + fw, err := kube.NewLocalPortForwarder(cli, nn, 0, port) if err != nil { return nil, err } diff --git a/internal/cmd/egctl/config_cmd.go b/internal/cmd/egctl/config_cmd.go index 3fd1ea02e0bd..242706f6d37d 100644 --- a/internal/cmd/egctl/config_cmd.go +++ b/internal/cmd/egctl/config_cmd.go @@ -23,6 +23,7 @@ func newConfigCommand() *cobra.Command { } cfgCommand.AddCommand(proxyCommand()) + cfgCommand.AddCommand(ratelimitCommand()) flags := cfgCommand.Flags() options.AddKubeConfigFlags(flags) @@ -35,6 +36,10 @@ func newConfigCommand() *cobra.Command { return cfgCommand } +func ratelimitCommand() *cobra.Command { + return ratelimitConfigCommand() +} + func proxyCommand() *cobra.Command { c := &cobra.Command{ Use: "envoy-proxy", diff --git a/internal/cmd/egctl/config_ratelimit.go b/internal/cmd/egctl/config_ratelimit.go new file mode 100644 index 000000000000..376ff65cd061 --- /dev/null +++ b/internal/cmd/egctl/config_ratelimit.go @@ -0,0 +1,226 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package egctl + +import ( + "context" + "errors" + "fmt" + "io" + "net/http" + + "github.com/spf13/cobra" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apimachinery/pkg/types" + cmdutil "k8s.io/kubectl/pkg/cmd/util" + + "github.com/envoyproxy/gateway/api/v1alpha1" + "github.com/envoyproxy/gateway/internal/envoygateway" + "github.com/envoyproxy/gateway/internal/infrastructure/kubernetes/ratelimit" + "github.com/envoyproxy/gateway/internal/kubernetes" +) + +var ( + defaultRateLimitNamespace = "envoy-gateway-system" // TODO: make this configurable until EG support + defaultConfigMap = "envoy-gateway-config" // TODO: make this configurable until EG support + defaultConfigMapKey = "envoy-gateway.yaml" // TODO: make this configurable until EG support +) + +func ratelimitConfigCommand() *cobra.Command { + + var ( + namespace string + ) + + rlConfigCmd := &cobra.Command{ + Use: "envoy-ratelimit", + Aliases: []string{"rl"}, + Long: `Retrieve the relevant rate limit configuration from the Rate Limit instance`, + Example: ` # Retrieve rate limit configuration + egctl config envoy-ratelimit + + # Retrieve rate limit configuration with short syntax + egctl c rl +`, + Run: func(c *cobra.Command, args []string) { + cmdutil.CheckErr(runRateLimitConfig(c, namespace)) + }, + } + + rlConfigCmd.Flags().StringVarP(&namespace, "namespace", "n", defaultRateLimitNamespace, "Specific a namespace to get resources") + return rlConfigCmd +} + +func runRateLimitConfig(c *cobra.Command, ns string) error { + + cli, err := getCLIClient() + if err != nil { + return err + } + + out, err := retrieveRateLimitConfig(cli, ns) + if err != nil { + return err + } + + _, err = fmt.Fprintln(c.OutOrStdout(), string(out)) + return err +} + +func retrieveRateLimitConfig(cli kubernetes.CLIClient, ns string) ([]byte, error) { + + // Before retrieving the rate limit configuration + // we make sure that the global rate limit feature is enabled + if enable, err := checkEnableGlobalRateLimit(cli); !enable { + return nil, fmt.Errorf("global rate limit feature is not enabled") + } else if err != nil { + return nil, fmt.Errorf("failed to get global rate limit status: %w", err) + } + + // Filter out all rate limit pods in the Running state + rlNN, err := fetchRunningRateLimitPods(cli, ns, ratelimit.LabelSelector()) + if err != nil { + return nil, err + } + + // In fact, the configuration of multiple rate limit replicas are the same. + // After we filter out the rate limit Pods in the Running state, + // we can directly use the first pod. + rlPod := rlNN[0] + fw, err := portForwarder(cli, rlPod, rateLimitDebugPort) + if err != nil { + return nil, fmt.Errorf("failed to initialize pod-forwarding for %s/%s: %w", rlPod.Namespace, rlPod.Name, err) + } + + return extractRateLimitConfig(fw, rlPod) +} + +// fetchRunningRateLimitPods gets the rate limit Pods, based on the labelSelectors. +// It further filters out only those rate limit Pods that are in "Running" state. +func fetchRunningRateLimitPods(cli kubernetes.CLIClient, namespace string, labelSelector []string) ([]types.NamespacedName, error) { + + // Since multiple replicas of the rate limit are configured to be equal, + // we do not need to use the pod name to obtain the specified pod. + rlPods, err := cli.PodsForSelector(namespace, labelSelector...) + if err != nil { + return nil, err + } + + rlNN := []types.NamespacedName{} + for _, rlPod := range rlPods.Items { + rlPodNsName := types.NamespacedName{ + Namespace: rlPod.Namespace, + Name: rlPod.Name, + } + + // Check that the rate limit pod is ready properly and can accept external traffic + if !checkRateLimitPodStatusReady(rlPod.Status) { + continue + } + + rlNN = append(rlNN, rlPodNsName) + } + if len(rlNN) == 0 { + return nil, fmt.Errorf("please check that the rate limit instance starts properly") + } + + return rlNN, nil +} + +// checkRateLimitPodStatusReady Check that the rate limit pod is ready +func checkRateLimitPodStatusReady(status corev1.PodStatus) bool { + + if status.Phase != corev1.PodRunning { + return false + } + + for _, condition := range status.Conditions { + if condition.Type == corev1.PodReady && + condition.Status == corev1.ConditionTrue { + return true + } + } + + return false +} + +// extractRateLimitConfig After turning on port forwarding through PortForwarder, +// construct a request and send it to the rate limit Pod to obtain relevant configuration information. +func extractRateLimitConfig(fw kubernetes.PortForwarder, rlPod types.NamespacedName) ([]byte, error) { + + if err := fw.Start(); err != nil { + return nil, fmt.Errorf("failed to start port forwarding for pod %s/%s: %w", rlPod.Namespace, rlPod.Name, err) + } + defer fw.Stop() + + out, err := rateLimitConfigRequest(fw.Address()) + if err != nil { + return nil, fmt.Errorf("failed to send request to get rate config for pod %s/%s: %w", rlPod.Namespace, rlPod.Name, err) + } + + return out, nil +} + +// checkEnableGlobalRateLimit Check whether the Global Rate Limit function is enabled +func checkEnableGlobalRateLimit(cli kubernetes.CLIClient) (bool, error) { + + kubeCli := cli.Kube() + cm, err := kubeCli.CoreV1(). + ConfigMaps(defaultRateLimitNamespace). + Get(context.TODO(), defaultConfigMap, metav1.GetOptions{}) + if err != nil { + return false, err + } + + config, ok := cm.Data[defaultConfigMapKey] + if !ok { + return false, fmt.Errorf("failed to get envoy-gateway configuration") + } + + decoder := serializer.NewCodecFactory(envoygateway.GetScheme()).UniversalDeserializer() + obj, gvk, err := decoder.Decode([]byte(config), nil, nil) + if err != nil { + return false, err + } + + if gvk.Group != v1alpha1.GroupVersion.Group || + gvk.Version != v1alpha1.GroupVersion.Version || + gvk.Kind != v1alpha1.KindEnvoyGateway { + return false, errors.New("failed to decode unmatched resource type") + } + + eg, ok := obj.(*v1alpha1.EnvoyGateway) + if !ok { + return false, errors.New("failed to convert object to EnvoyGateway type") + } + + if eg.RateLimit == nil || eg.RateLimit.Backend.Redis == nil { + return false, nil + } + + return true, nil +} + +func rateLimitConfigRequest(address string) ([]byte, error) { + url := fmt.Sprintf("http://%s/rlconfig", address) + + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + defer func() { + _ = resp.Body.Close() + }() + + return io.ReadAll(resp.Body) +} diff --git a/internal/cmd/egctl/config_test.go b/internal/cmd/egctl/config_test.go index 47a70c19fdee..ff1ad2f8ace4 100644 --- a/internal/cmd/egctl/config_test.go +++ b/internal/cmd/egctl/config_test.go @@ -18,7 +18,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/protobuf/reflect/protoreflect" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/kubernetes/fake" + "k8s.io/client-go/rest" + "github.com/envoyproxy/gateway/internal/infrastructure/kubernetes/ratelimit" kube "github.com/envoyproxy/gateway/internal/kubernetes" "github.com/envoyproxy/gateway/internal/utils/file" netutil "github.com/envoyproxy/gateway/internal/utils/net" @@ -79,6 +86,8 @@ func (fw *fakePortForwarder) Address() string { return fmt.Sprintf("localhost:%d", fw.localPort) } +func (fw *fakePortForwarder) WaitForStop() {} + func TestExtractAllConfigDump(t *testing.T) { input, err := readInputConfig("in.all.json") require.NoError(t, err) @@ -267,3 +276,267 @@ func sampleAggregatedConfigDump(configDump protoreflect.ProtoMessage) aggregated }, } } + +type fakeCLIClient struct { + pods []corev1.Pod + cm *corev1.ConfigMap +} + +func (f *fakeCLIClient) RESTConfig() *rest.Config { + return nil +} + +func (f *fakeCLIClient) Pod(types.NamespacedName) (*corev1.Pod, error) { + return nil, nil +} + +func (f *fakeCLIClient) PodsForSelector(string, ...string) (*corev1.PodList, error) { + return &corev1.PodList{Items: f.pods}, nil +} + +func (f *fakeCLIClient) PodExec(types.NamespacedName, string, string) (stdout string, stderr string, err error) { + return "", "", nil +} + +func (f *fakeCLIClient) Kube() kubernetes.Interface { + return fake.NewSimpleClientset(f.cm) +} + +func TestFetchRunningRateLimitPods(t *testing.T) { + + cases := []struct { + caseName string + rlPods []corev1.Pod + namespace string + labelSelector []string + expectErr error + }{ + { + caseName: "normally obtain the rate limit pod of Running phase", + rlPods: []corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "envoy-ratelimit-666457bc4c-c2td5", + Namespace: "envoy-gateway-system", + Labels: map[string]string{ + "app.kubernetes.io/name": "envoy-ratelimit", + "app.kubernetes.io/component": "ratelimit", + "app.kubernetes.io/managed-by": "envoy-gateway", + }, + }, + Status: corev1.PodStatus{ + Phase: corev1.PodRunning, + Conditions: []corev1.PodCondition{ + { + Type: corev1.PodReady, + Status: corev1.ConditionTrue, + }, + { + Type: corev1.ContainersReady, + Status: corev1.ConditionTrue, + }, + }, + }, + }, + }, + namespace: "envoy-gateway-system", + labelSelector: ratelimit.LabelSelector(), + expectErr: nil, + }, + { + caseName: "unable to obtain rate limit pod", + rlPods: []corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "envoy-ratelimit-666457bc4c-c2td5", + Namespace: "envoy-gateway-system", + }, + Status: corev1.PodStatus{ + Phase: corev1.PodPending, + }, + }, + }, + namespace: "envoy-gateway-system", + labelSelector: ratelimit.LabelSelector(), + expectErr: fmt.Errorf("please check that the rate limit instance starts properly"), + }, + } + + for _, tc := range cases { + + t.Run(tc.caseName, func(t *testing.T) { + + fakeCli := &fakeCLIClient{ + pods: tc.rlPods, + } + + _, err := fetchRunningRateLimitPods(fakeCli, tc.namespace, tc.labelSelector) + require.Equal(t, tc.expectErr, err) + + }) + + } +} + +func TestCheckEnableGlobalRateLimit(t *testing.T) { + + cases := []struct { + caseName string + egConfigMap *corev1.ConfigMap + expect bool + }{ + { + caseName: "global rate limit feature is enabled", + expect: true, + egConfigMap: &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "envoy-gateway-config", + Namespace: "envoy-gateway-system", + }, + Data: map[string]string{ + "envoy-gateway.yaml": ` +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyGateway +provider: + type: Kubernetes +gateway: + controllerName: gateway.envoyproxy.io/gatewayclass-controller +rateLimit: + backend: + type: Redis + redis: + url: redis.redis-system.svc.cluster.local:6379 +`, + }, + }, + }, + { + caseName: "global rate limit feature is not enabled", + expect: false, + egConfigMap: &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "envoy-gateway-config", + Namespace: "envoy-gateway-system", + }, + Data: map[string]string{ + "envoy-gateway.yaml": ` +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyGateway +provider: + type: Kubernetes +gateway: + controllerName: gateway.envoyproxy.io/gatewayclass-controller +`, + }, + }, + }, + } + + for _, tc := range cases { + + t.Run(tc.caseName, func(t *testing.T) { + + fakeCli := &fakeCLIClient{ + cm: tc.egConfigMap, + } + + actual, err := checkEnableGlobalRateLimit(fakeCli) + require.Equal(t, tc.expect, actual) + require.NoError(t, err) + + }) + + } +} + +func TestExtractRateLimitConfig(t *testing.T) { + + cases := []struct { + caseName string + responseBody []byte + rlPod types.NamespacedName + }{ + { + caseName: "rate limit configuration is extract normally", + responseBody: []byte("default/eg/http.httproute/default/backend/rule/0/match/0/*-key-rule-0-match-0_httproute/default/backend/rule/0/match/0/*-value-rule-0-match-0: unit=HOUR requests_per_unit=3, shadow_mode: false"), + rlPod: types.NamespacedName{ + Name: "envoy-ratelimit-666457bc4c-c2td5", + Namespace: "envoy-gateway-system", + }, + }, + } + + for _, tc := range cases { + + t.Run(tc.caseName, func(t *testing.T) { + + fw, err := newFakePortForwarder(tc.responseBody) + require.NoError(t, err) + + out, err := extractRateLimitConfig(fw, tc.rlPod) + require.NoError(t, err) + require.NotEmpty(t, out) + + }) + + } +} + +func TestCheckRateLimitPodStatusReady(t *testing.T) { + + cases := []struct { + caseName string + status corev1.PodStatus + expect bool + }{ + { + caseName: "rate limit pod is ready", + expect: true, + status: corev1.PodStatus{ + Phase: corev1.PodRunning, + Conditions: []corev1.PodCondition{ + { + Type: corev1.PodReady, + Status: corev1.ConditionTrue, + }, + { + Type: corev1.ContainersReady, + Status: corev1.ConditionTrue, + }, + }, + }, + }, + { + caseName: "rate limit pod is not ready", + expect: false, + status: corev1.PodStatus{ + Phase: corev1.PodRunning, + Conditions: []corev1.PodCondition{ + { + Type: corev1.PodReady, + Status: corev1.ConditionFalse, + }, + { + Type: corev1.ContainersReady, + Status: corev1.ConditionFalse, + }, + }, + }, + }, + { + caseName: "rate limit pod is running failed", + expect: false, + status: corev1.PodStatus{ + Phase: corev1.PodFailed, + }, + }, + } + + for _, tc := range cases { + t.Run(tc.caseName, func(t *testing.T) { + actual := checkRateLimitPodStatusReady(tc.status) + require.Equal(t, tc.expect, actual) + }) + } + +} diff --git a/internal/cmd/egctl/dashboard.go b/internal/cmd/egctl/dashboard.go new file mode 100644 index 000000000000..349662dbedab --- /dev/null +++ b/internal/cmd/egctl/dashboard.go @@ -0,0 +1,23 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package egctl + +import ( + "github.com/spf13/cobra" +) + +func newDashboardCommand() *cobra.Command { + c := &cobra.Command{ + Use: "dashboard", + Aliases: []string{"d"}, + Long: "Retrieve the dashboard.", + Short: "Retrieve the dashboard.", + } + + c.AddCommand(newEnvoyDashboardCmd()) + + return c +} diff --git a/internal/cmd/egctl/envoy_dashboard.go b/internal/cmd/egctl/envoy_dashboard.go new file mode 100644 index 000000000000..9b8f8bdf3274 --- /dev/null +++ b/internal/cmd/egctl/envoy_dashboard.go @@ -0,0 +1,138 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +package egctl + +import ( + "errors" + "fmt" + "io" + "os" + "os/exec" + "os/signal" + "runtime" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/types" + + kube "github.com/envoyproxy/gateway/internal/kubernetes" +) + +func newEnvoyDashboardCmd() *cobra.Command { + var podName, podNamespace string + var listenPort int + + dashboardCmd := &cobra.Command{ + Use: "envoy-proxy -n ", + Short: "Retrieve Envoy admin dashboard for the specified pod", + Long: `Retrieve Envoy admin dashboard for the specified pod.`, + Example: ` # Retrieve Envoy admin dashboard for the specified pod. + egctl experimental dashboard envoy-proxy -n + + # short syntax + egctl experimental d envoy-proxy -n +`, + Aliases: []string{"d"}, + Args: func(cmd *cobra.Command, args []string) error { + if len(args) != 1 && len(labelSelectors) == 0 { + cmd.Println(cmd.UsageString()) + return fmt.Errorf("dashboard requires pod name or label selector") + } + if len(args) > 0 && len(labelSelectors) > 0 { + cmd.Println(cmd.UsageString()) + return fmt.Errorf("name cannot be provided when a selector is specified") + } + return nil + }, + RunE: func(c *cobra.Command, args []string) error { + if listenPort > 65535 || listenPort < 0 { + return fmt.Errorf("invalid port number range") + } + + kubeClient, err := getCLIClient() + if err != nil { + return err + } + if len(args) != 0 { + podName = args[0] + } + if len(labelSelectors) > 0 { + pl, err := kubeClient.PodsForSelector(podNamespace, labelSelectors...) + if err != nil { + return fmt.Errorf("not able to locate pod with selector %s: %w", labelSelectors, err) + } + if len(pl.Items) < 1 { + return errors.New("no pods found") + } + podName = pl.Items[0].Name + podNamespace = pl.Items[0].Namespace + } + + return portForward(podName, podNamespace, "http://%s", listenPort, kubeClient, c.OutOrStdout()) + }, + } + dashboardCmd.PersistentFlags().StringArrayVarP(&labelSelectors, "labels", "l", nil, "Labels to select the envoy proxy pod.") + dashboardCmd.PersistentFlags().StringVarP(&podNamespace, "namespace", "n", "envoy-gateway-system", "Namespace where envoy proxy pod are installed.") + dashboardCmd.PersistentFlags().IntVarP(&listenPort, "port", "p", 0, "Local port to listen to.") + + return dashboardCmd +} + +// portForward first tries to forward localhost:remotePort to podName:remotePort, falls back to dynamic local port +func portForward(podName, namespace, urlFormat string, listenPort int, client kube.CLIClient, writer io.Writer) error { + var fw kube.PortForwarder + meta := types.NamespacedName{ + Namespace: namespace, + Name: podName, + } + fw, err := kube.NewLocalPortForwarder(client, meta, listenPort, adminPort) + if err != nil { + return fmt.Errorf("could not build port forwarder for envoy proxy: %w", err) + } + + if err = fw.Start(); err != nil { + fw.Stop() + return fmt.Errorf("could not start port forwarder for envoy proxy: %w", err) + } + + ClosePortForwarderOnInterrupt(fw) + + openBrowser(fmt.Sprintf(urlFormat, fw.Address()), writer) + + fw.WaitForStop() + + return nil +} + +func ClosePortForwarderOnInterrupt(fw kube.PortForwarder) { + go func() { + signals := make(chan os.Signal, 1) + signal.Notify(signals, os.Interrupt) + defer signal.Stop(signals) + <-signals + fw.Stop() + }() +} + +func openBrowser(url string, writer io.Writer) { + var err error + + fmt.Fprintf(writer, "%s\n", url) + + switch runtime.GOOS { + case "linux": + err = exec.Command("xdg-open", url).Start() + case "windows": + err = exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start() + case "darwin": + err = exec.Command("open", url).Start() + default: + fmt.Fprintf(writer, "Unsupported platform %q; open %s in your browser.\n", runtime.GOOS, url) + } + + if err != nil { + fmt.Fprintf(writer, "Failed to open browser; open %s in your browser.\n", url) + } +} diff --git a/internal/cmd/egctl/envoy_stats.go b/internal/cmd/egctl/envoy_stats.go index 527529c9cbf3..c7701da0bcd9 100644 --- a/internal/cmd/egctl/envoy_stats.go +++ b/internal/cmd/egctl/envoy_stats.go @@ -146,7 +146,7 @@ func setupEnvoyServerStatsConfig(kubeClient kubernetes.CLIClient, podName, podNa path += "/prometheus" } - fw, err := portForwarder(kubeClient, types.NamespacedName{Namespace: podNamespace, Name: podName}) + fw, err := portForwarder(kubeClient, types.NamespacedName{Namespace: podNamespace, Name: podName}, adminPort) if err != nil { return "", fmt.Errorf("failed to initialize pod-forwarding for %s/%s: %w", podNamespace, podName, err) } @@ -169,7 +169,7 @@ func setupEnvoyClusterStatsConfig(kubeClient kubernetes.CLIClient, podName, podN // for yaml output we will convert the json to yaml when printed path += "?format=json" } - fw, err := portForwarder(kubeClient, types.NamespacedName{Namespace: podNamespace, Name: podName}) + fw, err := portForwarder(kubeClient, types.NamespacedName{Namespace: podNamespace, Name: podName}, adminPort) if err != nil { return "", fmt.Errorf("failed to initialize pod-forwarding for %s/%s: %w", podNamespace, podName, err) } diff --git a/internal/cmd/egctl/experimental.go b/internal/cmd/egctl/experimental.go index e22dc3e6ca60..ad307cc7cb37 100644 --- a/internal/cmd/egctl/experimental.go +++ b/internal/cmd/egctl/experimental.go @@ -25,6 +25,7 @@ func newExperimentalCommand() *cobra.Command { experimentalCommand.AddCommand(newTranslateCommand()) experimentalCommand.AddCommand(newStatsCommand()) experimentalCommand.AddCommand(newStatusCommand()) + experimentalCommand.AddCommand(newDashboardCommand()) return experimentalCommand } diff --git a/internal/cmd/egctl/testdata/translate/in/echo-gateway-api.yaml b/internal/cmd/egctl/testdata/translate/in/echo-gateway-api.yaml index f0e412d92b07..57e3253c71a4 100644 --- a/internal/cmd/egctl/testdata/translate/in/echo-gateway-api.yaml +++ b/internal/cmd/egctl/testdata/translate/in/echo-gateway-api.yaml @@ -55,7 +55,7 @@ spec: spec: serviceAccountName: backend containers: - - image: gcr.io/k8s-staging-ingressconformance/echoserver:v20221109-7ee2f3e + - image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e imagePullPolicy: IfNotPresent name: backend ports: diff --git a/internal/cmd/egctl/testdata/translate/in/envoy-patch-policy.yaml b/internal/cmd/egctl/testdata/translate/in/envoy-patch-policy.yaml index e020bc9d4294..be98f705f713 100644 --- a/internal/cmd/egctl/testdata/translate/in/envoy-patch-policy.yaml +++ b/internal/cmd/egctl/testdata/translate/in/envoy-patch-policy.yaml @@ -59,7 +59,7 @@ spec: spec: serviceAccountName: backend containers: - - image: gcr.io/k8s-staging-ingressconformance/echoserver:v20221109-7ee2f3e + - image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e imagePullPolicy: IfNotPresent name: backend ports: diff --git a/internal/cmd/egctl/testdata/translate/in/jwt-single-route-single-match-to-xds.yaml b/internal/cmd/egctl/testdata/translate/in/jwt-single-route-single-match-to-xds.yaml index 14efe586c4e8..cef3ccc53833 100644 --- a/internal/cmd/egctl/testdata/translate/in/jwt-single-route-single-match-to-xds.yaml +++ b/internal/cmd/egctl/testdata/translate/in/jwt-single-route-single-match-to-xds.yaml @@ -55,7 +55,7 @@ spec: spec: serviceAccountName: backend containers: - - image: gcr.io/k8s-staging-ingressconformance/echoserver:v20221109-7ee2f3e + - image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e imagePullPolicy: IfNotPresent name: backend ports: diff --git a/internal/cmd/egctl/testdata/translate/in/quickstart.yaml b/internal/cmd/egctl/testdata/translate/in/quickstart.yaml index f0e412d92b07..57e3253c71a4 100644 --- a/internal/cmd/egctl/testdata/translate/in/quickstart.yaml +++ b/internal/cmd/egctl/testdata/translate/in/quickstart.yaml @@ -55,7 +55,7 @@ spec: spec: serviceAccountName: backend containers: - - image: gcr.io/k8s-staging-ingressconformance/echoserver:v20221109-7ee2f3e + - image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e imagePullPolicy: IfNotPresent name: backend ports: diff --git a/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml b/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml index 92a71a6ac1cd..f97ac2357659 100644 --- a/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml @@ -814,9 +814,8 @@ xds: routeConfigName: default/eg/http serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: default/eg/http perConnectionBufferLimitBytes: 32768 - activeState: @@ -883,6 +882,7 @@ xds: serverHeaderTransformation: PASS_THROUGH statPrefix: http useRemoteAddress: true + drainType: MODIFY_ONLY name: default/eg/grpc perConnectionBufferLimitBytes: 32768 - activeState: @@ -905,6 +905,7 @@ xds: socketAddress: address: 0.0.0.0 portValue: 8443 + drainType: MODIFY_ONLY filterChains: - filterChainMatch: serverNames: @@ -950,6 +951,7 @@ xds: socketAddress: address: 0.0.0.0 portValue: 1234 + drainType: MODIFY_ONLY filterChains: - filters: - name: envoy.filters.network.tcp_proxy @@ -1027,6 +1029,8 @@ xds: name: httproute/default/backend/rule/0/match/0/www_example_com route: cluster: httproute/default/backend/rule/0 + upgradeConfigs: + - upgradeType: websocket - routeConfig: '@type': type.googleapis.com/envoy.config.route.v3.RouteConfiguration ignorePortInHostMatching: true diff --git a/internal/cmd/egctl/testdata/translate/out/envoy-patch-policy.all.yaml b/internal/cmd/egctl/testdata/translate/out/envoy-patch-policy.all.yaml index c31c5d146f32..b7e57c2ca976 100644 --- a/internal/cmd/egctl/testdata/translate/out/envoy-patch-policy.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/envoy-patch-policy.all.yaml @@ -210,9 +210,8 @@ xds: routeConfigName: default/eg/http serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: default/eg/http perConnectionBufferLimitBytes: 32768 - '@type': type.googleapis.com/envoy.admin.v3.RoutesConfigDump diff --git a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.json b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.json index bd7a401d9572..03b4c4e86226 100644 --- a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.json +++ b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.json @@ -570,16 +570,12 @@ }, "serverHeaderTransformation": "PASS_THROUGH", "statPrefix": "http", - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ], "useRemoteAddress": true } } ] }, + "drainType": "MODIFY_ONLY", "name": "default/eg/http", "perConnectionBufferLimitBytes": 32768 } @@ -684,6 +680,7 @@ } ] }, + "drainType": "MODIFY_ONLY", "name": "default/eg/grpc", "perConnectionBufferLimitBytes": 32768 } @@ -720,6 +717,7 @@ "portValue": 8443 } }, + "drainType": "MODIFY_ONLY", "filterChains": [ { "filterChainMatch": { @@ -797,6 +795,7 @@ "portValue": 1234 } }, + "drainType": "MODIFY_ONLY", "filterChains": [ { "filters": [ @@ -923,7 +922,12 @@ }, "name": "httproute/default/backend/rule/0/match/0/www_example_com", "route": { - "cluster": "httproute/default/backend/rule/0" + "cluster": "httproute/default/backend/rule/0", + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] } } ] diff --git a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.yaml b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.yaml index ed5c71ea6024..2ebb68e1841a 100644 --- a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.yaml @@ -340,9 +340,8 @@ xds: routeConfigName: default/eg/http serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: default/eg/http perConnectionBufferLimitBytes: 32768 - activeState: @@ -409,6 +408,7 @@ xds: serverHeaderTransformation: PASS_THROUGH statPrefix: http useRemoteAddress: true + drainType: MODIFY_ONLY name: default/eg/grpc perConnectionBufferLimitBytes: 32768 - activeState: @@ -431,6 +431,7 @@ xds: socketAddress: address: 0.0.0.0 portValue: 8443 + drainType: MODIFY_ONLY filterChains: - filterChainMatch: serverNames: @@ -476,6 +477,7 @@ xds: socketAddress: address: 0.0.0.0 portValue: 1234 + drainType: MODIFY_ONLY filterChains: - filters: - name: envoy.filters.network.tcp_proxy @@ -553,6 +555,8 @@ xds: name: httproute/default/backend/rule/0/match/0/www_example_com route: cluster: httproute/default/backend/rule/0 + upgradeConfigs: + - upgradeType: websocket - routeConfig: '@type': type.googleapis.com/envoy.config.route.v3.RouteConfiguration ignorePortInHostMatching: true diff --git a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.listener.yaml b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.listener.yaml index bc904a54906d..fee6abd4f5a2 100644 --- a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.listener.yaml +++ b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.listener.yaml @@ -57,9 +57,8 @@ xds: routeConfigName: default/eg/http serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: default/eg/http perConnectionBufferLimitBytes: 32768 - activeState: @@ -126,6 +125,7 @@ xds: serverHeaderTransformation: PASS_THROUGH statPrefix: http useRemoteAddress: true + drainType: MODIFY_ONLY name: default/eg/grpc perConnectionBufferLimitBytes: 32768 - activeState: @@ -148,6 +148,7 @@ xds: socketAddress: address: 0.0.0.0 portValue: 8443 + drainType: MODIFY_ONLY filterChains: - filterChainMatch: serverNames: @@ -193,6 +194,7 @@ xds: socketAddress: address: 0.0.0.0 portValue: 1234 + drainType: MODIFY_ONLY filterChains: - filters: - name: envoy.filters.network.tcp_proxy diff --git a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.route.yaml b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.route.yaml index 318efe2352f9..65f1f62961ee 100644 --- a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.route.yaml +++ b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.route.yaml @@ -16,6 +16,8 @@ xds: name: httproute/default/backend/rule/0/match/0/www_example_com route: cluster: httproute/default/backend/rule/0 + upgradeConfigs: + - upgradeType: websocket - routeConfig: '@type': type.googleapis.com/envoy.config.route.v3.RouteConfiguration ignorePortInHostMatching: true diff --git a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.json b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.json index c776a2f53b3d..8a8d5051c171 100644 --- a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.json +++ b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.json @@ -447,16 +447,12 @@ }, "serverHeaderTransformation": "PASS_THROUGH", "statPrefix": "http", - "upgradeConfigs": [ - { - "upgradeType": "websocket" - } - ], "useRemoteAddress": true } } ] }, + "drainType": "MODIFY_ONLY", "name": "envoy-gateway-system/eg/http", "perConnectionBufferLimitBytes": 32768 } @@ -485,7 +481,12 @@ }, "name": "httproute/envoy-gateway-system/backend/rule/0/match/0/www_example_com", "route": { - "cluster": "httproute/envoy-gateway-system/backend/rule/0" + "cluster": "httproute/envoy-gateway-system/backend/rule/0", + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] }, "typedPerFilterConfig": { "envoy.filters.http.jwt_authn": { diff --git a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.yaml b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.yaml index 94acbe319049..e1a2c1e52525 100644 --- a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.yaml @@ -267,9 +267,8 @@ xds: routeConfigName: envoy-gateway-system/eg/http serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: envoy-gateway-system/eg/http perConnectionBufferLimitBytes: 32768 - '@type': type.googleapis.com/envoy.admin.v3.RoutesConfigDump @@ -288,6 +287,8 @@ xds: name: httproute/envoy-gateway-system/backend/rule/0/match/0/www_example_com route: cluster: httproute/envoy-gateway-system/backend/rule/0 + upgradeConfigs: + - upgradeType: websocket typedPerFilterConfig: envoy.filters.http.jwt_authn: '@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig diff --git a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.listener.yaml b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.listener.yaml index acc9e8afdee5..05334cc0ae3e 100644 --- a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.listener.yaml +++ b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.listener.yaml @@ -74,8 +74,7 @@ xds: routeConfigName: envoy-gateway-system/eg/http serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: envoy-gateway-system/eg/http perConnectionBufferLimitBytes: 32768 diff --git a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.route.yaml b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.route.yaml index 476fb3e582e9..a02553f10081 100644 --- a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.route.yaml +++ b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.route.yaml @@ -16,6 +16,8 @@ xds: name: httproute/envoy-gateway-system/backend/rule/0/match/0/www_example_com route: cluster: httproute/envoy-gateway-system/backend/rule/0 + upgradeConfigs: + - upgradeType: websocket typedPerFilterConfig: envoy.filters.http.jwt_authn: '@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig diff --git a/internal/cmd/egctl/testdata/translate/out/multiple-xds.route.json b/internal/cmd/egctl/testdata/translate/out/multiple-xds.route.json index c2d43139edda..b311b7118393 100644 --- a/internal/cmd/egctl/testdata/translate/out/multiple-xds.route.json +++ b/internal/cmd/egctl/testdata/translate/out/multiple-xds.route.json @@ -21,7 +21,12 @@ }, "name": "httproute/default/backend/rule/0/match/0/www_example_com", "route": { - "cluster": "httproute/default/backend/rule/0" + "cluster": "httproute/default/backend/rule/0", + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] } } ] @@ -52,7 +57,12 @@ }, "name": "httproute/default/backend/rule/0/match/0/www_example2_com", "route": { - "cluster": "httproute/default/backend/rule/0" + "cluster": "httproute/default/backend/rule/0", + "upgradeConfigs": [ + { + "upgradeType": "websocket" + } + ] } } ] diff --git a/internal/cmd/egctl/testdata/translate/out/quickstart.route.yaml b/internal/cmd/egctl/testdata/translate/out/quickstart.route.yaml index 12104d66b085..f358d4066ef6 100644 --- a/internal/cmd/egctl/testdata/translate/out/quickstart.route.yaml +++ b/internal/cmd/egctl/testdata/translate/out/quickstart.route.yaml @@ -16,3 +16,5 @@ xds: name: httproute/envoy-gateway-system/backend/rule/0/match/0/www_example_com route: cluster: httproute/envoy-gateway-system/backend/rule/0 + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/cmd/egctl/version.go b/internal/cmd/egctl/version.go index de3cde37a61b..5cab0035358c 100644 --- a/internal/cmd/egctl/version.go +++ b/internal/cmd/egctl/version.go @@ -20,6 +20,7 @@ import ( "github.com/envoyproxy/gateway/internal/cmd/options" "github.com/envoyproxy/gateway/internal/cmd/version" kube "github.com/envoyproxy/gateway/internal/kubernetes" + "github.com/envoyproxy/gateway/internal/utils" ) const ( @@ -98,16 +99,14 @@ 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) continue } - nn := types.NamespacedName{ - Namespace: pod.Namespace, - Name: pod.Name, - } + nn := utils.NamespacedName(&pod) stdout, _, err := c.PodExec(nn, containerName, "envoy-gateway version -ojson") if err != nil { return fmt.Errorf("pod exec on %s/%s failed: %w", nn.Namespace, nn.Name, err) diff --git a/internal/cmd/envoy.go b/internal/cmd/envoy.go new file mode 100644 index 000000000000..20cf95bb412a --- /dev/null +++ b/internal/cmd/envoy.go @@ -0,0 +1,71 @@ +// 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 cmd + +import ( + "time" + + "github.com/spf13/cobra" + + "github.com/envoyproxy/gateway/internal/cmd/envoy" +) + +// getEnvoyCommand returns the envoy cobra command to be executed. +func getEnvoyCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "envoy", + Short: "Envoy proxy management", + } + + cmd.AddCommand(getShutdownCommand()) + cmd.AddCommand(getShutdownManagerCommand()) + + return cmd +} + +// getShutdownCommand returns the shutdown cobra command to be executed. +func getShutdownCommand() *cobra.Command { + var drainTimeout time.Duration + var minDrainDuration time.Duration + var exitAtConnections int + + cmd := &cobra.Command{ + Use: "shutdown", + Short: "Gracefully drain open connections prior to pod shutdown.", + RunE: func(cmd *cobra.Command, args []string) error { + return envoy.Shutdown(drainTimeout, minDrainDuration, exitAtConnections) + }, + } + + cmd.PersistentFlags().DurationVar(&drainTimeout, "drain-timeout", 600*time.Second, + "Graceful shutdown timeout. This should be less than the pod's terminationGracePeriodSeconds.") + + cmd.PersistentFlags().DurationVar(&minDrainDuration, "min-drain-duration", 5*time.Second, + "Minimum drain duration allowing time for endpoint deprogramming to complete.") + + cmd.PersistentFlags().IntVar(&exitAtConnections, "exit-at-connections", 0, + "Number of connections to wait for when monitoring Envoy listener drain process.") + + return cmd +} + +// getShutdownManagerCommand returns the shutdown manager cobra command to be executed. +func getShutdownManagerCommand() *cobra.Command { + var readyTimeout time.Duration + + cmd := &cobra.Command{ + Use: "shutdown-manager", + Short: "Provides HTTP endpoint used in preStop hook to block until ready for pod shutdown.", + RunE: func(cmd *cobra.Command, args []string) error { + return envoy.ShutdownManager(readyTimeout) + }, + } + + cmd.PersistentFlags().DurationVar(&readyTimeout, "ready-timeout", 610*time.Second, + "Shutdown ready timeout. This should be greater than shutdown's drain-timeout and less than the pod's terminationGracePeriodSeconds.") + + return cmd +} diff --git a/internal/cmd/envoy/shutdown_manager.go b/internal/cmd/envoy/shutdown_manager.go new file mode 100644 index 000000000000..1f0a199a4eb2 --- /dev/null +++ b/internal/cmd/envoy/shutdown_manager.go @@ -0,0 +1,248 @@ +// 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 envoy + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "net/http" + "os" + "os/signal" + "syscall" + "time" + + "golang.org/x/sys/unix" + + "github.com/envoyproxy/gateway/api/v1alpha1" + "github.com/envoyproxy/gateway/internal/logging" + "github.com/envoyproxy/gateway/internal/xds/bootstrap" +) + +var ( + logger = logging.DefaultLogger(v1alpha1.LogLevelInfo).WithName("shutdown-manager") +) + +const ( + // ShutdownManagerPort is the port Envoy shutdown manager will listen on. + ShutdownManagerPort = 19002 + // ShutdownManagerHealthCheckPath is the path used for health checks. + ShutdownManagerHealthCheckPath = "/healthz" + // ShutdownManagerReadyPath is the path used to indicate shutdown readiness. + ShutdownManagerReadyPath = "/shutdown/ready" + // ShutdownActiveFile is the file used to indicate shutdown readiness. + ShutdownActiveFile = "/tmp/shutdown-active" +) + +// ShutdownManager serves shutdown manager process for Envoy proxies. +func ShutdownManager(readyTimeout time.Duration) error { + // Setup HTTP handler + handler := http.NewServeMux() + handler.HandleFunc(ShutdownManagerHealthCheckPath, func(_ http.ResponseWriter, _ *http.Request) {}) + handler.HandleFunc(ShutdownManagerReadyPath, func(w http.ResponseWriter, _ *http.Request) { + shutdownReadyHandler(w, readyTimeout, ShutdownActiveFile) + }) + + // Setup HTTP server + srv := http.Server{ + Handler: handler, + Addr: fmt.Sprintf(":%d", ShutdownManagerPort), + ReadTimeout: 5 * time.Second, + ReadHeaderTimeout: 5 * time.Second, + WriteTimeout: 10 * time.Second, + IdleTimeout: 15 * time.Second, + } + + // Setup signal handling + c := make(chan struct{}) + go func() { + s := make(chan os.Signal, 1) + signal.Notify(s, os.Interrupt, syscall.SIGTERM) + + r := <-s + logger.Info(fmt.Sprintf("received %s", unix.SignalName(r.(syscall.Signal)))) + + // Shutdown HTTP server without interrupting active connections + if err := srv.Shutdown(context.Background()); err != nil { + logger.Error(err, "server shutdown error") + } + close(c) + }() + + // Start HTTP server + logger.Info("starting shutdown manager") + if err := srv.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) { + logger.Error(err, "starting shutdown manager failed") + } + + // Wait until done + <-c + return nil +} + +// shutdownReadyHandler handles the endpoint used by a preStop hook on the Envoy +// container to block until ready to terminate. When the graceful drain process +// has begun a file will be written to indicate shutdown is in progress. This +// handler will poll for the file and block until it is removed. +func shutdownReadyHandler(w http.ResponseWriter, readyTimeout time.Duration, activeFile string) { + var startTime = time.Now() + + logger.Info("received shutdown ready request") + + // Since we cannot establish order between preStop hooks, wait a bit giving the exec + // preStop hook a chance to touch the signaling file before starting to poll for it. + time.Sleep(2 * time.Second) + + // Exit early if active file failed to show up + if _, err := os.Stat(activeFile); os.IsNotExist(err) { + logger.Info("shutdown active file not found") + w.WriteHeader(http.StatusInternalServerError) + return + } + + // Poll for shutdown readiness + for { + // Check if ready timeout is exceeded + elapsedTime := time.Since(startTime) + if elapsedTime > readyTimeout { + logger.Info("shutdown readiness timeout exceeded") + w.WriteHeader(http.StatusInternalServerError) + return + } + + _, err := os.Stat(activeFile) + switch { + case os.IsNotExist(err): + logger.Info("shutdown readiness detected") + return + case err != nil: + logger.Error(err, "error checking for shutdown readiness") + case err == nil: + time.Sleep(1 * time.Second) + } + } +} + +// Shutdown is called from a preStop hook on the shutdown-manager container where +// it will initiate a graceful drain sequence on the Envoy proxy and block until +// connections are drained or a timeout is exceeded. +func Shutdown(drainTimeout time.Duration, minDrainDuration time.Duration, exitAtConnections int) error { + var startTime = time.Now() + var allowedToExit = false + + // Reconfigure logger to write to stdout of main process if running in Kubernetes + if _, k8s := os.LookupEnv("KUBERNETES_SERVICE_HOST"); k8s && os.Getpid() != 1 { + logger = logging.FileLogger("/proc/1/fd/1", "shutdown-manager", v1alpha1.LogLevelInfo) + } + + // Signal to shutdownReadyHandler that drain process is started + if _, err := os.Create(ShutdownActiveFile); err != nil { + logger.Error(err, "error creating shutdown active file") + return err + } + + logger.Info(fmt.Sprintf("initiating graceful drain with %.0f second minimum drain period and %.0f second timeout", + minDrainDuration.Seconds(), drainTimeout.Seconds())) + + // Start failing active health checks + if err := postEnvoyAdminAPI("healthcheck/fail"); err != nil { + logger.Error(err, "error failing active health checks") + } + + // Initiate graceful drain sequence + if err := postEnvoyAdminAPI("drain_listeners?graceful&skip_exit"); err != nil { + logger.Error(err, "error initiating graceful drain") + } + + // Poll total connections from Envoy admin API until minimum drain period has + // been reached and total connections reaches threshold or timeout is exceeded + for { + elapsedTime := time.Since(startTime) + + conn, err := getTotalConnections() + if err != nil { + logger.Error(err, "error getting total connections") + } + + if elapsedTime > minDrainDuration && !allowedToExit { + logger.Info(fmt.Sprintf("minimum drain period reached; will exit when total connections reaches %d", exitAtConnections)) + allowedToExit = true + } + + if elapsedTime > drainTimeout { + logger.Info("graceful drain sequence timeout exceeded") + break + } else if allowedToExit && conn != nil && *conn <= exitAtConnections { + logger.Info("graceful drain sequence completed") + break + } + + time.Sleep(1 * time.Second) + } + + // Signal to shutdownReadyHandler that drain process is complete + if err := os.Remove(ShutdownActiveFile); err != nil { + logger.Error(err, "error removing shutdown active file") + return err + } + + return nil +} + +// postEnvoyAdminAPI sends a POST request to the Envoy admin API +func postEnvoyAdminAPI(path string) error { + if resp, err := http.Post(fmt.Sprintf("http://%s:%d/%s", + bootstrap.EnvoyAdminAddress, bootstrap.EnvoyAdminPort, path), "application/json", nil); err != nil { + return err + } else { + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("unexpected response status: %s", resp.Status) + } + return nil + } +} + +// getTotalConnections retrieves the total number of open connections from Envoy's server.total_connections stat +func getTotalConnections() (*int, error) { + // Send request to Envoy admin API to retrieve server.total_connections stat + if resp, err := http.Get(fmt.Sprintf("http://%s:%d//stats?filter=^server\\.total_connections$&format=json", + bootstrap.EnvoyAdminAddress, bootstrap.EnvoyAdminPort)); err != nil { + return nil, err + } else { + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("unexpected response status: %s", resp.Status) + } else { + // Define struct to decode JSON response into; expecting a single stat in the response in the format: + // {"stats":[{"name":"server.total_connections","value":123}]} + var r *struct { + Stats []struct { + Name string + Value int + } + } + + // Decode JSON response into struct + if err := json.NewDecoder(resp.Body).Decode(&r); err != nil { + return nil, err + } + + // Defensive check for empty stats + if len(r.Stats) == 0 { + return nil, fmt.Errorf("no stats found") + } + + // Log and return total connections + c := r.Stats[0].Value + logger.Info(fmt.Sprintf("total connections: %d", c)) + return &c, nil + } + } +} diff --git a/internal/cmd/envoy_test.go b/internal/cmd/envoy_test.go new file mode 100644 index 000000000000..9115357d63d3 --- /dev/null +++ b/internal/cmd/envoy_test.go @@ -0,0 +1,17 @@ +// 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 cmd + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetEnvoyCommand(t *testing.T) { + got := getEnvoyCommand() + assert.Equal(t, "envoy", got.Use) +} diff --git a/internal/cmd/root.go b/internal/cmd/root.go index e7807346cc76..c7e4a6f2a2b7 100644 --- a/internal/cmd/root.go +++ b/internal/cmd/root.go @@ -19,6 +19,7 @@ func GetRootCommand() *cobra.Command { } cmd.AddCommand(getServerCommand()) + cmd.AddCommand(getEnvoyCommand()) cmd.AddCommand(getVersionCommand()) cmd.AddCommand(getCertGenCommand()) diff --git a/internal/cmd/version/version.go b/internal/cmd/version/version.go index eb169af2b7c3..f40eb5104139 100644 --- a/internal/cmd/version/version.go +++ b/internal/cmd/version/version.go @@ -18,26 +18,29 @@ import ( ) type Info struct { - EnvoyGatewayVersion string `json:"envoyGatewayVersion"` - GatewayAPIVersion string `json:"gatewayAPIVersion"` - EnvoyProxyVersion string `json:"envoyProxyVersion"` - GitCommitID string `json:"gitCommitID"` + EnvoyGatewayVersion string `json:"envoyGatewayVersion"` + GatewayAPIVersion string `json:"gatewayAPIVersion"` + EnvoyProxyVersion string `json:"envoyProxyVersion"` + ShutdownManagerVersion string `json:"shutdownManagerVersion"` + GitCommitID string `json:"gitCommitID"` } func Get() Info { return Info{ - EnvoyGatewayVersion: envoyGatewayVersion, - GatewayAPIVersion: gatewayAPIVersion, - EnvoyProxyVersion: envoyProxyVersion, - GitCommitID: gitCommitID, + EnvoyGatewayVersion: envoyGatewayVersion, + GatewayAPIVersion: gatewayAPIVersion, + EnvoyProxyVersion: envoyProxyVersion, + ShutdownManagerVersion: shutdownManagerVersion, + GitCommitID: gitCommitID, } } var ( - envoyGatewayVersion string - gatewayAPIVersion string - envoyProxyVersion = strings.Split(*v1alpha1.DefaultKubernetesContainerImage(v1alpha1.DefaultEnvoyProxyImage), ":")[1] - gitCommitID string + envoyGatewayVersion string + gatewayAPIVersion string + envoyProxyVersion = strings.Split(*v1alpha1.DefaultKubernetesContainerImage(v1alpha1.DefaultEnvoyProxyImage), ":")[1] + shutdownManagerVersion string + gitCommitID string ) func init() { @@ -67,6 +70,7 @@ func Print(w io.Writer, format string) error { _, _ = fmt.Fprintf(w, "ENVOY_GATEWAY_VERSION: %s\n", v.EnvoyGatewayVersion) _, _ = fmt.Fprintf(w, "ENVOY_PROXY_VERSION: %s\n", v.EnvoyProxyVersion) _, _ = fmt.Fprintf(w, "GATEWAYAPI_VERSION: %s\n", v.GatewayAPIVersion) + _, _ = fmt.Fprintf(w, "SHUTDOWN_MANAGER_VERSION: %s\n", v.ShutdownManagerVersion) _, _ = fmt.Fprintf(w, "GIT_COMMIT_ID: %s\n", v.GitCommitID) } diff --git a/internal/gatewayapi/backendtrafficpolicy.go b/internal/gatewayapi/backendtrafficpolicy.go index 3f21a987c2fd..c3e4cec23d6d 100644 --- a/internal/gatewayapi/backendtrafficpolicy.go +++ b/internal/gatewayapi/backendtrafficpolicy.go @@ -23,6 +23,7 @@ import ( egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/ir" "github.com/envoyproxy/gateway/internal/status" + "github.com/envoyproxy/gateway/internal/utils" "github.com/envoyproxy/gateway/internal/utils/regex" ) @@ -66,10 +67,7 @@ func (t *Translator) ProcessBackendTrafficPolicies(backendTrafficPolicies []*egv } gatewayMap := map[types.NamespacedName]*policyGatewayTargetContext{} for _, gw := range gateways { - key := types.NamespacedName{ - Name: gw.GetName(), - Namespace: gw.GetNamespace(), - } + key := utils.NamespacedName(gw) gatewayMap[key] = &policyGatewayTargetContext{GatewayContext: gw} } @@ -354,7 +352,15 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back // Should exist since we've validated this ir := xdsIR[irKey] + policyTarget := irStringKey( + string(ptr.Deref(policy.Spec.TargetRef.Namespace, gwv1a2.Namespace(policy.Namespace))), + string(policy.Spec.TargetRef.Name), + ) for _, http := range ir.HTTP { + gatewayName := http.Name[0:strings.LastIndex(http.Name, "/")] + if t.MergeGateways && gatewayName != policyTarget { + continue + } for _, r := range http.Routes { // Apply if not already set if r.RateLimit == nil { @@ -870,6 +876,15 @@ func (t *Translator) buildCircuitBreaker(policy *egv1a1.BackendTrafficPolicy) *i return nil } } + + if pcb.MaxRequestsPerConnection != nil { + if ui32, ok := int64ToUint32(*pcb.MaxRequestsPerConnection); ok { + cb.MaxRequestsPerConnection = &ui32 + } else { + setBackendTrafficPolicyTranslationErrorCondition(policy, "Circuit Breaker", fmt.Sprintf("invalid MaxRequestsPerConnection value %d", *pcb.MaxRequestsPerConnection)) + return nil + } + } } return cb diff --git a/internal/gatewayapi/clienttrafficpolicy.go b/internal/gatewayapi/clienttrafficpolicy.go index 5bd81cabf959..f5992db21a87 100644 --- a/internal/gatewayapi/clienttrafficpolicy.go +++ b/internal/gatewayapi/clienttrafficpolicy.go @@ -21,6 +21,7 @@ import ( egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/ir" "github.com/envoyproxy/gateway/internal/status" + "github.com/envoyproxy/gateway/internal/utils" ) const ( @@ -64,10 +65,7 @@ func (t *Translator) ProcessClientTrafficPolicies(resources *Resources, } // Check for conflicts - key := types.NamespacedName{ - Name: gateway.Name, - Namespace: gateway.Namespace, - } + key := utils.NamespacedName(gateway) // Check if another policy targeting the same section exists section := string(*(policy.Spec.TargetRef.SectionName)) diff --git a/internal/gatewayapi/contexts.go b/internal/gatewayapi/contexts.go index 83eb153a94d1..1ee327302b18 100644 --- a/internal/gatewayapi/contexts.go +++ b/internal/gatewayapi/contexts.go @@ -417,3 +417,22 @@ func (r *RouteParentContext) HasCondition(route RouteContext, condType gwapiv1.R } return false } + +// BackendRefContext represents a generic BackendRef object (HTTPBackendRef, GRPCBackendRef or BackendRef itself) +type BackendRefContext any + +func GetBackendRef(b BackendRefContext) *gwapiv1.BackendRef { + rv := reflect.ValueOf(b) + br := rv.FieldByName("BackendRef") + if br.IsValid() { + backendRef := br.Interface().(gwapiv1.BackendRef) + return &backendRef + + } + backendRef := b.(gwapiv1.BackendRef) + return &backendRef +} + +func GetFilters(b BackendRefContext) any { + return reflect.ValueOf(b).FieldByName("Filters").Interface() +} diff --git a/internal/gatewayapi/filters.go b/internal/gatewayapi/filters.go index 73dcf54ca7ff..c728e1e863b9 100644 --- a/internal/gatewayapi/filters.go +++ b/internal/gatewayapi/filters.go @@ -704,15 +704,17 @@ func (t *Translator) processRequestMirrorFilter( // Wrap the filter's BackendObjectReference into a BackendRef so we can use existing tooling to check it weight := int32(1) - mirrorBackendRef := gwapiv1.BackendRef{ - BackendObjectReference: mirrorBackend, - Weight: &weight, + mirrorBackendRef := gwapiv1.HTTPBackendRef{ + BackendRef: gwapiv1.BackendRef{ + BackendObjectReference: mirrorBackend, + Weight: &weight, + }, } // This sets the status on the HTTPRoute, should the usage be changed so that the status message reflects that the backendRef is from the filter? filterNs := filterContext.Route.GetNamespace() serviceNamespace := NamespaceDerefOr(mirrorBackend.Namespace, filterNs) - if !t.validateBackendRef(&mirrorBackendRef, filterContext.ParentRef, filterContext.Route, + if !t.validateBackendRef(mirrorBackendRef, filterContext.ParentRef, filterContext.Route, resources, serviceNamespace, KindHTTPRoute) { return } diff --git a/internal/gatewayapi/helpers.go b/internal/gatewayapi/helpers.go index 4c4ef61aece8..fd5456191ac1 100644 --- a/internal/gatewayapi/helpers.go +++ b/internal/gatewayapi/helpers.go @@ -18,6 +18,7 @@ import ( "sigs.k8s.io/gateway-api/apis/v1alpha2" "github.com/envoyproxy/gateway/internal/ir" + "github.com/envoyproxy/gateway/internal/utils" ) const ( @@ -126,7 +127,7 @@ func GetReferencedListeners(parentRef gwapiv1.ParentReference, gateways []*Gatew var referencedListeners []*ListenerContext for _, gateway := range gateways { - if !IsRefToGateway(parentRef, types.NamespacedName{Namespace: gateway.Namespace, Name: gateway.Name}) { + if !IsRefToGateway(parentRef, utils.NamespacedName(gateway)) { continue } diff --git a/internal/gatewayapi/listener.go b/internal/gatewayapi/listener.go index 1a92c751deaf..4702d2a4e26f 100644 --- a/internal/gatewayapi/listener.go +++ b/internal/gatewayapi/listener.go @@ -9,11 +9,11 @@ import ( "fmt" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/ir" + "github.com/envoyproxy/gateway/internal/utils" "github.com/envoyproxy/gateway/internal/utils/naming" ) @@ -242,7 +242,7 @@ func processTracing(gw *gwapiv1.Gateway, envoyproxy *egv1a1.EnvoyProxy) *ir.Trac } return &ir.Tracing{ - ServiceName: naming.ServiceName(types.NamespacedName{Name: gw.Name, Namespace: gw.Namespace}), + ServiceName: naming.ServiceName(utils.NamespacedName(gw)), ProxyTracing: *envoyproxy.Spec.Telemetry.Tracing, } } diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index fc4dac08cf52..b09e08ba7be1 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -173,7 +173,8 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe dstAddrTypeMap := make(map[ir.DestinationAddressType]int) for _, backendRef := range rule.BackendRefs { - ds, backendWeight := t.processDestination(backendRef.BackendRef, parentRef, httpRoute, resources) + backendRef := backendRef + ds, backendWeight := t.processDestination(backendRef, parentRef, httpRoute, resources) if !t.EndpointRoutingDisabled && ds != nil && len(ds.Endpoints) > 0 && ds.AddressType != nil { dstAddrTypeMap[*ds.AddressType]++ } @@ -213,6 +214,7 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe StatusCode: 500, } } + ruleRoute.IsHTTP2 = false } // TODO handle: @@ -467,7 +469,8 @@ func (t *Translator) processGRPCRouteRules(grpcRoute *GRPCRouteContext, parentRe } for _, backendRef := range rule.BackendRefs { - ds, backendWeight := t.processDestination(backendRef.BackendRef, parentRef, grpcRoute, resources) + backendRef := backendRef + ds, backendWeight := t.processDestination(backendRef, parentRef, grpcRoute, resources) for _, route := range ruleRoutes { // If the route already has a direct response or redirect configured, then it was from a filter so skip // processing any destinations for this route. @@ -495,6 +498,7 @@ func (t *Translator) processGRPCRouteRules(grpcRoute *GRPCRouteContext, parentRe StatusCode: 500, } } + ruleRoute.IsHTTP2 = true } // TODO handle: @@ -658,6 +662,7 @@ func (t *Translator) processHTTPRouteParentRefListener(route RouteContext, route ExtensionRefs: routeRoute.ExtensionRefs, Timeout: routeRoute.Timeout, Retry: routeRoute.Retry, + IsHTTP2: routeRoute.IsHTTP2, } // Don't bother copying over the weights unless the route has invalid backends. if routeRoute.BackendWeights.Invalid > 0 { @@ -1065,20 +1070,19 @@ func (t *Translator) processTCPRouteParentRefs(tcpRoute *TCPRouteContext, resour // processDestination takes a backendRef and translates it into destination setting or sets error statuses and // returns the weight for the backend so that 500 error responses can be returned for invalid backends in // the same proportion as the backend would have otherwise received -func (t *Translator) processDestination(backendRef gwapiv1.BackendRef, +func (t *Translator) processDestination(backendRefContext BackendRefContext, parentRef *RouteParentContext, route RouteContext, resources *Resources) (ds *ir.DestinationSetting, backendWeight uint32) { - + routeType := GetRouteType(route) weight := uint32(1) + backendRef := GetBackendRef(backendRefContext) if backendRef.Weight != nil { weight = uint32(*backendRef.Weight) } backendNamespace := NamespaceDerefOr(backendRef.Namespace, route.GetNamespace()) - - routeType := GetRouteType(route) - if !t.validateBackendRef(&backendRef, parentRef, route, resources, backendNamespace, routeType) { + if !t.validateBackendRef(backendRefContext, parentRef, route, resources, backendNamespace, routeType) { return nil, weight } diff --git a/internal/gatewayapi/runner/runner.go b/internal/gatewayapi/runner/runner.go index ac2ec3140a07..ebc5d612d257 100644 --- a/internal/gatewayapi/runner/runner.go +++ b/internal/gatewayapi/runner/runner.go @@ -16,7 +16,7 @@ import ( extension "github.com/envoyproxy/gateway/internal/extension/types" "github.com/envoyproxy/gateway/internal/gatewayapi" "github.com/envoyproxy/gateway/internal/message" - "github.com/envoyproxy/gateway/internal/provider/utils" + "github.com/envoyproxy/gateway/internal/utils" ) type Config struct { diff --git a/internal/gatewayapi/securitypolicy.go b/internal/gatewayapi/securitypolicy.go index 0e5d91145e59..636b7316e113 100644 --- a/internal/gatewayapi/securitypolicy.go +++ b/internal/gatewayapi/securitypolicy.go @@ -9,7 +9,6 @@ import ( "encoding/json" "errors" "fmt" - "hash/fnv" "net/http" "net/netip" "net/url" @@ -28,6 +27,7 @@ import ( egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/ir" "github.com/envoyproxy/gateway/internal/status" + "github.com/envoyproxy/gateway/internal/utils" ) const ( @@ -61,10 +61,7 @@ func (t *Translator) ProcessSecurityPolicies(securityPolicies []*egv1a1.Security } gatewayMap := map[types.NamespacedName]*policyGatewayTargetContext{} for _, gw := range gateways { - key := types.NamespacedName{ - Name: gw.GetName(), - Namespace: gw.GetNamespace(), - } + key := utils.NamespacedName(gw) gatewayMap[key] = &policyGatewayTargetContext{GatewayContext: gw} } @@ -363,7 +360,8 @@ func (t *Translator) translateSecurityPolicyForGateway( } } - // Apply IR to all the routes within the specific Gateway + // Apply IR to all the routes within the specific Gateway that originated + // from the gateway to which this security policy was attached. // If the feature is already set, then skip it, since it must have be // set by a policy attaching to the route // @@ -373,7 +371,15 @@ func (t *Translator) translateSecurityPolicyForGateway( // Should exist since we've validated this ir := xdsIR[irKey] + policyTarget := irStringKey( + string(ptr.Deref(policy.Spec.TargetRef.Namespace, gwv1a2.Namespace(policy.Namespace))), + string(policy.Spec.TargetRef.Name), + ) for _, http := range ir.HTTP { + gatewayName := http.Name[0:strings.LastIndex(http.Name, "/")] + if t.MergeGateways && gatewayName != policyTarget { + continue + } for _, r := range http.Routes { // Apply if not already set if r.CORS == nil { @@ -495,11 +501,8 @@ func (t *Translator) buildOIDC( logoutPath = *oidc.LogoutPath } - h := fnv.New32a() - if _, err = h.Write([]byte(policy.UID)); err != nil { - return nil, fmt.Errorf("error generating oauth cookie suffix: %w", err) - } - suffix := fmt.Sprintf("%X", h.Sum32()) + // Generate a unique cookie suffix for oauth filters + suffix := utils.Digest32(string(policy.UID)) return &ir.OIDC{ Provider: *provider, diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-status-conditions.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-status-conditions.out.yaml index 8d808860337c..429b235bb9e4 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-status-conditions.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-status-conditions.out.yaml @@ -360,6 +360,7 @@ xdsIR: directResponse: statusCode: 500 hostname: '*' + isHTTP2: false name: httproute/envoy-gateway/httproute-1/rule/0/match/0/* pathMatch: distinct: false @@ -390,4 +391,5 @@ xdsIR: exact: foo name: magic hostname: '*' + isHTTP2: true name: grpcroute/envoy-gateway/grpcroute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-status-fault-injection.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-status-fault-injection.out.yaml index 67f60a56cdd2..d712794bd956 100755 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-status-fault-injection.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-status-fault-injection.out.yaml @@ -333,6 +333,7 @@ xdsIR: fixedDelay: 5.4s percentage: 80 hostname: '*' + isHTTP2: true name: grpcroute/default/grpcroute-1/rule/0/match/-1/* envoy-gateway/gateway-2: accessLog: @@ -366,6 +367,7 @@ xdsIR: httpStatus: 14 percentage: 0.01 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-2/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false @@ -391,6 +393,7 @@ xdsIR: fixedDelay: 5.4s percentage: 80 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers-error.in.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers-error.in.yaml index d762170ad927..42f7cafb4f49 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers-error.in.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers-error.in.yaml @@ -1,44 +1,91 @@ gateways: -- apiVersion: gateway.networking.k8s.io/v1 - kind: Gateway - metadata: - namespace: envoy-gateway - name: gateway-1 - spec: - gatewayClassName: envoy-gateway-class - listeners: - - name: http - protocol: HTTP - port: 80 - allowedRoutes: - namespaces: - from: All -grpcRoutes: -- apiVersion: gateway.networking.k8s.io/v1alpha2 - kind: GRPCRoute - metadata: - namespace: default - name: grpcroute-1 - spec: - parentRefs: - - namespace: envoy-gateway + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway name: gateway-1 - sectionName: http - rules: - - backendRefs: - - name: service-1 - port: 8080 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-2 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All +grpcRoutes: + - apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: GRPCRoute + metadata: + namespace: default + name: grpcroute-1 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 +httpRoutes: + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-1 + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - namespace: envoy-gateway + name: gateway-2 + sectionName: http + rules: + - matches: + - path: + value: "/" + backendRefs: + - name: service-1 + port: 8080 backendTrafficPolicies: -- apiVersion: gateway.envoyproxy.io/v1alpha1 - kind: BackendTrafficPolicy - metadata: - namespace: envoy-gateway - name: policy-for-gateway - spec: - targetRef: - group: gateway.networking.k8s.io - kind: Gateway - name: gateway-1 + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: namespace: envoy-gateway - circuitBreaker: - maxConnections: -1 + name: policy-for-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + circuitBreaker: + maxConnections: -1 + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + namespace: default + name: policy-for-route + spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + namespace: default + circuitBreaker: + maxRequestsPerConnection: -1 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers-error.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers-error.out.yaml index 5d6239cac0ef..af7b979d1139 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers-error.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers-error.out.yaml @@ -1,4 +1,26 @@ backendTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + creationTimestamp: null + name: policy-for-route + namespace: default + spec: + circuitBreaker: + maxRequestsPerConnection: -1 + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + namespace: default + status: + conditions: + - lastTransitionTime: null + message: 'Unable to translate Circuit Breaker: invalid MaxRequestsPerConnection + value -1' + reason: Invalid + status: "False" + type: Accepted - apiVersion: gateway.envoyproxy.io/v1alpha1 kind: BackendTrafficPolicy metadata: @@ -62,6 +84,46 @@ gateways: kind: HTTPRoute - group: gateway.networking.k8s.io kind: GRPCRoute +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-2 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 1 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute grpcRoutes: - apiVersion: gateway.networking.k8s.io/v1alpha2 kind: GRPCRoute @@ -96,6 +158,45 @@ grpcRoutes: name: gateway-1 namespace: envoy-gateway sectionName: http +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-1 + namespace: default + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - name: gateway-2 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: / + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-2 + namespace: envoy-gateway + sectionName: http infraIR: envoy-gateway/gateway-1: proxy: @@ -112,6 +213,21 @@ infraIR: gateway.envoyproxy.io/owning-gateway-name: gateway-1 gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway name: envoy-gateway/gateway-1 + envoy-gateway/gateway-2: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-2/http + ports: + - containerPort: 10080 + name: http + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-2 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-2 xdsIR: envoy-gateway/gateway-1: accessLog: @@ -141,4 +257,39 @@ xdsIR: protocol: GRPC weight: 1 hostname: '*' + isHTTP2: true name: grpcroute/default/grpcroute-1/rule/0/match/-1/* + envoy-gateway/gateway-2: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-2/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - backendWeights: + invalid: 0 + valid: 0 + destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: gateway.envoyproxy.io + isHTTP2: false + name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: / diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers.out.yaml index bcb293af7e34..f556715f0734 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-circuitbreakers.out.yaml @@ -255,6 +255,7 @@ xdsIR: maxConnections: 2048 maxParallelRequests: 4294967295 maxPendingRequests: 1 + maxRequestsPerConnection: 1 destination: name: grpcroute/default/grpcroute-1/rule/0 settings: @@ -265,6 +266,7 @@ xdsIR: protocol: GRPC weight: 1 hostname: '*' + isHTTP2: true name: grpcroute/default/grpcroute-1/rule/0/match/-1/* envoy-gateway/gateway-2: accessLog: @@ -288,6 +290,7 @@ xdsIR: maxConnections: 42 maxParallelRequests: 42 maxPendingRequests: 42 + maxRequestsPerConnection: 42 destination: name: httproute/default/httproute-1/rule/0 settings: @@ -298,6 +301,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml index c17d82f6c58b..78b8946cc3e4 100755 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml @@ -459,6 +459,7 @@ xdsIR: interval: 2s maxEjectionPercent: 100 hostname: '*' + isHTTP2: true name: grpcroute/default/grpcroute-1/rule/0/match/-1/* envoy-gateway/gateway-2: accessLog: @@ -503,6 +504,7 @@ xdsIR: interval: 1s maxEjectionPercent: 100 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-2/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false @@ -536,6 +538,7 @@ xdsIR: interval: 8ms maxEjectionPercent: 11 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-3/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false @@ -572,6 +575,7 @@ xdsIR: interval: 1s maxEjectionPercent: 100 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-loadbalancer.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-loadbalancer.out.yaml index 9d5bcd090da8..bab8fe348b4d 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-loadbalancer.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-loadbalancer.out.yaml @@ -341,6 +341,7 @@ xdsIR: protocol: GRPC weight: 1 hostname: '*' + isHTTP2: true loadBalancer: random: {} name: grpcroute/default/grpcroute-1/rule/0/match/-1/* @@ -372,6 +373,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false loadBalancer: leastRequest: slowStart: @@ -394,6 +396,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false loadBalancer: consistentHash: sourceIP: true diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-default-route-level-limit.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-default-route-level-limit.out.yaml index abc03a889986..e228e8776996 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-default-route-level-limit.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-default-route-level-limit.out.yaml @@ -167,6 +167,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-limit-unit.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-limit-unit.out.yaml index cb2cc3a2d65f..b5b012fec275 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-limit-unit.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-limit-unit.out.yaml @@ -171,6 +171,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-match-type.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-match-type.out.yaml index e1ad598d0d0c..7dd5dc16199a 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-match-type.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-match-type.out.yaml @@ -167,6 +167,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-multiple-route-level-limits.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-multiple-route-level-limits.out.yaml index 6aa90e650ebb..44be1dd47f23 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-multiple-route-level-limits.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit-invalid-multiple-route-level-limits.out.yaml @@ -173,6 +173,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit.out.yaml index b6a440898a51..d6dfc3c0cd4f 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-local-ratelimit.out.yaml @@ -170,6 +170,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-proxyprotocol.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-proxyprotocol.out.yaml index 9a6a94842042..04dfca6761d2 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-proxyprotocol.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-proxyprotocol.out.yaml @@ -255,6 +255,7 @@ xdsIR: protocol: GRPC weight: 1 hostname: '*' + isHTTP2: true name: grpcroute/default/grpcroute-1/rule/0/match/-1/* proxyProtocol: version: V1 @@ -286,6 +287,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit-invalid-regex.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit-invalid-regex.out.yaml index 4a807fcd435f..489f48f5a36a 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit-invalid-regex.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit-invalid-regex.out.yaml @@ -153,4 +153,5 @@ xdsIR: protocol: GRPC weight: 1 hostname: '*' + isHTTP2: true name: grpcroute/default/grpcroute-1/rule/0/match/-1/* diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit.out.yaml index 9d0268467bbb..87cd06f079c7 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit.out.yaml @@ -275,6 +275,7 @@ xdsIR: protocol: GRPC weight: 1 hostname: '*' + isHTTP2: true name: grpcroute/default/grpcroute-1/rule/0/match/-1/* rateLimit: global: @@ -316,6 +317,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-retries.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-retries.out.yaml index 76347ce5b792..9d3f4a10de7e 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-retries.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-retries.out.yaml @@ -274,6 +274,7 @@ xdsIR: protocol: GRPC weight: 1 hostname: '*' + isHTTP2: true name: grpcroute/default/grpcroute-1/rule/0/match/-1/* retry: perRetry: @@ -312,6 +313,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-same-prefix-httproutes.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-same-prefix-httproutes.out.yaml index 08a24c14b4bc..206a51d78e8a 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-same-prefix-httproutes.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-same-prefix-httproutes.out.yaml @@ -189,6 +189,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false @@ -207,6 +208,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcpkeepalive.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcpkeepalive.out.yaml index 3f9bbb33a3e6..b8edd449b87f 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcpkeepalive.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-tcpkeepalive.out.yaml @@ -259,6 +259,7 @@ xdsIR: protocol: GRPC weight: 1 hostname: '*' + isHTTP2: true name: grpcroute/default/grpcroute-1/rule/0/match/-1/* tcpKeepalive: idleTime: 1200 @@ -292,6 +293,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout-error.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout-error.out.yaml index 6feff83ca6bf..672c34f5bc45 100755 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout-error.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout-error.out.yaml @@ -145,4 +145,5 @@ xdsIR: protocol: GRPC weight: 1 hostname: '*' + isHTTP2: true name: grpcroute/default/grpcroute-1/rule/0/match/-1/* diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout.out.yaml index 9c5fe2dca531..5dc17c1c327b 100755 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout.out.yaml @@ -263,6 +263,7 @@ xdsIR: protocol: GRPC weight: 1 hostname: '*' + isHTTP2: true name: grpcroute/default/grpcroute-1/rule/0/match/-1/* timeout: http: @@ -298,6 +299,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-http3.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-http3.out.yaml index 1ffbde52972b..cafbbaa06ae4 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-http3.out.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-http3.out.yaml @@ -148,6 +148,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/extensions/httproute-with-valid-extension-filter.out.yaml b/internal/gatewayapi/testdata/extensions/httproute-with-valid-extension-filter.out.yaml index bee2d20033d8..b468c423db54 100644 --- a/internal/gatewayapi/testdata/extensions/httproute-with-valid-extension-filter.out.yaml +++ b/internal/gatewayapi/testdata/extensions/httproute-with-valid-extension-filter.out.yaml @@ -139,6 +139,7 @@ xdsIR: spec: data: stuff hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/gateway-allows-same-namespace-with-allowed-httproute.out.yaml b/internal/gatewayapi/testdata/gateway-allows-same-namespace-with-allowed-httproute.out.yaml index 93253e5b9dd9..4b5c58da3f16 100644 --- a/internal/gatewayapi/testdata/gateway-allows-same-namespace-with-allowed-httproute.out.yaml +++ b/internal/gatewayapi/testdata/gateway-allows-same-namespace-with-allowed-httproute.out.yaml @@ -119,6 +119,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/envoy-gateway/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/gateway-infrastructure.out.yaml b/internal/gatewayapi/testdata/gateway-infrastructure.out.yaml index 57e77d7b5f5d..c83cb118ca4a 100644 --- a/internal/gatewayapi/testdata/gateway-infrastructure.out.yaml +++ b/internal/gatewayapi/testdata/gateway-infrastructure.out.yaml @@ -137,6 +137,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-tls-secret-in-other-namespace-allowed-by-refgrant.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-tls-secret-in-other-namespace-allowed-by-refgrant.out.yaml index f72ccd5db183..3149574f2a70 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-tls-secret-in-other-namespace-allowed-by-refgrant.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-tls-secret-in-other-namespace-allowed-by-refgrant.out.yaml @@ -126,6 +126,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-tls-terminate-and-passthrough.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-tls-terminate-and-passthrough.out.yaml index e8683486282d..10d648c3c077 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-tls-terminate-and-passthrough.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-tls-terminate-and-passthrough.out.yaml @@ -195,6 +195,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: foo.bar.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/foo_bar_com pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration-with-same-algorithm-different-fqdn.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration-with-same-algorithm-different-fqdn.out.yaml index e2cd9a173fee..f4d7c106a12b 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration-with-same-algorithm-different-fqdn.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration-with-same-algorithm-different-fqdn.out.yaml @@ -128,6 +128,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration.out.yaml index 741785be4b67..d7ead7a8e2b2 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-valid-multiple-tls-configuration.out.yaml @@ -128,6 +128,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-valid-tls-configuration.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-valid-tls-configuration.out.yaml index bc02d7f95435..3c5182cc5a29 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-valid-tls-configuration.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-valid-tls-configuration.out.yaml @@ -125,6 +125,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/gateway-with-preexisting-status-condition.out.yaml b/internal/gatewayapi/testdata/gateway-with-preexisting-status-condition.out.yaml index da6a4630591f..d2dce6e0af75 100644 --- a/internal/gatewayapi/testdata/gateway-with-preexisting-status-condition.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-preexisting-status-condition.out.yaml @@ -119,6 +119,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/gateway-with-stale-status-condition.out.yaml b/internal/gatewayapi/testdata/gateway-with-stale-status-condition.out.yaml index aae3821da4d6..72c9325677f7 100644 --- a/internal/gatewayapi/testdata/gateway-with-stale-status-condition.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-stale-status-condition.out.yaml @@ -125,6 +125,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-multiple-httproutes.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-multiple-httproutes.out.yaml index 450ca22686fa..267296982ad3 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-multiple-httproutes.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-multiple-httproutes.out.yaml @@ -191,6 +191,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: foo.com + isHTTP2: false name: httproute/default/httproute-2/rule/0/match/0/foo_com pathMatch: distinct: false @@ -209,6 +210,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: foo.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/foo_com pathMatch: distinct: false @@ -237,6 +239,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: bar.com + isHTTP2: false name: httproute/default/httproute-2/rule/0/match/0/bar_com pathMatch: distinct: false @@ -255,6 +258,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: bar.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/bar_com pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-tcp-protocol.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-tcp-protocol.out.yaml index 28c85b2b5926..61119e9b76a9 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-tcp-protocol.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-tcp-protocol.out.yaml @@ -186,6 +186,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-udp-protocol.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-udp-protocol.out.yaml index 152181990886..fb19c1102f60 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-udp-protocol.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-udp-protocol.out.yaml @@ -186,6 +186,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/grpcroute-with-header-match.out.yaml b/internal/gatewayapi/testdata/grpcroute-with-header-match.out.yaml index c7dc5625f0dc..d2abc957458f 100644 --- a/internal/gatewayapi/testdata/grpcroute-with-header-match.out.yaml +++ b/internal/gatewayapi/testdata/grpcroute-with-header-match.out.yaml @@ -127,4 +127,5 @@ xdsIR: exact: foo name: magic hostname: '*' + isHTTP2: true name: grpcroute/default/grpcroute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/grpcroute-with-method-and-service-match.out.yaml b/internal/gatewayapi/testdata/grpcroute-with-method-and-service-match.out.yaml index c5bf727817fd..45acfd7e6147 100644 --- a/internal/gatewayapi/testdata/grpcroute-with-method-and-service-match.out.yaml +++ b/internal/gatewayapi/testdata/grpcroute-with-method-and-service-match.out.yaml @@ -127,6 +127,7 @@ xdsIR: protocol: GRPC weight: 1 hostname: '*' + isHTTP2: true name: grpcroute/default/grpcroute-1/rule/0/match/0/* pathMatch: distinct: false @@ -145,6 +146,7 @@ xdsIR: protocol: GRPC weight: 1 hostname: '*' + isHTTP2: true name: grpcroute/default/grpcroute-1/rule/0/match/1/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/grpcroute-with-method-match.out.yaml b/internal/gatewayapi/testdata/grpcroute-with-method-match.out.yaml index 864dddf6f6b4..67ed17a35f4d 100644 --- a/internal/gatewayapi/testdata/grpcroute-with-method-match.out.yaml +++ b/internal/gatewayapi/testdata/grpcroute-with-method-match.out.yaml @@ -125,6 +125,7 @@ xdsIR: protocol: GRPC weight: 1 hostname: '*' + isHTTP2: true name: grpcroute/default/grpcroute-1/rule/0/match/1/* pathMatch: distinct: false @@ -147,4 +148,5 @@ xdsIR: name: :path suffix: /ExampleExact hostname: '*' + isHTTP2: true name: grpcroute/default/grpcroute-1/rule/0/match/0/* 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 879cc4470cec..76f8148dce58 100644 --- a/internal/gatewayapi/testdata/grpcroute-with-request-header-modifier.out.yaml +++ b/internal/gatewayapi/testdata/grpcroute-with-request-header-modifier.out.yaml @@ -128,4 +128,5 @@ xdsIR: protocol: GRPC weight: 1 hostname: '*' + isHTTP2: true name: grpcroute/default/grpcroute-1/rule/0/match/-1/* diff --git a/internal/gatewayapi/testdata/grpcroute-with-service-match.out.yaml b/internal/gatewayapi/testdata/grpcroute-with-service-match.out.yaml index 231851d40dec..9624ffcaab1a 100644 --- a/internal/gatewayapi/testdata/grpcroute-with-service-match.out.yaml +++ b/internal/gatewayapi/testdata/grpcroute-with-service-match.out.yaml @@ -125,6 +125,7 @@ xdsIR: protocol: GRPC weight: 1 hostname: '*' + isHTTP2: true name: grpcroute/default/grpcroute-1/rule/0/match/0/* pathMatch: distinct: false @@ -143,6 +144,7 @@ xdsIR: protocol: GRPC weight: 1 hostname: '*' + isHTTP2: true name: grpcroute/default/grpcroute-1/rule/0/match/1/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout-error.out.yaml b/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout-error.out.yaml index 7087de39768c..2cb3682b8462 100755 --- a/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout-error.out.yaml +++ b/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout-error.out.yaml @@ -150,6 +150,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout.out.yaml b/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout.out.yaml index 4f34e9e2b46e..9fd9cf55b56d 100755 --- a/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout.out.yaml +++ b/internal/gatewayapi/testdata/httproute-and-backendtrafficpolicy-with-timeout.out.yaml @@ -264,6 +264,7 @@ xdsIR: protocol: GRPC weight: 1 hostname: '*' + isHTTP2: true name: grpcroute/default/grpcroute-1/rule/0/match/-1/* timeout: http: @@ -299,6 +300,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-more-different-listeners.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-more-different-listeners.out.yaml index 6fe027dc93da..9d0c0d570c98 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-more-different-listeners.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-more-different-listeners.out.yaml @@ -379,6 +379,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: foo.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/foo_com pathMatch: distinct: false @@ -407,6 +408,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: bar.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/bar_com pathMatch: distinct: false @@ -435,6 +437,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: foo1.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/foo1_com pathMatch: distinct: false @@ -463,6 +466,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: bar1.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/bar1_com pathMatch: distinct: false @@ -491,6 +495,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: foo2.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/foo2_com pathMatch: distinct: false @@ -519,6 +524,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: bar2.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/bar2_com pathMatch: distinct: false @@ -547,6 +553,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: foo3.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/foo3_com pathMatch: distinct: false @@ -575,6 +582,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: bar3.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/bar3_com pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-more-listeners.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-more-listeners.out.yaml index 2e7dfc189f5c..900412333360 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-more-listeners.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-more-listeners.out.yaml @@ -330,6 +330,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: foo.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/foo_com pathMatch: distinct: false @@ -358,6 +359,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: bar.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/bar_com pathMatch: distinct: false @@ -386,6 +388,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: foo1.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/foo1_com pathMatch: distinct: false @@ -414,6 +417,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: bar1.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/bar1_com pathMatch: distinct: false @@ -442,6 +446,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: foo2.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/foo2_com pathMatch: distinct: false @@ -470,6 +475,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: bar2.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/bar2_com pathMatch: distinct: false @@ -498,6 +504,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: foo3.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/foo3_com pathMatch: distinct: false @@ -526,6 +533,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: bar3.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/bar3_com pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-two-listeners-with-different-ports.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-two-listeners-with-different-ports.out.yaml index fbb816e0e088..5637d770bc7b 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-two-listeners-with-different-ports.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-two-listeners-with-different-ports.out.yaml @@ -161,6 +161,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false @@ -189,6 +190,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-two-listeners.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-two-listeners.out.yaml index bfa550205f14..cda246ecc6c4 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-two-listeners.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-gateway-with-two-listeners.out.yaml @@ -150,6 +150,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: foo.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/foo_com pathMatch: distinct: false @@ -178,6 +179,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: bar.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/bar_com pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-gateway.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-gateway.out.yaml index 77055214392e..39834ebc86ea 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-gateway.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-gateway.out.yaml @@ -119,6 +119,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-matching-port.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-matching-port.out.yaml index affe7bd4a7da..813d92502778 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-listener-matching-port.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-matching-port.out.yaml @@ -123,6 +123,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-on-gateway-with-two-listeners.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-on-gateway-with-two-listeners.out.yaml index 7d6a36622010..bbc2f85502af 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-listener-on-gateway-with-two-listeners.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-on-gateway-with-two-listeners.out.yaml @@ -161,6 +161,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: bar.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/bar_com pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-serviceimport-backendrefs-diff-address-type.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-serviceimport-backendrefs-diff-address-type.out.yaml index 3ec90700af69..967713517a0e 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-serviceimport-backendrefs-diff-address-type.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-serviceimport-backendrefs-diff-address-type.out.yaml @@ -133,6 +133,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-serviceimport-backendrefs-same-address-type.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-serviceimport-backendrefs-same-address-type.out.yaml index fb9339aea144..2a60e150ec6b 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-serviceimport-backendrefs-same-address-type.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-serviceimport-backendrefs-same-address-type.out.yaml @@ -133,6 +133,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref-fqdn-address-type.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref-fqdn-address-type.out.yaml index 77dca838d875..369959e0c7de 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref-fqdn-address-type.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref-fqdn-address-type.out.yaml @@ -123,6 +123,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref-mixed-address-type.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref-mixed-address-type.out.yaml index 7f2664975bc3..cd98ee93cc89 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref-mixed-address-type.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref-mixed-address-type.out.yaml @@ -125,6 +125,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref.out.yaml index 94da4357e7bc..8ffa5793822f 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref.out.yaml @@ -123,6 +123,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener.out.yaml index 0eb0237ab303..55c1ac1b83d1 100644 --- a/internal/gatewayapi/testdata/httproute-attaching-to-listener.out.yaml +++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener.out.yaml @@ -121,6 +121,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-backend-request-timeout.out.yaml b/internal/gatewayapi/testdata/httproute-backend-request-timeout.out.yaml index d30ba8e89704..e448a02bf2d0 100644 --- a/internal/gatewayapi/testdata/httproute-backend-request-timeout.out.yaml +++ b/internal/gatewayapi/testdata/httproute-backend-request-timeout.out.yaml @@ -123,6 +123,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-request-timeout.out.yaml b/internal/gatewayapi/testdata/httproute-request-timeout.out.yaml index 6001280e0974..ec80e30e1e8f 100644 --- a/internal/gatewayapi/testdata/httproute-request-timeout.out.yaml +++ b/internal/gatewayapi/testdata/httproute-request-timeout.out.yaml @@ -123,6 +123,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-no-weights.out.yaml b/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-no-weights.out.yaml index 643f69900d0d..048b705766e7 100644 --- a/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-no-weights.out.yaml +++ b/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-no-weights.out.yaml @@ -135,6 +135,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-weights.out.yaml b/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-weights.out.yaml index 8cb654878a71..53038b2348be 100644 --- a/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-weights.out.yaml +++ b/internal/gatewayapi/testdata/httproute-rule-with-multiple-backends-and-weights.out.yaml @@ -141,6 +141,7 @@ xdsIR: protocol: HTTP weight: 3 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-backendref-in-other-namespace-allowed-by-refgrant.out.yaml b/internal/gatewayapi/testdata/httproute-with-backendref-in-other-namespace-allowed-by-refgrant.out.yaml index 87fbbab63cc3..b827af53150c 100644 --- a/internal/gatewayapi/testdata/httproute-with-backendref-in-other-namespace-allowed-by-refgrant.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-backendref-in-other-namespace-allowed-by-refgrant.out.yaml @@ -121,6 +121,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-backendref-serviceimport-in-other-namespace-allowed-by-refgrant.out.yaml b/internal/gatewayapi/testdata/httproute-with-backendref-serviceimport-in-other-namespace-allowed-by-refgrant.out.yaml index d4210c168268..485d59bcde18 100644 --- a/internal/gatewayapi/testdata/httproute-with-backendref-serviceimport-in-other-namespace-allowed-by-refgrant.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-backendref-serviceimport-in-other-namespace-allowed-by-refgrant.out.yaml @@ -123,6 +123,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-empty-matches.out.yaml b/internal/gatewayapi/testdata/httproute-with-empty-matches.out.yaml index 3548d51c01ed..5ef60eccf6a2 100644 --- a/internal/gatewayapi/testdata/httproute-with-empty-matches.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-empty-matches.out.yaml @@ -118,4 +118,5 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/-1/* 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 aae26304aa73..9d439afa3c62 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 @@ -149,6 +149,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false 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 b8502e6f6d5f..7d69c437116c 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 @@ -165,6 +165,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-remove-multiple-filters.out.yaml b/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-remove-multiple-filters.out.yaml index 9a5096c8977b..f8a325b46ee6 100644 --- a/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-remove-multiple-filters.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-remove-multiple-filters.out.yaml @@ -135,6 +135,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-removes.out.yaml b/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-removes.out.yaml index 6578feab64fe..53c939f2b0df 100644 --- a/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-removes.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-removes.out.yaml @@ -130,6 +130,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false 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 7705fdfabaea..b5193139bbeb 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 @@ -140,6 +140,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-header-filter-no-headers.out.yaml b/internal/gatewayapi/testdata/httproute-with-header-filter-no-headers.out.yaml index 7a884c68a640..c3ab6b9f0210 100644 --- a/internal/gatewayapi/testdata/httproute-with-header-filter-no-headers.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-header-filter-no-headers.out.yaml @@ -127,6 +127,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-header-filter-remove.out.yaml b/internal/gatewayapi/testdata/httproute-with-header-filter-remove.out.yaml index c477945ad91c..3ac50c40bac5 100644 --- a/internal/gatewayapi/testdata/httproute-with-header-filter-remove.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-header-filter-remove.out.yaml @@ -131,6 +131,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-bad-port.out.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-bad-port.out.yaml index 01c173f38ac0..9c3bab389cf1 100644 --- a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-bad-port.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-bad-port.out.yaml @@ -113,6 +113,7 @@ xdsIR: directResponse: statusCode: 500 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-group.out.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-group.out.yaml index b276db338143..5f78538385f5 100644 --- a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-group.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-group.out.yaml @@ -117,6 +117,7 @@ xdsIR: directResponse: statusCode: 500 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-kind.out.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-kind.out.yaml index 4a803481a22a..b38425e7563a 100644 --- a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-kind.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-kind.out.yaml @@ -114,6 +114,7 @@ xdsIR: directResponse: statusCode: 500 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-port.out.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-port.out.yaml index 71bde7725ea3..6668252cdbc7 100644 --- a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-port.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-port.out.yaml @@ -113,6 +113,7 @@ xdsIR: directResponse: statusCode: 500 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-service.import.out.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-service.import.out.yaml index 00148a729ab5..da0bce317d6b 100644 --- a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-service.import.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-service.import.out.yaml @@ -115,6 +115,7 @@ xdsIR: directResponse: statusCode: 500 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-service.out.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-service.out.yaml index dc732a9e6340..ddaccd43a104 100644 --- a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-service.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-service.out.yaml @@ -113,6 +113,7 @@ xdsIR: directResponse: statusCode: 500 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-unsupported-filter.in.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-unsupported-filter.in.yaml new file mode 100644 index 000000000000..236a10736d20 --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-unsupported-filter.in.yaml @@ -0,0 +1,39 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-1 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + rules: + - matches: + - path: + type: Exact + value: "/exact" + backendRefs: + - name: service-1 + port: 8080 + filters: + - type: ResponseHeaderModifier + responseHeaderModifier: + set: + - name: "set-header-1" + value: "some-value" diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-unsupported-filter.out.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-unsupported-filter.out.yaml new file mode 100755 index 000000000000..f916d3030532 --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-unsupported-filter.out.yaml @@ -0,0 +1,127 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 1 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-1 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + rules: + - backendRefs: + - filters: + - responseHeaderModifier: + set: + - name: set-header-1 + value: some-value + type: ResponseHeaderModifier + name: service-1 + port: 8080 + matches: + - path: + type: Exact + value: /exact + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: The filters field within BackendRef is not supported + reason: UnsupportedRefValue + status: "False" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-1/http + ports: + - containerPort: 10080 + name: http + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-1 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - backendWeights: + invalid: 1 + valid: 0 + directResponse: + statusCode: 500 + hostname: '*' + isHTTP2: false + name: httproute/default/httproute-1/rule/0/match/0/* + pathMatch: + distinct: false + exact: /exact + name: "" diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-backendref-in-other-namespace.out.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-backendref-in-other-namespace.out.yaml index c5b4a11fc631..8d622b366803 100644 --- a/internal/gatewayapi/testdata/httproute-with-invalid-backendref-in-other-namespace.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-invalid-backendref-in-other-namespace.out.yaml @@ -114,6 +114,7 @@ xdsIR: directResponse: statusCode: 500 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-mirror-filter-duplicates.out.yaml b/internal/gatewayapi/testdata/httproute-with-mirror-filter-duplicates.out.yaml index 83ebeba62da5..431a85a1dca1 100644 --- a/internal/gatewayapi/testdata/httproute-with-mirror-filter-duplicates.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-mirror-filter-duplicates.out.yaml @@ -137,6 +137,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false mirrors: - name: httproute/default/httproute-1/rule/0-mirror-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 7c62a1f0c231..8588726a36eb 100644 --- a/internal/gatewayapi/testdata/httproute-with-mirror-filter-multiple.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-mirror-filter-multiple.out.yaml @@ -159,6 +159,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false mirrors: - name: httproute/default/httproute-1/rule/0-mirror-1 settings: diff --git a/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-no-port.out.yaml b/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-no-port.out.yaml index 8437bcb07025..a5b71817a086 100644 --- a/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-no-port.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-no-port.out.yaml @@ -131,6 +131,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-not-found.out.yaml b/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-not-found.out.yaml index dd562ce8c9f7..a9fb238b04f6 100644 --- a/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-not-found.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-not-found.out.yaml @@ -131,6 +131,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-mirror-filter.out.yaml b/internal/gatewayapi/testdata/httproute-with-mirror-filter.out.yaml index df106f915c61..d324d2465149 100644 --- a/internal/gatewayapi/testdata/httproute-with-mirror-filter.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-mirror-filter.out.yaml @@ -131,6 +131,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false mirrors: - name: httproute/default/httproute-1/rule/0-mirror-0 settings: diff --git a/internal/gatewayapi/testdata/httproute-with-redirect-filter-full-path-replace-https.out.yaml b/internal/gatewayapi/testdata/httproute-with-redirect-filter-full-path-replace-https.out.yaml index 3947ff48a908..a786efec2833 100644 --- a/internal/gatewayapi/testdata/httproute-with-redirect-filter-full-path-replace-https.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-redirect-filter-full-path-replace-https.out.yaml @@ -123,6 +123,7 @@ xdsIR: invalid: 0 valid: 0 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-redirect-filter-hostname.out.yaml b/internal/gatewayapi/testdata/httproute-with-redirect-filter-hostname.out.yaml index aa327a0b959d..97f129b026c8 100644 --- a/internal/gatewayapi/testdata/httproute-with-redirect-filter-hostname.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-redirect-filter-hostname.out.yaml @@ -121,6 +121,7 @@ xdsIR: invalid: 0 valid: 0 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-redirect-filter-prefix-replace-with-port-http.out.yaml b/internal/gatewayapi/testdata/httproute-with-redirect-filter-prefix-replace-with-port-http.out.yaml index c6fe24cbab13..09be04932d99 100644 --- a/internal/gatewayapi/testdata/httproute-with-redirect-filter-prefix-replace-with-port-http.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-redirect-filter-prefix-replace-with-port-http.out.yaml @@ -124,6 +124,7 @@ xdsIR: invalid: 0 valid: 0 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false 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 9392479ccea2..43c7a116b4b9 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 @@ -161,6 +161,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false 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 fee2bd210978..4fba4eb7b99c 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 @@ -149,6 +149,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false 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 a91ca6103c4d..61441d6a1d62 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 @@ -165,6 +165,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-remove-multiple-filters.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-remove-multiple-filters.out.yaml index 5ab2a26ae47c..4f58c01222d7 100644 --- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-remove-multiple-filters.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-remove-multiple-filters.out.yaml @@ -135,6 +135,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-removes.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-removes.out.yaml index 2bb71c3ed7eb..0cd94a754a4a 100644 --- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-removes.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-removes.out.yaml @@ -130,6 +130,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false 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 3752d8e55a01..b7f3e26ef42f 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 @@ -140,6 +140,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-no-headers.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-no-headers.out.yaml index 23dc715f3566..48c3b5f8f5b3 100644 --- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-no-headers.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-no-headers.out.yaml @@ -127,6 +127,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-remove.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-remove.out.yaml index 04fde189169a..1ea53e4797df 100644 --- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-remove.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-remove.out.yaml @@ -131,6 +131,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-single-rule-with-exact-path-match.out.yaml b/internal/gatewayapi/testdata/httproute-with-single-rule-with-exact-path-match.out.yaml index 45c81d7d3961..0b9bc1037ecc 100644 --- a/internal/gatewayapi/testdata/httproute-with-single-rule-with-exact-path-match.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-single-rule-with-exact-path-match.out.yaml @@ -120,6 +120,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-single-rule-with-http-method-match.out.yaml b/internal/gatewayapi/testdata/httproute-with-single-rule-with-http-method-match.out.yaml index bf140ce157cf..291e21eebccf 100644 --- a/internal/gatewayapi/testdata/httproute-with-single-rule-with-http-method-match.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-single-rule-with-http-method-match.out.yaml @@ -122,4 +122,5 @@ xdsIR: exact: POST name: :method hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/httproute-with-single-rule-with-path-prefix-and-exact-header-matches.out.yaml b/internal/gatewayapi/testdata/httproute-with-single-rule-with-path-prefix-and-exact-header-matches.out.yaml index 00156188b42f..b16e4cfe932f 100644 --- a/internal/gatewayapi/testdata/httproute-with-single-rule-with-path-prefix-and-exact-header-matches.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-single-rule-with-path-prefix-and-exact-header-matches.out.yaml @@ -131,6 +131,7 @@ xdsIR: exact: Val-2 name: Header-2 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-some-invalid-backend-refs-no-service.out.yaml b/internal/gatewayapi/testdata/httproute-with-some-invalid-backend-refs-no-service.out.yaml index 0f7128fea24c..ad7e977d4a85 100644 --- a/internal/gatewayapi/testdata/httproute-with-some-invalid-backend-refs-no-service.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-some-invalid-backend-refs-no-service.out.yaml @@ -124,6 +124,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-specific-hostname-attaching-to-gateway-with-wildcard-hostname.out.yaml b/internal/gatewayapi/testdata/httproute-with-specific-hostname-attaching-to-gateway-with-wildcard-hostname.out.yaml index 42931795df85..2beec1c17f53 100644 --- a/internal/gatewayapi/testdata/httproute-with-specific-hostname-attaching-to-gateway-with-wildcard-hostname.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-specific-hostname-attaching-to-gateway-with-wildcard-hostname.out.yaml @@ -122,6 +122,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-two-specific-hostnames-attaching-to-gateway-with-wildcard-hostname.out.yaml b/internal/gatewayapi/testdata/httproute-with-two-specific-hostnames-attaching-to-gateway-with-wildcard-hostname.out.yaml index b3920b0478ae..a2a913ec417a 100644 --- a/internal/gatewayapi/testdata/httproute-with-two-specific-hostnames-attaching-to-gateway-with-wildcard-hostname.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-two-specific-hostnames-attaching-to-gateway-with-wildcard-hostname.out.yaml @@ -123,6 +123,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false @@ -141,6 +142,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: whales.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/whales_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-full-path-replace-http.out.yaml b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-full-path-replace-http.out.yaml index 39989471f38a..8b2138f2100b 100644 --- a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-full-path-replace-http.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-full-path-replace-http.out.yaml @@ -130,6 +130,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-hostname-prefix-replace.out.yaml b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-hostname-prefix-replace.out.yaml index 7e1364ae96e9..9ea570c292b0 100644 --- a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-hostname-prefix-replace.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-hostname-prefix-replace.out.yaml @@ -131,6 +131,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-hostname.out.yaml b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-hostname.out.yaml index 2209165a18f6..bf682e88b35c 100644 --- a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-hostname.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-hostname.out.yaml @@ -128,6 +128,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-filter-type.out.yaml b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-filter-type.out.yaml index bfbe2d70d281..b85ff6e2db35 100644 --- a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-filter-type.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-invalid-filter-type.out.yaml @@ -128,6 +128,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-prefix-replace-http.out.yaml b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-prefix-replace-http.out.yaml index c23a593b95b3..bc23aabd4d75 100644 --- a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-prefix-replace-http.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-prefix-replace-http.out.yaml @@ -130,6 +130,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproute-with-wildcard-hostname-attaching-to-gateway-with-unset-hostname.out.yaml b/internal/gatewayapi/testdata/httproute-with-wildcard-hostname-attaching-to-gateway-with-unset-hostname.out.yaml index 0570ee57378a..8d436c384cb2 100644 --- a/internal/gatewayapi/testdata/httproute-with-wildcard-hostname-attaching-to-gateway-with-unset-hostname.out.yaml +++ b/internal/gatewayapi/testdata/httproute-with-wildcard-hostname-attaching-to-gateway-with-unset-hostname.out.yaml @@ -121,6 +121,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*.envoyproxy.io' + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/*_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/httproutes-with-multiple-matches.out.yaml b/internal/gatewayapi/testdata/httproutes-with-multiple-matches.out.yaml index 6a2feea08a35..325c79da51dc 100644 --- a/internal/gatewayapi/testdata/httproutes-with-multiple-matches.out.yaml +++ b/internal/gatewayapi/testdata/httproutes-with-multiple-matches.out.yaml @@ -306,6 +306,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: example.com + isHTTP2: false name: httproute/envoy-gateway/httproute-2/rule/0/match/0/example_com pathMatch: distinct: false @@ -328,6 +329,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: example.com + isHTTP2: false name: httproute/envoy-gateway/httproute-3/rule/0/match/0/example_com pathMatch: distinct: false @@ -350,6 +352,7 @@ xdsIR: exact: one name: version hostname: example.net + isHTTP2: false name: httproute/envoy-gateway/httproute-4/rule/0/match/0/example_net pathMatch: distinct: false @@ -368,6 +371,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: example.net + isHTTP2: false name: httproute/envoy-gateway/httproute-5/rule/0/match/0/example_net pathMatch: distinct: false @@ -386,6 +390,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*.com' + isHTTP2: false name: httproute/envoy-gateway/httproute-1/rule/0/match/0/*_com pathMatch: distinct: false @@ -404,6 +409,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*.net' + isHTTP2: false name: httproute/envoy-gateway/httproute-1/rule/0/match/0/*_net pathMatch: distinct: false @@ -422,6 +428,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: '*' + isHTTP2: false name: httproute/envoy-gateway/httproute-1/rule/0/match/0/* pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/merge-valid-multiple-gateways-multiple-routes.out.yaml b/internal/gatewayapi/testdata/merge-valid-multiple-gateways-multiple-routes.out.yaml index e3c179523202..073d47f8cfc9 100644 --- a/internal/gatewayapi/testdata/merge-valid-multiple-gateways-multiple-routes.out.yaml +++ b/internal/gatewayapi/testdata/merge-valid-multiple-gateways-multiple-routes.out.yaml @@ -246,6 +246,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false @@ -283,6 +284,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: example.com + isHTTP2: false name: httproute/default/httproute-2/rule/0/match/0/example_com pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/merge-with-isolated-policies.in.yaml b/internal/gatewayapi/testdata/merge-with-isolated-policies.in.yaml new file mode 100644 index 000000000000..2ce31b166c6a --- /dev/null +++ b/internal/gatewayapi/testdata/merge-with-isolated-policies.in.yaml @@ -0,0 +1,132 @@ +envoyproxy: + apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyProxy + metadata: + namespace: envoy-gateway-system + name: test + spec: + mergeGateways: true +gateways: + - apiVersion: gateway.networking.k8s.io/v1beta1 + kind: Gateway + metadata: + name: gateway-1 + namespace: default + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + port: 80 + protocol: HTTP + allowedRoutes: + namespaces: + from: Same + - apiVersion: gateway.networking.k8s.io/v1beta1 + kind: Gateway + metadata: + name: gateway-2 + namespace: default + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http-2 + port: 8888 + protocol: HTTP + allowedRoutes: + namespaces: + from: Same +httpRoutes: + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-1 + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - namespace: default + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/" + backendRefs: + - name: service-1 + port: 8080 + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-2 + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - namespace: default + name: gateway-2 + sectionName: http-2 + rules: + - matches: + - path: + value: "/" + backendRefs: + - name: service-2 + port: 8080 +securityPolicies: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + namespace: default + name: policy-for-route-2 + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: default + cors: + allowOrigins: + - "*" + allowMethods: + - GET + - POST + allowHeaders: + - "x-header-5" + - "x-header-6" + exposeHeaders: + - "x-header-7" + - "x-header-8" + maxAge: 2000s +clientTrafficPolicies: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + namespace: default + name: target-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-2 + namespace: default + timeout: + http: + requestReceivedTimeout: "5s" +backendTrafficPolicies: + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + namespace: default + name: policy-for-gateway + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: default + tcpKeepalive: + probes: 3 + idleTime: 20m + interval: 60s diff --git a/internal/gatewayapi/testdata/merge-with-isolated-policies.out.yaml b/internal/gatewayapi/testdata/merge-with-isolated-policies.out.yaml new file mode 100644 index 000000000000..a23c58be9b69 --- /dev/null +++ b/internal/gatewayapi/testdata/merge-with-isolated-policies.out.yaml @@ -0,0 +1,357 @@ +backendTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + creationTimestamp: null + name: policy-for-gateway + namespace: default + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: default + tcpKeepalive: + idleTime: 20m + interval: 60s + probes: 3 + status: + conditions: + - lastTransitionTime: null + message: BackendTrafficPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +clientTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: ClientTrafficPolicy + metadata: + creationTimestamp: null + name: target-gateway + namespace: default + spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-2 + namespace: default + timeout: + http: + requestReceivedTimeout: 5s + status: + conditions: + - lastTransitionTime: null + message: ClientTrafficPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +gateways: +- apiVersion: gateway.networking.k8s.io/v1beta1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: default + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: Same + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 1 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +- apiVersion: gateway.networking.k8s.io/v1beta1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-2 + namespace: default + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: Same + name: http-2 + port: 8888 + protocol: HTTP + status: + listeners: + - attachedRoutes: 1 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http-2 + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-1 + namespace: default + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - name: gateway-1 + namespace: default + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: / + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: default + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-2 + namespace: default + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - name: gateway-2 + namespace: default + sectionName: http-2 + rules: + - backendRefs: + - name: service-2 + port: 8080 + matches: + - path: + value: / + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-2 + namespace: default + sectionName: http-2 +infraIR: + envoy-gateway-class: + proxy: + config: + apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: EnvoyProxy + metadata: + creationTimestamp: null + name: test + namespace: envoy-gateway-system + spec: + logging: {} + mergeGateways: true + status: {} + listeners: + - address: null + name: default/gateway-1/http + ports: + - containerPort: 10080 + name: default/gateway-1/http + protocol: HTTP + servicePort: 80 + - address: null + name: default/gateway-2/http-2 + ports: + - containerPort: 8888 + name: default/gateway-2/http-2 + protocol: HTTP + servicePort: 8888 + metadata: + labels: + gateway.envoyproxy.io/owning-gatewayclass: envoy-gateway-class + name: envoy-gateway-class +securityPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + creationTimestamp: null + name: policy-for-route-2 + namespace: default + spec: + cors: + allowHeaders: + - x-header-5 + - x-header-6 + allowMethods: + - GET + - POST + allowOrigins: + - '*' + exposeHeaders: + - x-header-7 + - x-header-8 + maxAge: 33m20s + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: default + status: + conditions: + - lastTransitionTime: null + message: SecurityPolicy has been accepted. + reason: Accepted + status: "True" + type: Accepted +xdsIR: + envoy-gateway-class: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: default/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - backendWeights: + invalid: 0 + valid: 0 + cors: + allowHeaders: + - x-header-5 + - x-header-6 + allowMethods: + - GET + - POST + allowOrigins: + - distinct: false + name: "" + safeRegex: .* + exposeHeaders: + - x-header-7 + - x-header-8 + maxAge: 33m20s + destination: + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: gateway.envoyproxy.io + isHTTP2: false + name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: / + tcpKeepalive: + idleTime: 1200 + interval: 60 + probes: 3 + - address: 0.0.0.0 + hostnames: + - '*' + isHTTP2: false + name: default/gateway-2/http-2 + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 8888 + routes: + - 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 + hostname: gateway.envoyproxy.io + isHTTP2: false + name: httproute/default/httproute-2/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: / + timeout: + http: + requestReceivedTimeout: 5s diff --git a/internal/gatewayapi/testdata/securitypolicy-status-conditions.out.yaml b/internal/gatewayapi/testdata/securitypolicy-status-conditions.out.yaml index d4471cd24f32..a0317b8cb596 100644 --- a/internal/gatewayapi/testdata/securitypolicy-status-conditions.out.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-status-conditions.out.yaml @@ -360,6 +360,7 @@ xdsIR: directResponse: statusCode: 500 hostname: '*' + isHTTP2: false name: httproute/envoy-gateway/httproute-1/rule/0/match/0/* pathMatch: distinct: false @@ -390,4 +391,5 @@ xdsIR: exact: foo name: magic hostname: '*' + isHTTP2: true name: grpcroute/envoy-gateway/grpcroute-1/rule/0/match/0/* diff --git a/internal/gatewayapi/testdata/securitypolicy-with-basic-auth.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-basic-auth.out.yaml index 96c93cd3e938..793ada202e99 100644 --- a/internal/gatewayapi/testdata/securitypolicy-with-basic-auth.out.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-basic-auth.out.yaml @@ -150,6 +150,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/securitypolicy-with-cors.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-cors.out.yaml index c50b5e03ad6e..40e431d4324a 100644 --- a/internal/gatewayapi/testdata/securitypolicy-with-cors.out.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-cors.out.yaml @@ -426,6 +426,7 @@ xdsIR: protocol: GRPC weight: 1 hostname: '*' + isHTTP2: true name: grpcroute/default/grpcroute-1/rule/0/match/-1/* envoy-gateway/gateway-2: accessLog: @@ -473,6 +474,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false @@ -521,6 +523,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false name: httproute/default/httproute-2/rule/0/match/0/gateway_envoyproxy_io pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-matching-port.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-matching-port.out.yaml index d7acc9b0a32d..bf16c864b020 100755 --- a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-matching-port.out.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-matching-port.out.yaml @@ -152,6 +152,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: www.foo.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/www_foo_com pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-reference-grant.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-reference-grant.out.yaml index 46f93304a508..975f2f7f894f 100755 --- a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-reference-grant.out.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-reference-grant.out.yaml @@ -153,6 +153,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: www.foo.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/www_foo_com pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-service.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-service.out.yaml index dfd4c3f88d1c..d314d430d0b5 100755 --- a/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-service.out.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-invalid-no-service.out.yaml @@ -152,6 +152,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: www.foo.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/www_foo_com pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth.out.yaml index 412c56438097..76d0285f0061 100755 --- a/internal/gatewayapi/testdata/securitypolicy-with-extauth.out.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth.out.yaml @@ -233,6 +233,7 @@ xdsIR: - header1 - header2 hostname: www.foo.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/www_foo_com pathMatch: distinct: false @@ -267,6 +268,7 @@ xdsIR: - header2 path: /auth hostname: www.bar.com + isHTTP2: false name: httproute/default/httproute-2/rule/0/match/0/www_bar_com pathMatch: distinct: false diff --git a/internal/gatewayapi/testdata/securitypolicy-with-jwt-and-invalid-oidc.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-jwt-and-invalid-oidc.out.yaml index 367f2d30acfd..17072300d821 100644 --- a/internal/gatewayapi/testdata/securitypolicy-with-jwt-and-invalid-oidc.out.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-jwt-and-invalid-oidc.out.yaml @@ -238,6 +238,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false jwt: providers: - audiences: @@ -267,6 +268,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false jwt: providers: - audiences: diff --git a/internal/gatewayapi/testdata/securitypolicy-with-jwt-with-custom-extractor.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-jwt-with-custom-extractor.out.yaml index 10b9b7e2d4ed..b3bd5c88ce74 100644 --- a/internal/gatewayapi/testdata/securitypolicy-with-jwt-with-custom-extractor.out.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-jwt-with-custom-extractor.out.yaml @@ -290,6 +290,7 @@ xdsIR: protocol: GRPC weight: 1 hostname: '*' + isHTTP2: true jwt: providers: - audiences: @@ -339,6 +340,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false jwt: providers: - audiences: diff --git a/internal/gatewayapi/testdata/securitypolicy-with-jwt.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-jwt.out.yaml index c7e397cc54c7..9d808e2ae572 100644 --- a/internal/gatewayapi/testdata/securitypolicy-with-jwt.out.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-jwt.out.yaml @@ -282,6 +282,7 @@ xdsIR: protocol: GRPC weight: 1 hostname: '*' + isHTTP2: true jwt: providers: - audiences: @@ -331,6 +332,7 @@ xdsIR: protocol: HTTP weight: 1 hostname: gateway.envoyproxy.io + isHTTP2: false jwt: providers: - audiences: diff --git a/internal/gatewayapi/testdata/securitypolicy-with-oidc.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-oidc.out.yaml index c08304d3ebd6..a0953830c231 100644 --- a/internal/gatewayapi/testdata/securitypolicy-with-oidc.out.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-oidc.out.yaml @@ -228,11 +228,12 @@ xdsIR: protocol: HTTP weight: 1 hostname: www.example.com + isHTTP2: false name: httproute/default/httproute-1/rule/0/match/0/www_example_com oidc: clientID: client2.oauth.foo.com clientSecret: Y2xpZW50MTpzZWNyZXQK - cookieSuffix: 5F93C2E4 + cookieSuffix: 5f93c2e4 logoutPath: /foo/logout provider: authorizationEndpoint: https://oauth.foo.com/oauth2/v2/auth @@ -260,11 +261,12 @@ xdsIR: protocol: HTTP weight: 1 hostname: www.example.com + isHTTP2: false name: httproute/default/httproute-2/rule/0/match/0/www_example_com oidc: clientID: client1.apps.googleusercontent.com clientSecret: Y2xpZW50MTpzZWNyZXQK - cookieSuffix: B0A1B740 + cookieSuffix: b0a1b740 logoutPath: /bar/logout provider: authorizationEndpoint: https://accounts.google.com/o/oauth2/v2/auth diff --git a/internal/gatewayapi/validate.go b/internal/gatewayapi/validate.go index e694f1f9e7a6..e7ddb427a157 100644 --- a/internal/gatewayapi/validate.go +++ b/internal/gatewayapi/validate.go @@ -22,8 +22,13 @@ import ( egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" ) -func (t *Translator) validateBackendRef(backendRef *gwapiv1a2.BackendRef, parentRef *RouteParentContext, route RouteContext, +func (t *Translator) validateBackendRef(backendRefContext BackendRefContext, parentRef *RouteParentContext, route RouteContext, resources *Resources, backendNamespace string, routeKind gwapiv1.Kind) bool { + if !t.validateBackendRefFilters(backendRefContext, parentRef, route, routeKind) { + return false + } + backendRef := GetBackendRef(backendRefContext) + if !t.validateBackendRefGroup(backendRef, parentRef, route) { return false } @@ -80,6 +85,32 @@ func (t *Translator) validateBackendRefKind(backendRef *gwapiv1a2.BackendRef, pa return true } +func (t *Translator) validateBackendRefFilters(backendRef BackendRefContext, parentRef *RouteParentContext, route RouteContext, routeKind gwapiv1.Kind) bool { + var filtersLen int + switch routeKind { + case KindHTTPRoute: + filters := GetFilters(backendRef).([]gwapiv1.HTTPRouteFilter) + filtersLen = len(filters) + case KindGRPCRoute: + filters := GetFilters(backendRef).([]gwapiv1a2.GRPCRouteFilter) + filtersLen = len(filters) + default: + return true + } + + if filtersLen > 0 { + parentRef.SetCondition(route, + gwapiv1.RouteConditionResolvedRefs, + metav1.ConditionFalse, + "UnsupportedRefValue", + "The filters field within BackendRef is not supported", + ) + return false + } + + return true +} + func (t *Translator) validateBackendNamespace(backendRef *gwapiv1a2.BackendRef, parentRef *RouteParentContext, route RouteContext, resources *Resources, routeKind gwapiv1.Kind) bool { if backendRef.Namespace != nil && string(*backendRef.Namespace) != "" && string(*backendRef.Namespace) != route.GetNamespace() { @@ -207,8 +238,8 @@ func (t *Translator) validateListenerConditions(listener *ListenerContext) (isRe listener.SetCondition(gwapiv1.ListenerConditionResolvedRefs, metav1.ConditionTrue, gwapiv1.ListenerReasonResolvedRefs, "Listener references have been resolved") return true - } + // Any condition on the listener apart from Programmed=true indicates an error. if !(lConditions[0].Type == string(gwapiv1.ListenerConditionProgrammed) && lConditions[0].Status == metav1.ConditionTrue) { hasProgrammedCond := false diff --git a/internal/infrastructure/kubernetes/infra_resource.go b/internal/infrastructure/kubernetes/infra_resource.go index d0e21be628ef..e03f33ce788b 100644 --- a/internal/infrastructure/kubernetes/infra_resource.go +++ b/internal/infrastructure/kubernetes/infra_resource.go @@ -18,6 +18,7 @@ import ( "k8s.io/apimachinery/pkg/types" "github.com/envoyproxy/gateway/internal/infrastructure/kubernetes/resource" + "github.com/envoyproxy/gateway/internal/utils" ) // createOrUpdateServiceAccount creates a ServiceAccount in the kube api server based on the @@ -29,10 +30,7 @@ func (i *Infra) createOrUpdateServiceAccount(ctx context.Context, r ResourceRend } current := &corev1.ServiceAccount{} - key := types.NamespacedName{ - Namespace: sa.Namespace, - Name: sa.Name, - } + key := utils.NamespacedName(sa) return i.Client.CreateOrUpdate(ctx, key, current, sa, func() bool { // the service account never changed, does not need to update diff --git a/internal/infrastructure/kubernetes/proxy/resource.go b/internal/infrastructure/kubernetes/proxy/resource.go index 7bedbd9cb237..2dcda4eba242 100644 --- a/internal/infrastructure/kubernetes/proxy/resource.go +++ b/internal/infrastructure/kubernetes/proxy/resource.go @@ -7,16 +7,19 @@ package proxy import ( "fmt" + "strings" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/utils/ptr" egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" + "github.com/envoyproxy/gateway/internal/cmd/envoy" + "github.com/envoyproxy/gateway/internal/cmd/version" "github.com/envoyproxy/gateway/internal/envoygateway/config" "github.com/envoyproxy/gateway/internal/infrastructure/kubernetes/resource" "github.com/envoyproxy/gateway/internal/ir" - providerutils "github.com/envoyproxy/gateway/internal/provider/utils" + "github.com/envoyproxy/gateway/internal/utils" "github.com/envoyproxy/gateway/internal/xds/bootstrap" ) @@ -52,7 +55,7 @@ var ( // ExpectedResourceHashedName returns expected resource hashed name including up to the 48 characters of the original name. func ExpectedResourceHashedName(name string) string { - hashedName := providerutils.GetHashedName(name, 48) + hashedName := utils.GetHashedName(name, 48) return fmt.Sprintf("%s-%s", config.EnvoyPrefix, hashedName) } @@ -98,7 +101,8 @@ func enablePrometheus(infra *ir.ProxyInfra) bool { // expectedProxyContainers returns expected proxy containers. func expectedProxyContainers(infra *ir.ProxyInfra, - deploymentConfig *egv1a1.KubernetesDeploymentSpec) ([]corev1.Container, error) { + deploymentConfig *egv1a1.KubernetesDeploymentSpec, + shutdownConfig *egv1a1.ShutdownConfig) ([]corev1.Container, error) { // Define slice to hold container ports var ports []corev1.ContainerPort @@ -116,7 +120,7 @@ func expectedProxyContainers(infra *ir.ProxyInfra, } port := corev1.ContainerPort{ // hashed container port name including up to the 6 characters of the port name and the maximum of 15 characters. - Name: providerutils.GetHashedName(p.Name, 6), + Name: utils.GetHashedName(p.Name, 6), ContainerPort: p.ContainerPort, Protocol: protocol, } @@ -184,11 +188,11 @@ func expectedProxyContainers(infra *ir.ProxyInfra, ImagePullPolicy: corev1.PullIfNotPresent, Command: []string{"envoy"}, Args: args, - Env: expectedProxyContainerEnv(deploymentConfig), + Env: expectedContainerEnv(deploymentConfig.Container), Resources: *deploymentConfig.Container.Resources, SecurityContext: deploymentConfig.Container.SecurityContext, Ports: ports, - VolumeMounts: expectedContainerVolumeMounts(deploymentConfig), + VolumeMounts: expectedContainerVolumeMounts(deploymentConfig.Container), TerminationMessagePolicy: corev1.TerminationMessageReadFile, TerminationMessagePath: "/dev/termination-log", ReadinessProbe: &corev1.Probe{ @@ -204,14 +208,100 @@ func expectedProxyContainers(infra *ir.ProxyInfra, SuccessThreshold: 1, FailureThreshold: 3, }, + Lifecycle: &corev1.Lifecycle{ + PreStop: &corev1.LifecycleHandler{ + HTTPGet: &corev1.HTTPGetAction{ + Path: envoy.ShutdownManagerReadyPath, + Port: intstr.FromInt32(envoy.ShutdownManagerPort), + Scheme: corev1.URISchemeHTTP, + }, + }, + }, + }, + { + Name: "shutdown-manager", + Image: expectedShutdownManagerImage(), + ImagePullPolicy: corev1.PullIfNotPresent, + Command: []string{"envoy-gateway"}, + Args: expectedShutdownManagerArgs(shutdownConfig), + Env: expectedContainerEnv(nil), + Resources: *egv1a1.DefaultShutdownManagerContainerResourceRequirements(), + TerminationMessagePolicy: corev1.TerminationMessageReadFile, + TerminationMessagePath: "/dev/termination-log", + ReadinessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + HTTPGet: &corev1.HTTPGetAction{ + Path: envoy.ShutdownManagerHealthCheckPath, + Port: intstr.IntOrString{Type: intstr.Int, IntVal: envoy.ShutdownManagerPort}, + Scheme: corev1.URISchemeHTTP, + }, + }, + TimeoutSeconds: 1, + PeriodSeconds: 10, + SuccessThreshold: 1, + FailureThreshold: 3, + }, + LivenessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + HTTPGet: &corev1.HTTPGetAction{ + Path: envoy.ShutdownManagerHealthCheckPath, + Port: intstr.IntOrString{Type: intstr.Int, IntVal: envoy.ShutdownManagerPort}, + Scheme: corev1.URISchemeHTTP, + }, + }, + TimeoutSeconds: 1, + PeriodSeconds: 10, + SuccessThreshold: 1, + FailureThreshold: 3, + }, + Lifecycle: &corev1.Lifecycle{ + PreStop: &corev1.LifecycleHandler{ + Exec: &corev1.ExecAction{ + Command: expectedShutdownPreStopCommand(shutdownConfig), + }, + }, + }, }, } return containers, nil } +func expectedShutdownManagerImage() string { + if v := version.Get().ShutdownManagerVersion; v != "" { + return fmt.Sprintf("%s:%s", strings.Split(egv1a1.DefaultShutdownManagerImage, ":")[0], v) + } + return egv1a1.DefaultShutdownManagerImage +} + +func expectedShutdownManagerArgs(cfg *egv1a1.ShutdownConfig) []string { + args := []string{"envoy", "shutdown-manager"} + if cfg != nil && cfg.DrainTimeout != nil { + args = append(args, fmt.Sprintf("--ready-timeout=%.0fs", cfg.DrainTimeout.Seconds()+10)) + } + return args +} + +func expectedShutdownPreStopCommand(cfg *egv1a1.ShutdownConfig) []string { + command := []string{"envoy-gateway", "envoy", "shutdown"} + + if cfg == nil { + return command + } + + if cfg.DrainTimeout != nil { + command = append(command, fmt.Sprintf("--drain-timeout=%.0fs", cfg.DrainTimeout.Seconds())) + } + + if cfg.MinDrainDuration != nil { + command = append(command, fmt.Sprintf("--min-drain-duration=%.0fs", cfg.MinDrainDuration.Seconds())) + } + + return command +} + // expectedContainerVolumeMounts returns expected proxy container volume mounts. -func expectedContainerVolumeMounts(deploymentSpec *egv1a1.KubernetesDeploymentSpec) []corev1.VolumeMount { +func expectedContainerVolumeMounts(containerSpec *egv1a1.KubernetesContainerSpec) []corev1.VolumeMount { volumeMounts := []corev1.VolumeMount{ { Name: "certs", @@ -224,7 +314,7 @@ func expectedContainerVolumeMounts(deploymentSpec *egv1a1.KubernetesDeploymentSp }, } - return resource.ExpectedContainerVolumeMounts(deploymentSpec.Container, volumeMounts) + return resource.ExpectedContainerVolumeMounts(containerSpec, volumeMounts) } // expectedDeploymentVolumes returns expected proxy deployment volumes. @@ -266,8 +356,8 @@ func expectedDeploymentVolumes(name string, deploymentSpec *egv1a1.KubernetesDep return resource.ExpectedDeploymentVolumes(deploymentSpec.Pod, volumes) } -// expectedProxyContainerEnv returns expected proxy container envs. -func expectedProxyContainerEnv(deploymentConfig *egv1a1.KubernetesDeploymentSpec) []corev1.EnvVar { +// expectedContainerEnv returns expected proxy container envs. +func expectedContainerEnv(containerSpec *egv1a1.KubernetesContainerSpec) []corev1.EnvVar { env := []corev1.EnvVar{ { Name: envoyNsEnvVar, @@ -289,5 +379,9 @@ func expectedProxyContainerEnv(deploymentConfig *egv1a1.KubernetesDeploymentSpec }, } - return resource.ExpectedProxyContainerEnv(deploymentConfig.Container, env) + if containerSpec != nil { + return resource.ExpectedContainerEnv(containerSpec, env) + } else { + return env + } } diff --git a/internal/infrastructure/kubernetes/proxy/resource_provider.go b/internal/infrastructure/kubernetes/proxy/resource_provider.go index 7ed28fb75b8a..fd4107ea0deb 100644 --- a/internal/infrastructure/kubernetes/proxy/resource_provider.go +++ b/internal/infrastructure/kubernetes/proxy/resource_provider.go @@ -178,15 +178,17 @@ func (r *ResourceRender) ConfigMap() (*corev1.ConfigMap, error) { // Deployment returns the expected Deployment based on the provided infra. func (r *ResourceRender) Deployment() (*appsv1.Deployment, error) { + proxyConfig := r.infra.GetProxyConfig() + // Get the EnvoyProxy config to configure the deployment. - provider := r.infra.GetProxyConfig().GetEnvoyProxyProvider() + provider := proxyConfig.GetEnvoyProxyProvider() if provider.Type != egv1a1.ProviderTypeKubernetes { return nil, fmt.Errorf("invalid provider type %v for Kubernetes infra manager", provider.Type) } deploymentConfig := provider.GetEnvoyProxyKubeProvider().EnvoyDeployment // Get expected bootstrap configurations rendered ProxyContainers - containers, err := expectedProxyContainers(r.infra, deploymentConfig) + containers, err := expectedProxyContainers(r.infra, deploymentConfig, proxyConfig.Spec.Shutdown) if err != nil { return nil, err } @@ -241,7 +243,7 @@ func (r *ResourceRender) Deployment() (*appsv1.Deployment, error) { InitContainers: deploymentConfig.InitContainers, ServiceAccountName: ExpectedResourceHashedName(r.infra.Name), AutomountServiceAccountToken: ptr.To(false), - TerminationGracePeriodSeconds: ptr.To[int64](300), + TerminationGracePeriodSeconds: expectedTerminationGracePeriodSeconds(proxyConfig.Spec.Shutdown), DNSPolicy: corev1.DNSClusterFirst, RestartPolicy: corev1.RestartPolicyAlways, SchedulerName: "default-scheduler", @@ -265,9 +267,22 @@ func (r *ResourceRender) Deployment() (*appsv1.Deployment, error) { deployment.Spec.Replicas = nil } + // apply merge patch to deployment + if merged, err := deploymentConfig.ApplyMergePatch(deployment); err == nil { + deployment = merged + } + return deployment, nil } +func expectedTerminationGracePeriodSeconds(cfg *egv1a1.ShutdownConfig) *int64 { + s := 900 // default + if cfg != nil && cfg.DrainTimeout != nil { + s = int(cfg.DrainTimeout.Seconds() + 300) // 5 minutes longer than drain timeout + } + return ptr.To(int64(s)) +} + func (r *ResourceRender) HorizontalPodAutoscaler() (*autoscalingv2.HorizontalPodAutoscaler, error) { provider := r.infra.GetProxyConfig().GetEnvoyProxyProvider() if provider.Type != egv1a1.ProviderTypeKubernetes { diff --git a/internal/infrastructure/kubernetes/proxy/resource_provider_test.go b/internal/infrastructure/kubernetes/proxy/resource_provider_test.go index 8a41fba535c7..2e2280826874 100644 --- a/internal/infrastructure/kubernetes/proxy/resource_provider_test.go +++ b/internal/infrastructure/kubernetes/proxy/resource_provider_test.go @@ -10,12 +10,14 @@ import ( "os" "sort" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" appsv1 "k8s.io/api/apps/v1" autoscalingv2 "k8s.io/api/autoscaling/v2" corev1 "k8s.io/api/core/v1" + v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" @@ -86,6 +88,7 @@ func TestDeployment(t *testing.T) { caseName string infra *ir.Infra deploy *egv1a1.KubernetesDeploymentSpec + shutdown *egv1a1.ShutdownConfig proxyLogging map[egv1a1.ProxyLogComponent]egv1a1.LogLevel bootstrap string telemetry *egv1a1.ProxyTelemetry @@ -133,6 +136,58 @@ func TestDeployment(t *testing.T) { }, }, }, + { + caseName: "patch-deployment", + infra: newTestInfra(), + deploy: &egv1a1.KubernetesDeploymentSpec{ + Patch: &egv1a1.KubernetesPatchSpec{ + Type: ptr.To(egv1a1.StrategicMerge), + Value: v1.JSON{ + Raw: []byte("{\"spec\":{\"template\":{\"spec\":{\"hostNetwork\":true,\"dnsPolicy\":\"ClusterFirstWithHostNet\"}}}}"), + }, + }, + }, + }, + { + caseName: "shutdown-manager", + infra: newTestInfra(), + deploy: &egv1a1.KubernetesDeploymentSpec{ + Patch: &egv1a1.KubernetesPatchSpec{ + Type: ptr.To(egv1a1.StrategicMerge), + Value: v1.JSON{ + Raw: []byte(`{ + "spec":{ + "template":{ + "spec":{ + "containers":[{ + "name":"shutdown-manager", + "resources":{ + "requests":{"cpu":"100m","memory":"64Mi"}, + "limits":{"cpu":"200m","memory":"96Mi"} + }, + "securityContext":{"runAsUser":1234}, + "env":[ + {"name":"env_a","value":"env_a_value"}, + {"name":"env_b","value":"env_b_value"} + ], + "image":"envoyproxy/gateway-dev:v1.2.3" + }] + } + } + } + }`), + }, + }, + }, + shutdown: &egv1a1.ShutdownConfig{ + DrainTimeout: &metav1.Duration{ + Duration: 30 * time.Second, + }, + MinDrainDuration: &metav1.Duration{ + Duration: 15 * time.Second, + }, + }, + }, { caseName: "bootstrap", infra: newTestInfra(), @@ -474,6 +529,10 @@ func TestDeployment(t *testing.T) { tc.infra.Proxy.Config.Spec.Concurrency = tc.concurrency } + if tc.shutdown != nil { + tc.infra.Proxy.Config.Spec.Shutdown = tc.shutdown + } + if len(tc.extraArgs) > 0 { tc.infra.Proxy.Config.Spec.ExtraArgs = tc.extraArgs } diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml index be74dfcff766..e684044d8ca7 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml @@ -52,6 +52,12 @@ spec: fieldPath: metadata.name image: envoyproxy/envoy:distroless-dev imagePullPolicy: IfNotPresent + lifecycle: + preStop: + httpGet: + path: /shutdown/ready + port: 19002 + scheme: HTTP name: envoy ports: - containerPort: 8080 @@ -81,11 +87,61 @@ spec: readOnly: true - mountPath: /sds name: sds + - args: + - envoy + - shutdown-manager + command: + - envoy-gateway + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + image: envoyproxy/gateway-dev:latest + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - envoy-gateway + - envoy + - shutdown + name: shutdown-manager + resources: + requests: + cpu: 10m + memory: 32Mi + readinessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 300 + terminationGracePeriodSeconds: 900 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml index 93b5a6f2f2e4..f2640964efdb 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml @@ -53,6 +53,12 @@ spec: fieldPath: metadata.name image: envoyproxy/envoy:distroless-dev imagePullPolicy: IfNotPresent + lifecycle: + preStop: + httpGet: + path: /shutdown/ready + port: 19002 + scheme: HTTP name: envoy ports: - containerPort: 8080 @@ -82,11 +88,61 @@ spec: readOnly: true - mountPath: /sds name: sds + - args: + - envoy + - shutdown-manager + command: + - envoy-gateway + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + image: envoyproxy/gateway-dev:latest + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - envoy-gateway + - envoy + - shutdown + name: shutdown-manager + resources: + requests: + cpu: 10m + memory: 32Mi + readinessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 300 + terminationGracePeriodSeconds: 900 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml index 98428f0a37d9..ffc5a24f7ae5 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml @@ -158,6 +158,12 @@ spec: fieldPath: metadata.name image: envoyproxy/envoy:v1.2.3 imagePullPolicy: IfNotPresent + lifecycle: + preStop: + httpGet: + path: /shutdown/ready + port: 19002 + scheme: HTTP name: envoy ports: - containerPort: 8080 @@ -192,11 +198,61 @@ spec: readOnly: true - mountPath: /sds name: sds + - args: + - envoy + - shutdown-manager + command: + - envoy-gateway + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + image: envoyproxy/gateway-dev:latest + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - envoy-gateway + - envoy + - shutdown + name: shutdown-manager + resources: + requests: + cpu: 10m + memory: 32Mi + readinessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 300 + terminationGracePeriodSeconds: 900 securityContext: runAsUser: 1000 volumes: 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 2b141eca6717..ac68d8e5cece 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml @@ -157,6 +157,12 @@ spec: fieldPath: metadata.name image: envoyproxy/envoy:v1.2.3 imagePullPolicy: IfNotPresent + lifecycle: + preStop: + httpGet: + path: /shutdown/ready + port: 19002 + scheme: HTTP name: envoy ports: - containerPort: 8080 @@ -193,6 +199,56 @@ spec: name: sds - mountPath: /lib/filter_foo.so name: custom-libs + - args: + - envoy + - shutdown-manager + command: + - envoy-gateway + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + image: envoyproxy/gateway-dev:latest + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - envoy-gateway + - envoy + - shutdown + name: shutdown-manager + resources: + requests: + cpu: 10m + memory: 32Mi + readinessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File initContainers: - name: install-filter-foo image: alpine:3.11.3 @@ -210,7 +266,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 300 + terminationGracePeriodSeconds: 900 securityContext: runAsUser: 1000 volumes: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml index 08b6d4128838..c5f427b646dc 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml @@ -155,6 +155,12 @@ spec: fieldPath: metadata.name image: envoyproxy/envoy:v1.2.3 imagePullPolicy: IfNotPresent + lifecycle: + preStop: + httpGet: + path: /shutdown/ready + port: 19002 + scheme: HTTP name: envoy ports: - containerPort: 8080 @@ -189,11 +195,61 @@ spec: readOnly: true - mountPath: /sds name: sds + - args: + - envoy + - shutdown-manager + command: + - envoy-gateway + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + image: envoyproxy/gateway-dev:latest + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - envoy-gateway + - envoy + - shutdown + name: shutdown-manager + resources: + requests: + cpu: 10m + memory: 32Mi + readinessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 300 + terminationGracePeriodSeconds: 900 securityContext: runAsUser: 1000 volumes: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml index 8479979b5522..c96afd0aa57e 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml @@ -153,6 +153,12 @@ spec: fieldPath: metadata.name image: envoyproxy/envoy:distroless-dev imagePullPolicy: IfNotPresent + lifecycle: + preStop: + httpGet: + path: /shutdown/ready + port: 19002 + scheme: HTTP name: envoy ports: - containerPort: 8080 @@ -182,11 +188,61 @@ spec: readOnly: true - mountPath: /sds name: sds + - args: + - envoy + - shutdown-manager + command: + - envoy-gateway + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + image: envoyproxy/gateway-dev:latest + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - envoy-gateway + - envoy + - shutdown + name: shutdown-manager + resources: + requests: + cpu: 10m + memory: 32Mi + readinessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 300 + terminationGracePeriodSeconds: 900 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/enable-prometheus.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/enable-prometheus.yaml index 811717c40fe4..ef459a404015 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/enable-prometheus.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/enable-prometheus.yaml @@ -179,6 +179,12 @@ spec: fieldPath: metadata.name image: envoyproxy/envoy:distroless-dev imagePullPolicy: IfNotPresent + lifecycle: + preStop: + httpGet: + path: /shutdown/ready + port: 19002 + scheme: HTTP name: envoy ports: - containerPort: 8080 @@ -211,11 +217,61 @@ spec: readOnly: true - mountPath: /sds name: sds + - args: + - envoy + - shutdown-manager + command: + - envoy-gateway + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + image: envoyproxy/gateway-dev:latest + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - envoy-gateway + - envoy + - shutdown + name: shutdown-manager + resources: + requests: + cpu: 10m + memory: 32Mi + readinessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 300 + terminationGracePeriodSeconds: 900 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml index 553cb1733b71..0bace33bc2b8 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml @@ -159,6 +159,12 @@ spec: value: env_b_value image: envoyproxy/envoy:v1.2.3 imagePullPolicy: IfNotPresent + lifecycle: + preStop: + httpGet: + path: /shutdown/ready + port: 19002 + scheme: HTTP name: envoy ports: - containerPort: 8080 @@ -193,11 +199,61 @@ spec: readOnly: true - mountPath: /sds name: sds + - args: + - envoy + - shutdown-manager + command: + - envoy-gateway + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + image: envoyproxy/gateway-dev:latest + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - envoy-gateway + - envoy + - shutdown + name: shutdown-manager + resources: + requests: + cpu: 10m + memory: 32Mi + readinessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 300 + terminationGracePeriodSeconds: 900 securityContext: runAsUser: 1000 volumes: 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 6d5dce5112fd..4b0bcd0dfce2 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 @@ -165,6 +165,12 @@ spec: fieldPath: metadata.name image: envoyproxy/envoy:distroless-dev imagePullPolicy: IfNotPresent + lifecycle: + preStop: + httpGet: + path: /shutdown/ready + port: 19002 + scheme: HTTP name: envoy ports: - containerPort: 8080 @@ -194,11 +200,61 @@ spec: readOnly: true - mountPath: /sds name: sds + - args: + - envoy + - shutdown-manager + command: + - envoy-gateway + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + image: envoyproxy/gateway-dev:latest + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - envoy-gateway + - envoy + - shutdown + name: shutdown-manager + resources: + requests: + cpu: 10m + memory: 32Mi + readinessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 300 + terminationGracePeriodSeconds: 900 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml new file mode 100644 index 000000000000..3029ab1a4a27 --- /dev/null +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml @@ -0,0 +1,263 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/name: envoy + app.kubernetes.io/component: proxy + app.kubernetes.io/managed-by: envoy-gateway + gateway.envoyproxy.io/owning-gateway-name: default + gateway.envoyproxy.io/owning-gateway-namespace: default + name: envoy-default-37a8eec1 + namespace: envoy-gateway-system +spec: + replicas: 1 + strategy: + type: RollingUpdate + selector: + matchLabels: + app.kubernetes.io/name: envoy + app.kubernetes.io/component: proxy + app.kubernetes.io/managed-by: envoy-gateway + gateway.envoyproxy.io/owning-gateway-name: default + gateway.envoyproxy.io/owning-gateway-namespace: default + template: + metadata: + labels: + app.kubernetes.io/name: envoy + app.kubernetes.io/component: proxy + app.kubernetes.io/managed-by: envoy-gateway + gateway.envoyproxy.io/owning-gateway-name: default + gateway.envoyproxy.io/owning-gateway-namespace: default + spec: + automountServiceAccountToken: false + containers: + - args: + - --service-cluster default + - --service-node $(ENVOY_POD_NAME) + - | + --config-yaml admin: + access_log: + - name: envoy.access_loggers.file + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog + path: /dev/null + address: + socket_address: + address: 127.0.0.1 + port_value: 19000 + layered_runtime: + layers: + - name: global_config + static_layer: + envoy.restart_features.use_eds_cache_for_ads: true + re2.max_program_size.error_level: 4294967295 + re2.max_program_size.warn_level: 1000 + dynamic_resources: + ads_config: + api_type: DELTA_GRPC + transport_api_version: V3 + grpc_services: + - envoy_grpc: + cluster_name: xds_cluster + set_node_on_first_message_only: true + lds_config: + ads: {} + resource_api_version: V3 + cds_config: + ads: {} + resource_api_version: V3 + static_resources: + listeners: + - name: envoy-gateway-proxy-ready-0.0.0.0-19001 + address: + socket_address: + address: 0.0.0.0 + port_value: 19001 + protocol: TCP + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + stat_prefix: eg-ready-http + route_config: + name: local_route + http_filters: + - name: envoy.filters.http.health_check + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.health_check.v3.HealthCheck + pass_through_mode: false + headers: + - name: ":path" + string_match: + exact: /ready + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + clusters: + - connect_timeout: 10s + load_assignment: + cluster_name: xds_cluster + endpoints: + - load_balancing_weight: 1 + lb_endpoints: + - load_balancing_weight: 1 + endpoint: + address: + socket_address: + address: envoy-gateway + port_value: 18000 + typed_extension_protocol_options: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions" + explicit_http_config: + http2_protocol_options: + connection_keepalive: + interval: 30s + timeout: 5s + name: xds_cluster + type: STRICT_DNS + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + tls_params: + tls_maximum_protocol_version: TLSv1_3 + tls_certificate_sds_secret_configs: + - name: xds_certificate + sds_config: + path_config_source: + path: "/sds/xds-certificate.json" + resource_api_version: V3 + validation_context_sds_secret_config: + name: xds_trusted_ca + sds_config: + path_config_source: + path: "/sds/xds-trusted-ca.json" + resource_api_version: V3 + - --log-level warn + - --cpuset-threads + command: + - envoy + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + image: envoyproxy/envoy:distroless-dev + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + httpGet: + path: /shutdown/ready + port: 19002 + scheme: HTTP + name: envoy + ports: + - containerPort: 8080 + name: EnvoyH-d76a15e2 + protocol: TCP + - containerPort: 8443 + name: EnvoyH-6658f727 + protocol: TCP + resources: + requests: + cpu: 100m + memory: 512Mi + readinessProbe: + httpGet: + path: /ready + port: 19001 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /certs + name: certs + readOnly: true + - mountPath: /sds + name: sds + - args: + - envoy + - shutdown-manager + command: + - envoy-gateway + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + image: envoyproxy/gateway-dev:latest + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - envoy-gateway + - envoy + - shutdown + name: shutdown-manager + resources: + requests: + cpu: 10m + memory: 32Mi + readinessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + dnsPolicy: ClusterFirstWithHostNet + hostNetwork: true + restartPolicy: Always + schedulerName: default-scheduler + serviceAccountName: envoy-default-37a8eec1 + terminationGracePeriodSeconds: 900 + volumes: + - name: certs + secret: + secretName: envoy + defaultMode: 420 + - configMap: + defaultMode: 420 + items: + - key: xds-trusted-ca.json + path: xds-trusted-ca.json + - key: xds-certificate.json + path: xds-certificate.json + name: envoy-default-37a8eec1 + optional: false + name: sds + revisionHistoryLimit: 10 + progressDeadlineSeconds: 600 diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/shutdown-manager.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/shutdown-manager.yaml new file mode 100644 index 000000000000..c28ad823250f --- /dev/null +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/shutdown-manager.yaml @@ -0,0 +1,274 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/name: envoy + app.kubernetes.io/component: proxy + app.kubernetes.io/managed-by: envoy-gateway + gateway.envoyproxy.io/owning-gateway-name: default + gateway.envoyproxy.io/owning-gateway-namespace: default + name: envoy-default-37a8eec1 + namespace: envoy-gateway-system +spec: + replicas: 1 + strategy: + type: RollingUpdate + selector: + matchLabels: + app.kubernetes.io/name: envoy + app.kubernetes.io/component: proxy + app.kubernetes.io/managed-by: envoy-gateway + gateway.envoyproxy.io/owning-gateway-name: default + gateway.envoyproxy.io/owning-gateway-namespace: default + template: + metadata: + labels: + app.kubernetes.io/name: envoy + app.kubernetes.io/component: proxy + app.kubernetes.io/managed-by: envoy-gateway + gateway.envoyproxy.io/owning-gateway-name: default + gateway.envoyproxy.io/owning-gateway-namespace: default + spec: + automountServiceAccountToken: false + containers: + - args: + - --service-cluster default + - --service-node $(ENVOY_POD_NAME) + - | + --config-yaml admin: + access_log: + - name: envoy.access_loggers.file + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog + path: /dev/null + address: + socket_address: + address: 127.0.0.1 + port_value: 19000 + layered_runtime: + layers: + - name: global_config + static_layer: + envoy.restart_features.use_eds_cache_for_ads: true + re2.max_program_size.error_level: 4294967295 + re2.max_program_size.warn_level: 1000 + dynamic_resources: + ads_config: + api_type: DELTA_GRPC + transport_api_version: V3 + grpc_services: + - envoy_grpc: + cluster_name: xds_cluster + set_node_on_first_message_only: true + lds_config: + ads: {} + resource_api_version: V3 + cds_config: + ads: {} + resource_api_version: V3 + static_resources: + listeners: + - name: envoy-gateway-proxy-ready-0.0.0.0-19001 + address: + socket_address: + address: 0.0.0.0 + port_value: 19001 + protocol: TCP + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + stat_prefix: eg-ready-http + route_config: + name: local_route + http_filters: + - name: envoy.filters.http.health_check + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.health_check.v3.HealthCheck + pass_through_mode: false + headers: + - name: ":path" + string_match: + exact: /ready + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + clusters: + - connect_timeout: 10s + load_assignment: + cluster_name: xds_cluster + endpoints: + - load_balancing_weight: 1 + lb_endpoints: + - load_balancing_weight: 1 + endpoint: + address: + socket_address: + address: envoy-gateway + port_value: 18000 + typed_extension_protocol_options: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions" + explicit_http_config: + http2_protocol_options: + connection_keepalive: + interval: 30s + timeout: 5s + name: xds_cluster + type: STRICT_DNS + transport_socket: + name: envoy.transport_sockets.tls + typed_config: + "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext + common_tls_context: + tls_params: + tls_maximum_protocol_version: TLSv1_3 + tls_certificate_sds_secret_configs: + - name: xds_certificate + sds_config: + path_config_source: + path: "/sds/xds-certificate.json" + resource_api_version: V3 + validation_context_sds_secret_config: + name: xds_trusted_ca + sds_config: + path_config_source: + path: "/sds/xds-trusted-ca.json" + resource_api_version: V3 + - --log-level warn + - --cpuset-threads + command: + - envoy + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + image: envoyproxy/envoy:distroless-dev + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + httpGet: + path: /shutdown/ready + port: 19002 + scheme: HTTP + name: envoy + ports: + - containerPort: 8080 + name: EnvoyH-d76a15e2 + protocol: TCP + - containerPort: 8443 + name: EnvoyH-6658f727 + protocol: TCP + resources: + requests: + cpu: 100m + memory: 512Mi + readinessProbe: + httpGet: + path: /ready + port: 19001 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /certs + name: certs + readOnly: true + - mountPath: /sds + name: sds + - args: + - envoy + - shutdown-manager + - --ready-timeout=40s + command: + - envoy-gateway + env: + - name: env_a + value: env_a_value + - name: env_b + value: env_b_value + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + image: envoyproxy/gateway-dev:v1.2.3 + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - envoy-gateway + - envoy + - shutdown + - --drain-timeout=30s + - --min-drain-duration=15s + name: shutdown-manager + resources: + limits: + cpu: 200m + memory: 96Mi + requests: + cpu: 100m + memory: 64Mi + readinessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + securityContext: + runAsUser: 1234 + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + serviceAccountName: envoy-default-37a8eec1 + terminationGracePeriodSeconds: 330 + volumes: + - name: certs + secret: + secretName: envoy + defaultMode: 420 + - configMap: + defaultMode: 420 + items: + - key: xds-trusted-ca.json + path: xds-trusted-ca.json + - key: xds-certificate.json + path: xds-certificate.json + name: envoy-default-37a8eec1 + optional: false + name: sds + revisionHistoryLimit: 10 + progressDeadlineSeconds: 600 diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml index c285f7aab2e4..81437fea591c 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml @@ -159,6 +159,12 @@ spec: value: env_b_value image: envoyproxy/envoy:v1.2.3 imagePullPolicy: IfNotPresent + lifecycle: + preStop: + httpGet: + path: /shutdown/ready + port: 19002 + scheme: HTTP name: envoy ports: - containerPort: 8080 @@ -193,11 +199,61 @@ spec: readOnly: true - mountPath: /sds name: sds + - args: + - envoy + - shutdown-manager + command: + - envoy-gateway + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + image: envoyproxy/gateway-dev:latest + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - envoy-gateway + - envoy + - shutdown + name: shutdown-manager + resources: + requests: + cpu: 10m + memory: 32Mi + readinessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 300 + terminationGracePeriodSeconds: 900 securityContext: runAsUser: 1000 volumes: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml index 8975df8b435a..5e6fd0e18b65 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml @@ -159,6 +159,12 @@ spec: fieldPath: metadata.name image: envoyproxy/envoy:distroless-dev imagePullPolicy: IfNotPresent + lifecycle: + preStop: + httpGet: + path: /shutdown/ready + port: 19002 + scheme: HTTP name: envoy ports: - containerPort: 8080 @@ -188,11 +194,61 @@ spec: readOnly: true - mountPath: /sds name: sds + - args: + - envoy + - shutdown-manager + command: + - envoy-gateway + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + image: envoyproxy/gateway-dev:latest + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - envoy-gateway + - envoy + - shutdown + name: shutdown-manager + resources: + requests: + cpu: 10m + memory: 32Mi + readinessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 300 + terminationGracePeriodSeconds: 900 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml index 3c60a423cb15..fbace368c2b4 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml @@ -53,6 +53,12 @@ spec: fieldPath: metadata.name image: envoyproxy/envoy:distroless-dev imagePullPolicy: IfNotPresent + lifecycle: + preStop: + httpGet: + path: /shutdown/ready + port: 19002 + scheme: HTTP name: envoy ports: - containerPort: 8080 @@ -82,11 +88,61 @@ spec: readOnly: true - mountPath: /sds name: sds + - args: + - envoy + - shutdown-manager + command: + - envoy-gateway + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + image: envoyproxy/gateway-dev:latest + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - envoy-gateway + - envoy + - shutdown + name: shutdown-manager + resources: + requests: + cpu: 10m + memory: 32Mi + readinessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 300 + terminationGracePeriodSeconds: 900 volumes: - name: certs secret: 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 f850773cb4db..d039593fdf90 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml @@ -155,6 +155,12 @@ spec: fieldPath: metadata.name image: envoyproxy/envoy:distroless-dev imagePullPolicy: IfNotPresent + lifecycle: + preStop: + httpGet: + path: /shutdown/ready + port: 19002 + scheme: HTTP name: envoy ports: - containerPort: 8080 @@ -184,11 +190,61 @@ spec: readOnly: true - mountPath: /sds name: sds + - args: + - envoy + - shutdown-manager + command: + - envoy-gateway + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + image: envoyproxy/gateway-dev:latest + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - envoy-gateway + - envoy + - shutdown + name: shutdown-manager + resources: + requests: + cpu: 10m + memory: 32Mi + readinessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 300 + terminationGracePeriodSeconds: 900 volumes: - name: certs secret: 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 3e4886930996..15f475f4fc72 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 @@ -153,6 +153,12 @@ spec: fieldPath: metadata.name image: envoyproxy/envoy:distroless-dev imagePullPolicy: IfNotPresent + lifecycle: + preStop: + httpGet: + path: /shutdown/ready + port: 19002 + scheme: HTTP name: envoy ports: - containerPort: 8080 @@ -182,11 +188,61 @@ spec: readOnly: true - mountPath: /sds name: sds + - args: + - envoy + - shutdown-manager + command: + - envoy-gateway + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + image: envoyproxy/gateway-dev:latest + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - envoy-gateway + - envoy + - shutdown + name: shutdown-manager + resources: + requests: + cpu: 10m + memory: 32Mi + readinessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 300 + terminationGracePeriodSeconds: 900 imagePullSecrets: - name: aaa - name: bbb 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 c8fde97892f2..c80231848bbd 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml @@ -153,6 +153,12 @@ spec: fieldPath: metadata.name image: envoyproxy/envoy:distroless-dev imagePullPolicy: IfNotPresent + lifecycle: + preStop: + httpGet: + path: /shutdown/ready + port: 19002 + scheme: HTTP name: envoy ports: - containerPort: 8080 @@ -182,6 +188,56 @@ spec: readOnly: true - mountPath: /sds name: sds + - args: + - envoy + - shutdown-manager + command: + - envoy-gateway + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + image: envoyproxy/gateway-dev:latest + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - envoy-gateway + - envoy + - shutdown + name: shutdown-manager + resources: + requests: + cpu: 10m + memory: 32Mi + readinessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File dnsPolicy: ClusterFirst nodeSelector: key1: value1 @@ -189,7 +245,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 300 + terminationGracePeriodSeconds: 900 volumes: - name: certs secret: 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 7233f15ebd58..f3bb3826542e 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 @@ -153,6 +153,12 @@ spec: fieldPath: metadata.name image: envoyproxy/envoy:distroless-dev imagePullPolicy: IfNotPresent + lifecycle: + preStop: + httpGet: + path: /shutdown/ready + port: 19002 + scheme: HTTP name: envoy ports: - containerPort: 8080 @@ -182,11 +188,61 @@ spec: readOnly: true - mountPath: /sds name: sds + - args: + - envoy + - shutdown-manager + command: + - envoy-gateway + env: + - name: ENVOY_GATEWAY_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: ENVOY_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + image: envoyproxy/gateway-dev:latest + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - envoy-gateway + - envoy + - shutdown + name: shutdown-manager + resources: + requests: + cpu: 10m + memory: 32Mi + readinessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /healthz + port: 19002 + scheme: HTTP + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 300 + terminationGracePeriodSeconds: 900 topologySpreadConstraints: - maxSkew: 1 topologyKey: kubernetes.io/hostname diff --git a/internal/infrastructure/kubernetes/ratelimit/resource.go b/internal/infrastructure/kubernetes/ratelimit/resource.go index 95631e41ab8d..b0d44694e2c3 100644 --- a/internal/infrastructure/kubernetes/ratelimit/resource.go +++ b/internal/infrastructure/kubernetes/ratelimit/resource.go @@ -10,6 +10,7 @@ import ( "fmt" "net" "strconv" + "strings" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/intstr" @@ -98,6 +99,20 @@ func GetServiceURL(namespace string, dnsDomain string) string { return fmt.Sprintf("grpc://%s.%s.svc.%s:%d", InfraName, namespace, dnsDomain, InfraGRPCPort) } +// LabelSelector returns the string slice form labels used for all envoy rate limit resources. +func LabelSelector() []string { + + rlLabelMap := rateLimitLabels() + retLabels := make([]string, 0, len(rlLabelMap)) + + for labelK, labelV := range rlLabelMap { + ls := strings.Join([]string{labelK, labelV}, "=") + retLabels = append(retLabels, ls) + } + + return retLabels +} + // rateLimitLabels returns the labels used for all envoy rate limit resources. func rateLimitLabels() map[string]string { return map[string]string{ @@ -307,7 +322,7 @@ func expectedRateLimitContainerEnv(rateLimit *egv1a1.RateLimit, rateLimitDeploym } } - return resource.ExpectedProxyContainerEnv(rateLimitDeployment.Container, env) + return resource.ExpectedContainerEnv(rateLimitDeployment.Container, env) } // Validate the ratelimit tls secret validating. diff --git a/internal/infrastructure/kubernetes/ratelimit/resource_provider.go b/internal/infrastructure/kubernetes/ratelimit/resource_provider.go index 6549a4304129..5e4a2a2639bd 100644 --- a/internal/infrastructure/kubernetes/ratelimit/resource_provider.go +++ b/internal/infrastructure/kubernetes/ratelimit/resource_provider.go @@ -205,6 +205,11 @@ func (r *ResourceRender) Deployment() (*appsv1.Deployment, error) { } } + // apply merge patch to deployment + if merged, err := r.rateLimitDeployment.ApplyMergePatch(deployment); err == nil { + deployment = merged + } + return deployment, nil } diff --git a/internal/infrastructure/kubernetes/ratelimit/resource_provider_test.go b/internal/infrastructure/kubernetes/ratelimit/resource_provider_test.go index b6dc4f71c516..2b8d774d14c2 100644 --- a/internal/infrastructure/kubernetes/ratelimit/resource_provider_test.go +++ b/internal/infrastructure/kubernetes/ratelimit/resource_provider_test.go @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/require" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -36,6 +37,32 @@ var ownerReferenceUID = map[string]types.UID{ ResourceKindServiceAccount: "test-owner-reference-uid-for-service-account", } +func TestRateLimitLabelSelector(t *testing.T) { + + cases := []struct { + name string + expected []string + }{ + { + name: "rateLimit-labelSelector", + expected: []string{ + "app.kubernetes.io/name=envoy-ratelimit", + "app.kubernetes.io/component=ratelimit", + "app.kubernetes.io/managed-by=envoy-gateway", + }, + }, + } + + for _, tc := range cases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + got := LabelSelector() + require.ElementsMatch(t, tc.expected, got) + }) + } + +} + func TestRateLimitLabels(t *testing.T) { cases := []struct { name string @@ -146,6 +173,18 @@ func TestDeployment(t *testing.T) { rateLimit: rateLimit, deploy: cfg.EnvoyGateway.GetEnvoyGatewayProvider().GetEnvoyGatewayKubeProvider().RateLimitDeployment, }, + { + caseName: "patch-deployment", + rateLimit: rateLimit, + deploy: &egv1a1.KubernetesDeploymentSpec{ + Patch: &egv1a1.KubernetesPatchSpec{ + Type: ptr.To(egv1a1.StrategicMerge), + Value: v1.JSON{ + Raw: []byte("{\"spec\":{\"template\":{\"spec\":{\"hostNetwork\":true,\"dnsPolicy\":\"ClusterFirstWithHostNet\"}}}}"), + }, + }, + }, + }, { caseName: "custom", rateLimit: rateLimit, diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/patch-deployment.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/patch-deployment.yaml new file mode 100644 index 000000000000..c9e915ef9b0f --- /dev/null +++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/patch-deployment.yaml @@ -0,0 +1,114 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/name: envoy-ratelimit + app.kubernetes.io/component: ratelimit + app.kubernetes.io/managed-by: envoy-gateway + name: envoy-ratelimit + namespace: envoy-gateway-system + ownerReferences: + - apiVersion: apps/v1 + kind: Deployment + name: envoy-gateway + uid: test-owner-reference-uid-for-deployment +spec: + replicas: 1 + strategy: + type: RollingUpdate + selector: + matchLabels: + app.kubernetes.io/name: envoy-ratelimit + app.kubernetes.io/component: ratelimit + app.kubernetes.io/managed-by: envoy-gateway + template: + metadata: + labels: + app.kubernetes.io/name: envoy-ratelimit + app.kubernetes.io/component: ratelimit + app.kubernetes.io/managed-by: envoy-gateway + spec: + automountServiceAccountToken: false + containers: + - command: + - /bin/ratelimit + env: + - name: REDIS_SOCKET_TYPE + value: tcp + - name: REDIS_URL + value: redis.redis.svc:6379 + - name: RUNTIME_ROOT + value: /data + - name: RUNTIME_SUBDIRECTORY + value: ratelimit + - name: RUNTIME_IGNOREDOTFILES + value: "true" + - name: RUNTIME_WATCH_ROOT + value: "false" + - name: LOG_LEVEL + value: info + - name: USE_STATSD + value: "false" + - name: CONFIG_TYPE + value: GRPC_XDS_SOTW + - name: CONFIG_GRPC_XDS_SERVER_URL + value: envoy-gateway:18001 + - name: CONFIG_GRPC_XDS_NODE_ID + value: envoy-ratelimit + - name: GRPC_SERVER_USE_TLS + value: "true" + - name: GRPC_SERVER_TLS_CERT + value: "/certs/tls.crt" + - name: GRPC_SERVER_TLS_KEY + value: "/certs/tls.key" + - name: GRPC_SERVER_TLS_CA_CERT + value: "/certs/ca.crt" + - name: CONFIG_GRPC_XDS_SERVER_USE_TLS + value: "true" + - name: CONFIG_GRPC_XDS_CLIENT_TLS_CERT + value: "/certs/tls.crt" + - name: CONFIG_GRPC_XDS_CLIENT_TLS_KEY + value: "/certs/tls.key" + - name: CONFIG_GRPC_XDS_SERVER_TLS_CACERT + value: "/certs/ca.crt" + - name: FORCE_START_WITHOUT_INITIAL_CONFIG + value: "true" + image: envoyproxy/ratelimit:master + imagePullPolicy: IfNotPresent + name: envoy-ratelimit + ports: + - containerPort: 8081 + name: grpc + protocol: TCP + resources: + requests: + cpu: 100m + memory: 512Mi + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /certs + name: certs + readOnly: true + readinessProbe: + failureThreshold: 3 + httpGet: + path: /healthcheck + port: 8080 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + dnsPolicy: ClusterFirstWithHostNet + hostNetwork: true + restartPolicy: Always + schedulerName: default-scheduler + serviceAccountName: envoy-ratelimit + terminationGracePeriodSeconds: 300 + volumes: + - name: certs + secret: + secretName: envoy-rate-limit + defaultMode: 420 + revisionHistoryLimit: 10 + progressDeadlineSeconds: 600 diff --git a/internal/infrastructure/kubernetes/resource/resource.go b/internal/infrastructure/kubernetes/resource/resource.go index 0a98e155e065..a729b7aa100c 100644 --- a/internal/infrastructure/kubernetes/resource/resource.go +++ b/internal/infrastructure/kubernetes/resource/resource.go @@ -53,8 +53,8 @@ func CompareSvc(currentSvc, originalSvc *corev1.Service) bool { cmpopts.IgnoreFields(corev1.ServiceSpec{}, "ClusterIP", "ClusterIPs")) } -// ExpectedProxyContainerEnv returns expected container envs. -func ExpectedProxyContainerEnv(container *egv1a1.KubernetesContainerSpec, env []corev1.EnvVar) []corev1.EnvVar { +// ExpectedContainerEnv returns expected container envs. +func ExpectedContainerEnv(container *egv1a1.KubernetesContainerSpec, env []corev1.EnvVar) []corev1.EnvVar { amendFunc := func(envVar corev1.EnvVar) { for index, e := range env { if e.Name == envVar.Name { diff --git a/internal/infrastructure/kubernetes/resource/resource_test.go b/internal/infrastructure/kubernetes/resource/resource_test.go index 61bd0fb2444c..de115c3c1f3a 100644 --- a/internal/infrastructure/kubernetes/resource/resource_test.go +++ b/internal/infrastructure/kubernetes/resource/resource_test.go @@ -361,7 +361,7 @@ func TestExpectedProxyContainerEnv(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - assert.Equalf(t, tt.want, ExpectedProxyContainerEnv(tt.args.container, tt.args.env), "ExpectedProxyContainerEnv(%v, %v)", tt.args.container, tt.args.env) + assert.Equalf(t, tt.want, ExpectedContainerEnv(tt.args.container, tt.args.env), "ExpectedProxyContainerEnv(%v, %v)", tt.args.container, tt.args.env) }) } } diff --git a/internal/ir/xds.go b/internal/ir/xds.go index b6894482cac2..d501fffac8f5 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -413,6 +413,8 @@ type HTTPRoute struct { Name string `json:"name" yaml:"name"` // Hostname that the route matches against Hostname string `json:"hostname" yaml:"hostname,omitempty"` + // IsHTTP2 is set if the route is configured to serve HTTP2 traffic + IsHTTP2 bool `json:"isHTTP2" yaml:"isHTTP2"` // PathMatch defines the match conditions on the path. PathMatch *StringMatch `json:"pathMatch,omitempty" yaml:"pathMatch,omitempty"` // HeaderMatches define the match conditions on the request headers for this route. diff --git a/internal/kubernetes/port-forwarder.go b/internal/kubernetes/port-forwarder.go index a58e88ea5cd0..ceb439d7721b 100644 --- a/internal/kubernetes/port-forwarder.go +++ b/internal/kubernetes/port-forwarder.go @@ -24,6 +24,8 @@ type PortForwarder interface { Stop() + WaitForStop() + // Address returns the address of the local forwarded address. Address() string } @@ -128,6 +130,10 @@ func (f *localForwarder) Stop() { close(f.stopCh) } +func (f *localForwarder) WaitForStop() { + <-f.stopCh +} + func (f *localForwarder) Address() string { return fmt.Sprintf("%s:%d", netutil.DefaultLocalAddress, f.localPort) } diff --git a/internal/logging/log.go b/internal/logging/log.go index 0f92491bca6c..0d6d36f8f95d 100644 --- a/internal/logging/log.go +++ b/internal/logging/log.go @@ -6,6 +6,7 @@ package logging import ( + "io" "os" "github.com/go-logr/logr" @@ -23,7 +24,7 @@ type Logger struct { } func NewLogger(logging *v1alpha1.EnvoyGatewayLogging) Logger { - logger := initZapLogger(logging, logging.Level[v1alpha1.LogComponentGatewayDefault]) + logger := initZapLogger(os.Stdout, logging, logging.Level[v1alpha1.LogComponentGatewayDefault]) return Logger{ Logger: zapr.NewLogger(logger), @@ -32,9 +33,25 @@ func NewLogger(logging *v1alpha1.EnvoyGatewayLogging) Logger { } } +func FileLogger(file string, name string, level v1alpha1.LogLevel) Logger { + writer, err := os.OpenFile(file, os.O_WRONLY, 0666) + if err != nil { + panic(err) + } + + logging := v1alpha1.DefaultEnvoyGatewayLogging() + logger := initZapLogger(writer, logging, level) + + return Logger{ + Logger: zapr.NewLogger(logger).WithName(name), + logging: logging, + sugaredLogger: logger.Sugar(), + } +} + func DefaultLogger(level v1alpha1.LogLevel) Logger { logging := v1alpha1.DefaultEnvoyGatewayLogging() - logger := initZapLogger(logging, level) + logger := initZapLogger(os.Stdout, logging, level) return Logger{ Logger: zapr.NewLogger(logger), @@ -50,7 +67,7 @@ func DefaultLogger(level v1alpha1.LogLevel) Logger { // more information). func (l Logger) WithName(name string) Logger { logLevel := l.logging.Level[v1alpha1.EnvoyGatewayLogComponent(name)] - logger := initZapLogger(l.logging, logLevel) + logger := initZapLogger(os.Stdout, l.logging, logLevel) return Logger{ Logger: zapr.NewLogger(logger).WithName(name), @@ -88,9 +105,9 @@ func (l Logger) Sugar() *zap.SugaredLogger { return l.sugaredLogger } -func initZapLogger(logging *v1alpha1.EnvoyGatewayLogging, level v1alpha1.LogLevel) *zap.Logger { +func initZapLogger(w io.Writer, logging *v1alpha1.EnvoyGatewayLogging, level v1alpha1.LogLevel) *zap.Logger { parseLevel, _ := zapcore.ParseLevel(string(logging.DefaultEnvoyGatewayLoggingLevel(level))) - core := zapcore.NewCore(zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig()), zapcore.AddSync(os.Stdout), zap.NewAtomicLevelAt(parseLevel)) + core := zapcore.NewCore(zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig()), zapcore.AddSync(w), zap.NewAtomicLevelAt(parseLevel)) return zap.New(core, zap.AddCaller()) } diff --git a/internal/logging/log_test.go b/internal/logging/log_test.go index 788d47cc3aca..756e4e393187 100644 --- a/internal/logging/log_test.go +++ b/internal/logging/log_test.go @@ -41,6 +41,10 @@ func TestLogger(t *testing.T) { defaultLogger := DefaultLogger(v1alpha1.LogLevelInfo) assert.NotNil(t, defaultLogger.logging) assert.NotNil(t, defaultLogger.sugaredLogger) + + fileLogger := FileLogger("/dev/stderr", "fl-test", v1alpha1.LogLevelInfo) + assert.NotNil(t, fileLogger.logging) + assert.NotNil(t, fileLogger.sugaredLogger) } func TestLoggerWithName(t *testing.T) { diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go index af42d4c178b2..b7d305caa83e 100644 --- a/internal/provider/kubernetes/controller.go +++ b/internal/provider/kubernetes/controller.go @@ -37,8 +37,8 @@ import ( "github.com/envoyproxy/gateway/internal/gatewayapi" "github.com/envoyproxy/gateway/internal/logging" "github.com/envoyproxy/gateway/internal/message" - "github.com/envoyproxy/gateway/internal/provider/utils" "github.com/envoyproxy/gateway/internal/status" + "github.com/envoyproxy/gateway/internal/utils" "github.com/envoyproxy/gateway/internal/utils/slice" ) diff --git a/internal/provider/kubernetes/kubernetes_test.go b/internal/provider/kubernetes/kubernetes_test.go index 2c470f12d024..fc4cc7a39a01 100644 --- a/internal/provider/kubernetes/kubernetes_test.go +++ b/internal/provider/kubernetes/kubernetes_test.go @@ -37,6 +37,7 @@ import ( "github.com/envoyproxy/gateway/internal/gatewayapi" "github.com/envoyproxy/gateway/internal/message" "github.com/envoyproxy/gateway/internal/provider/kubernetes/test" + "github.com/envoyproxy/gateway/internal/utils" ) const ( @@ -101,7 +102,7 @@ func startEnv() (*envtest.Environment, *rest.Config, error) { func testGatewayClassController(ctx context.Context, t *testing.T, provider *Provider, _ *message.ProviderResources) { cli := provider.manager.GetClient() - gc := test.GetGatewayClass("test-gc-controllername", egv1a1.GatewayControllerName) + gc := test.GetGatewayClass("test-gc-controllername", egv1a1.GatewayControllerName, nil) require.NoError(t, cli.Create(ctx, gc)) defer func() { @@ -117,7 +118,7 @@ func testGatewayClassController(ctx context.Context, t *testing.T, provider *Pro func testGatewayClassAcceptedStatus(ctx context.Context, t *testing.T, provider *Provider, resources *message.ProviderResources) { cli := provider.manager.GetClient() - gc := test.GetGatewayClass("test-gc-accepted-status", egv1a1.GatewayControllerName) + gc := test.GetGatewayClass("test-gc-accepted-status", egv1a1.GatewayControllerName, nil) require.NoError(t, cli.Create(ctx, gc)) defer func() { @@ -138,14 +139,14 @@ func testGatewayClassAcceptedStatus(ctx context.Context, t *testing.T, provider return false }, defaultWait, defaultTick) + require.Eventually(t, func() bool { + return resources.GatewayAPIResources.Len() != 0 + }, defaultWait, defaultTick) + // Even though no gateways exist, the controller loads the empty resource map // to support gateway deletions. require.Eventually(t, func() bool { - gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) - if !ok { - return false - } - _, ok = (*gatewayClassResources)[gc.Name] + _, ok := waitUntilGatewayClassResourcesAreReady(resources, gc.Name) return ok }, defaultWait, defaultTick) } @@ -164,14 +165,14 @@ func testGatewayClassWithParamRef(ctx context.Context, t *testing.T, provider *P }() epName := "test-envoy-proxy" - ep := test.NewEnvoyProxy(testNs, epName) + ep := test.GetEnvoyProxy(types.NamespacedName{Namespace: testNs, Name: epName}, false) require.NoError(t, cli.Create(ctx, ep)) defer func() { require.NoError(t, cli.Delete(ctx, ep)) }() - gc := test.GetGatewayClass("gc-with-param-ref", egv1a1.GatewayControllerName) + gc := test.GetGatewayClass("gc-with-param-ref", egv1a1.GatewayControllerName, nil) gc.Spec.ParametersRef = &gwapiv1.ParametersReference{ Group: gwapiv1.Group(egv1a1.GroupVersion.Group), Kind: egv1a1.KindEnvoyProxy, @@ -200,11 +201,11 @@ func testGatewayClassWithParamRef(ctx context.Context, t *testing.T, provider *P }, defaultWait, defaultTick) require.Eventually(t, func() bool { - gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) - if !ok { - return false - } - res, ok := (*gatewayClassResources)[gc.Name] + return resources.GatewayAPIResources.Len() != 0 + }, defaultWait, defaultTick) + + require.Eventually(t, func() bool { + res, ok := waitUntilGatewayClassResourcesAreReady(resources, gc.Name) if !ok { return false } @@ -221,7 +222,7 @@ func testGatewayClassWithParamRef(ctx context.Context, t *testing.T, provider *P func testGatewayScheduledStatus(ctx context.Context, t *testing.T, provider *Provider, resources *message.ProviderResources) { cli := provider.manager.GetClient() - gc := test.GetGatewayClass("gc-scheduled-status-test", egv1a1.GatewayControllerName) + gc := test.GetGatewayClass("gc-scheduled-status-test", egv1a1.GatewayControllerName, nil) require.NoError(t, cli.Create(ctx, gc)) // Ensure the GatewayClass reports "Ready". @@ -321,7 +322,7 @@ func testGatewayScheduledStatus(ctx context.Context, t *testing.T, provider *Pro // Ensure the Gateway reports "Scheduled". require.Eventually(t, func() bool { - if err := cli.Get(ctx, types.NamespacedName{Namespace: gw.Namespace, Name: gw.Name}, gw); err != nil { + if err := cli.Get(ctx, utils.NamespacedName(gw), gw); err != nil { return false } @@ -340,10 +341,16 @@ func testGatewayScheduledStatus(ctx context.Context, t *testing.T, provider *Pro require.NoError(t, cli.Delete(ctx, gw)) }() + require.Eventually(t, func() bool { + return resources.GatewayAPIResources.Len() != 0 + }, defaultWait, defaultTick) + // Ensure the number of Gateways in the Gateway resource table is as expected. require.Eventually(t, func() bool { - gatewayClassResources, _ := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) - res := (*gatewayClassResources)[gc.Name] + res, ok := waitUntilGatewayClassResourcesAreReady(resources, gc.Name) + if !ok { + return false + } return res != nil && len(res.Gateways) == 1 }, defaultWait, defaultTick) @@ -354,15 +361,14 @@ func testGatewayScheduledStatus(ctx context.Context, t *testing.T, provider *Pro }, defaultWait, defaultTick) // Ensure the test Gateway in the Gateway resources is as expected. - key := types.NamespacedName{ - Namespace: gw.Namespace, - Name: gw.Name, - } + key := utils.NamespacedName(gw) require.Eventually(t, func() bool { return cli.Get(ctx, key, gw) == nil }, defaultWait, defaultTick) gatewayClassResources, _ := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + assert.NotNil(t, gatewayClassResources) + res := (*gatewayClassResources)[gc.Name] // Only check if the spec is equal // The watchable map will not store a resource @@ -375,7 +381,7 @@ func testGatewayScheduledStatus(ctx context.Context, t *testing.T, provider *Pro func testHTTPRoute(ctx context.Context, t *testing.T, provider *Provider, resources *message.ProviderResources) { cli := provider.manager.GetClient() - gc := test.GetGatewayClass("httproute-test", egv1a1.GatewayControllerName) + gc := test.GetGatewayClass("httproute-test", egv1a1.GatewayControllerName, nil) require.NoError(t, cli.Create(ctx, gc)) // Ensure the GatewayClass reports ready. @@ -884,27 +890,28 @@ func testHTTPRoute(ctx context.Context, t *testing.T, provider *Provider, resour }, defaultWait, defaultTick) // Ensure the test HTTPRoute in the HTTPRoute resources is as expected. - key := types.NamespacedName{ - Namespace: testCase.route.Namespace, - Name: testCase.route.Name, - } + key := utils.NamespacedName(&testCase.route) require.Eventually(t, func() bool { return cli.Get(ctx, key, &testCase.route) == nil }, defaultWait, defaultTick) require.Eventually(t, func() bool { - gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) - res := (*gatewayClassResources)[gc.Name] + res, ok := waitUntilGatewayClassResourcesAreReady(resources, gc.Name) + if !ok { + return false + } return ok && len(res.HTTPRoutes) != 0 }, defaultWait, defaultTick) + gatewayClassResources, _ := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + assert.NotNil(t, gatewayClassResources) + res := (*gatewayClassResources)[gc.Name] assert.Equal(t, &testCase.route, res.HTTPRoutes[0]) // Ensure the HTTPRoute Namespace is in the Namespace resource map. require.Eventually(t, func() bool { - gatewayClassResources, _ := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) - res, ok := (*gatewayClassResources)[testCase.route.Namespace] + res, ok := waitUntilGatewayClassResourcesAreReady(resources, gc.Name) if !ok { return false } @@ -923,8 +930,7 @@ func testHTTPRoute(ctx context.Context, t *testing.T, provider *Provider, resour return true } - gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) - res, ok := (*gatewayClassResources)[gc.Name] + res, ok := waitUntilGatewayClassResourcesAreReady(resources, gc.Name) if !ok { return false } @@ -942,7 +948,7 @@ func testHTTPRoute(ctx context.Context, t *testing.T, provider *Provider, resour func testTLSRoute(ctx context.Context, t *testing.T, provider *Provider, resources *message.ProviderResources) { cli := provider.manager.GetClient() - gc := test.GetGatewayClass("tlsroute-test", egv1a1.GatewayControllerName) + gc := test.GetGatewayClass("tlsroute-test", egv1a1.GatewayControllerName, nil) require.NoError(t, cli.Create(ctx, gc)) defer func() { @@ -1035,30 +1041,28 @@ func testTLSRoute(ctx context.Context, t *testing.T, provider *Provider, resourc }, defaultWait, defaultTick) // Ensure the test TLSRoute in the TLSRoute resources is as expected. - key := types.NamespacedName{ - Namespace: testCase.route.Namespace, - Name: testCase.route.Name, - } + key := utils.NamespacedName(&testCase.route) require.Eventually(t, func() bool { return cli.Get(ctx, key, &testCase.route) == nil }, defaultWait, defaultTick) require.Eventually(t, func() bool { - gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) - res, ok := (*gatewayClassResources)[gc.Name] + res, ok := waitUntilGatewayClassResourcesAreReady(resources, gc.Name) if !ok { return false } return ok && len(res.TLSRoutes) != 0 }, defaultWait, defaultTick) + gatewayClassResources, _ := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + assert.NotNil(t, gatewayClassResources) + res, _ := (*gatewayClassResources)[gc.Name] assert.Equal(t, &testCase.route, res.TLSRoutes[0]) // Ensure the HTTPRoute Namespace is in the Namespace resource map. require.Eventually(t, func() bool { - gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) - res, ok := (*gatewayClassResources)[gc.Name] + res, ok := waitUntilGatewayClassResourcesAreReady(resources, gc.Name) if !ok { return false } @@ -1072,8 +1076,7 @@ func testTLSRoute(ctx context.Context, t *testing.T, provider *Provider, resourc // Ensure the Service is in the resource map. require.Eventually(t, func() bool { - gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) - res, ok := (*gatewayClassResources)[gc.Name] + res, ok := waitUntilGatewayClassResourcesAreReady(resources, gc.Name) if !ok { return false } @@ -1094,7 +1097,7 @@ func testTLSRoute(ctx context.Context, t *testing.T, provider *Provider, resourc func testServiceCleanupForMultipleRoutes(ctx context.Context, t *testing.T, provider *Provider, resources *message.ProviderResources) { cli := provider.manager.GetClient() - gc := test.GetGatewayClass("service-cleanup-test", egv1a1.GatewayControllerName) + gc := test.GetGatewayClass("service-cleanup-test", egv1a1.GatewayControllerName, nil) require.NoError(t, cli.Create(ctx, gc)) defer func() { require.NoError(t, cli.Delete(ctx, gc)) @@ -1200,10 +1203,13 @@ func testServiceCleanupForMultipleRoutes(ctx context.Context, t *testing.T, prov require.NoError(t, cli.Create(ctx, &tlsRoute)) require.NoError(t, cli.Create(ctx, &httpRoute)) + require.Eventually(t, func() bool { + return resources.GatewayAPIResources.Len() != 0 + }, defaultWait, defaultTick) + // Check that the Service is present in the resource map require.Eventually(t, func() bool { - gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) - res, ok := (*gatewayClassResources)[gc.Name] + res, ok := waitUntilGatewayClassResourcesAreReady(resources, gc.Name) if !ok { return false } @@ -1218,8 +1224,7 @@ func testServiceCleanupForMultipleRoutes(ctx context.Context, t *testing.T, prov // Delete the TLSRoute, and check if the Service is still present require.NoError(t, cli.Delete(ctx, &tlsRoute)) require.Eventually(t, func() bool { - gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) - res, ok := (*gatewayClassResources)[gc.Name] + res, ok := waitUntilGatewayClassResourcesAreReady(resources, gc.Name) if !ok { return false } @@ -1234,8 +1239,7 @@ func testServiceCleanupForMultipleRoutes(ctx context.Context, t *testing.T, prov // Delete the HTTPRoute, and check if the Service is also removed require.NoError(t, cli.Delete(ctx, &httpRoute)) require.Eventually(t, func() bool { - gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) - res, ok := (*gatewayClassResources)[gc.Name] + res, ok := waitUntilGatewayClassResourcesAreReady(resources, gc.Name) if !ok { return false } @@ -1277,7 +1281,7 @@ func TestNamespacedProvider(t *testing.T) { cli := provider.manager.GetClient() gcName := "gc-watch-ns" - gc := test.GetGatewayClass(gcName, egv1a1.GatewayControllerName) + gc := test.GetGatewayClass(gcName, egv1a1.GatewayControllerName, nil) require.NoError(t, cli.Create(ctx, gc)) // Create the namespaces. @@ -1289,11 +1293,11 @@ func TestNamespacedProvider(t *testing.T) { require.NoError(t, cli.Create(ctx, ns3)) // Create the gateways - gw1 := test.GetGateway(types.NamespacedName{Name: "gw-ns1", Namespace: "ns1"}, gcName) + gw1 := test.GetGateway(types.NamespacedName{Name: "gw-ns1", Namespace: "ns1"}, gcName, 8080) require.NoError(t, cli.Create(ctx, gw1)) - gw2 := test.GetGateway(types.NamespacedName{Name: "gw-ns2", Namespace: "ns2"}, gcName) + gw2 := test.GetGateway(types.NamespacedName{Name: "gw-ns2", Namespace: "ns2"}, gcName, 8080) require.NoError(t, cli.Create(ctx, gw2)) - gw3 := test.GetGateway(types.NamespacedName{Name: "gw-ns3", Namespace: "ns3"}, gcName) + gw3 := test.GetGateway(types.NamespacedName{Name: "gw-ns3", Namespace: "ns3"}, gcName, 8080) require.NoError(t, cli.Create(ctx, gw3)) // Ensure only 2 gateways are reconciled @@ -1347,7 +1351,7 @@ func TestNamespaceSelectorProvider(t *testing.T) { require.NoError(t, cli.Create(ctx, nonWatchedNS)) gcName := "gc-name" - gc := test.GetGatewayClass(gcName, egv1a1.GatewayControllerName) + gc := test.GetGatewayClass(gcName, egv1a1.GatewayControllerName, nil) require.NoError(t, cli.Create(ctx, gc)) require.Eventually(t, func() bool { @@ -1369,21 +1373,24 @@ func TestNamespaceSelectorProvider(t *testing.T) { }() // Create the gateways - watchedGateway := test.GetGateway(types.NamespacedName{Name: "watched-gateway", Namespace: watchedNS.Name}, gcName) + watchedGateway := test.GetGateway(types.NamespacedName{Name: "watched-gateway", Namespace: watchedNS.Name}, gcName, 8080) require.NoError(t, cli.Create(ctx, watchedGateway)) defer func() { require.NoError(t, cli.Delete(ctx, watchedGateway)) }() - nonWatchedGateway := test.GetGateway(types.NamespacedName{Name: "non-watched-gateway", Namespace: nonWatchedNS.Name}, gcName) + nonWatchedGateway := test.GetGateway(types.NamespacedName{Name: "non-watched-gateway", Namespace: nonWatchedNS.Name}, gcName, 8080) require.NoError(t, cli.Create(ctx, nonWatchedGateway)) defer func() { require.NoError(t, cli.Delete(ctx, nonWatchedGateway)) }() require.Eventually(t, func() bool { - gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) - res, ok := (*gatewayClassResources)[gc.Name] + return resources.GatewayAPIResources.Len() != 0 + }, defaultWait, defaultTick) + + require.Eventually(t, func() bool { + res, ok := waitUntilGatewayClassResourcesAreReady(resources, gc.Name) if !ok { return false } @@ -1535,8 +1542,7 @@ func TestNamespaceSelectorProvider(t *testing.T) { }() require.Eventually(t, func() bool { - gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) - res, ok := (*gatewayClassResources)[gc.Name] + res, ok := waitUntilGatewayClassResourcesAreReady(resources, gc.Name) if !ok { return false } @@ -1545,8 +1551,7 @@ func TestNamespaceSelectorProvider(t *testing.T) { }, defaultWait, defaultTick) require.Eventually(t, func() bool { - gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) - res, ok := (*gatewayClassResources)[gc.Name] + res, ok := waitUntilGatewayClassResourcesAreReady(resources, gc.Name) if !ok { return false } @@ -1554,8 +1559,7 @@ func TestNamespaceSelectorProvider(t *testing.T) { }, defaultWait, defaultTick) require.Eventually(t, func() bool { - gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) - res, ok := (*gatewayClassResources)[gc.Name] + res, ok := waitUntilGatewayClassResourcesAreReady(resources, gc.Name) if !ok { return false } @@ -1563,8 +1567,7 @@ func TestNamespaceSelectorProvider(t *testing.T) { }, defaultWait, defaultTick) require.Eventually(t, func() bool { - gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) - res, ok := (*gatewayClassResources)[gc.Name] + res, ok := waitUntilGatewayClassResourcesAreReady(resources, gc.Name) if !ok { return false } @@ -1572,8 +1575,7 @@ func TestNamespaceSelectorProvider(t *testing.T) { }, defaultWait, defaultTick) require.Eventually(t, func() bool { - gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) - res, ok := (*gatewayClassResources)[gc.Name] + res, ok := waitUntilGatewayClassResourcesAreReady(resources, gc.Name) if !ok { return false } @@ -1581,8 +1583,7 @@ func TestNamespaceSelectorProvider(t *testing.T) { }, defaultWait, defaultTick) require.Eventually(t, func() bool { - gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) - res, ok := (*gatewayClassResources)[gc.Name] + res, ok := waitUntilGatewayClassResourcesAreReady(resources, gc.Name) if !ok { return false } @@ -1590,3 +1591,17 @@ func TestNamespaceSelectorProvider(t *testing.T) { }, defaultWait, defaultTick) } + +func waitUntilGatewayClassResourcesAreReady(resources *message.ProviderResources, gatewayClassName string) (*gatewayapi.Resources, bool) { + gatewayClassResources, ok := resources.GatewayAPIResources.Load(egv1a1.GatewayControllerName) + if !ok { + return nil, false + } + + res, ok := (*gatewayClassResources)[gatewayClassName] + if !ok { + return nil, false + } + + return res, true +} diff --git a/internal/provider/kubernetes/predicates.go b/internal/provider/kubernetes/predicates.go index 5a042d1cacfc..c929721dcccf 100644 --- a/internal/provider/kubernetes/predicates.go +++ b/internal/provider/kubernetes/predicates.go @@ -7,6 +7,7 @@ package kubernetes import ( "context" + "fmt" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -23,7 +24,7 @@ import ( egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/gatewayapi" - "github.com/envoyproxy/gateway/internal/provider/utils" + "github.com/envoyproxy/gateway/internal/utils" ) // hasMatchingController returns true if the provided object is a GatewayClass @@ -221,16 +222,11 @@ func (r *gatewayAPIReconciler) validateServiceForReconcile(obj client.Object) bo } // Merged gateways will have only this label, update status of all Gateways under found GatewayClass. - gclass, ok := labels[gatewayapi.OwningGatewayClassLabel] - if ok && r.mergeGateways[gclass] { - res, _ := r.resources.GatewayAPIResources.Load(string(r.classController)) - if res != nil { - if (*res)[gclass] != nil && len((*res)[gclass].Gateways) > 0 { - for _, gw := range (*res)[gclass].Gateways { - gw := gw - r.updateStatusForGateway(ctx, gw) - } - } + gcName, ok := labels[gatewayapi.OwningGatewayClassLabel] + if ok && r.mergeGateways[gcName] { + if err := r.updateStatusForGatewaysUnderGatewayClass(ctx, gcName); err != nil { + r.log.Info("no Gateways found under GatewayClass", "name", gcName) + return false } return false } @@ -323,7 +319,7 @@ func (r *gatewayAPIReconciler) isRouteReferencingBackend(nsName *types.Namespace return allAssociatedRoutes != 0 } -// validateEndpointSliceForReconcile returns true if the the endpointSlice references +// validateEndpointSliceForReconcile returns true if the endpointSlice references // a service that is referenced by a xRoute func (r *gatewayAPIReconciler) validateEndpointSliceForReconcile(obj client.Object) bool { ep, ok := obj.(*discoveryv1.EndpointSlice) @@ -378,16 +374,11 @@ func (r *gatewayAPIReconciler) validateDeploymentForReconcile(obj client.Object) } // Merged gateways will have only this label, update status of all Gateways under found GatewayClass. - gclass, ok := labels[gatewayapi.OwningGatewayClassLabel] - if ok && r.mergeGateways[gclass] { - res, _ := r.resources.GatewayAPIResources.Load(string(r.classController)) - if res != nil { - if (*res)[gclass] != nil && len((*res)[gclass].Gateways) > 0 { - for _, gw := range (*res)[gclass].Gateways { - gw := gw - r.updateStatusForGateway(ctx, gw) - } - } + gcName, ok := labels[gatewayapi.OwningGatewayClassLabel] + if ok && r.mergeGateways[gcName] { + if err := r.updateStatusForGatewaysUnderGatewayClass(ctx, gcName); err != nil { + r.log.Info("no Gateways found under GatewayClass", "name", gcName) + return false } return false } @@ -450,6 +441,27 @@ func (r *gatewayAPIReconciler) findOwningGateway(ctx context.Context, labels map return gtw } +// updateStatusForGatewaysUnderGatewayClass updates status of all Gateways under the GatewayClass. +func (r *gatewayAPIReconciler) updateStatusForGatewaysUnderGatewayClass(ctx context.Context, gatewayClassName string) error { + gateways := new(gwapiv1.GatewayList) + if err := r.client.List(ctx, gateways, &client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector(classGatewayIndex, gatewayClassName), + }); err != nil { + return err + } + + if len(gateways.Items) == 0 { + return fmt.Errorf("no gateways found for gatewayclass: %s", gatewayClassName) + } + + for _, gateway := range gateways.Items { + gateway := gateway + r.updateStatusForGateway(ctx, &gateway) + } + + return nil +} + func (r *gatewayAPIReconciler) handleNode(obj client.Object) bool { ctx := context.Background() node, ok := obj.(*corev1.Node) diff --git a/internal/provider/kubernetes/predicates_test.go b/internal/provider/kubernetes/predicates_test.go index c36f29016bbe..cd88d7b7100c 100644 --- a/internal/provider/kubernetes/predicates_test.go +++ b/internal/provider/kubernetes/predicates_test.go @@ -38,12 +38,12 @@ func TestGatewayClassHasMatchingController(t *testing.T) { }{ { name: "matching controller name", - obj: test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), + obj: test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil), expect: true, }, { name: "non-matching controller name", - obj: test.GetGatewayClass("test-gc", "not.configured/controller"), + obj: test.GetGatewayClass("test-gc", "not.configured/controller", nil), expect: false, }, } @@ -149,14 +149,14 @@ func TestValidateGatewayForReconcile(t *testing.T) { }{ { name: "references class with matching controller name", - configs: []client.Object{test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName)}, - gateway: test.GetGateway(types.NamespacedName{Name: "scheduled-status-test"}, "test-gc"), + configs: []client.Object{test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil)}, + gateway: test.GetGateway(types.NamespacedName{Name: "scheduled-status-test"}, "test-gc", 8080), expect: true, }, { name: "references class with non-matching controller name", - configs: []client.Object{test.GetGatewayClass("test-gc", "not.configured/controller")}, - gateway: test.GetGateway(types.NamespacedName{Name: "scheduled-status-test"}, "test-gc"), + configs: []client.Object{test.GetGatewayClass("test-gc", "not.configured/controller", nil)}, + gateway: test.GetGateway(types.NamespacedName{Name: "scheduled-status-test"}, "test-gc", 8080), expect: false, }, } @@ -191,8 +191,8 @@ func TestValidateSecretForReconcile(t *testing.T) { { name: "references valid gateway", configs: []client.Object{ - test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), - test.GetSecureGateway(types.NamespacedName{Name: "scheduled-status-test"}, "test-gc", test.ObjectKindNamespacedName{ + test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil), + test.GetSecureGateway(types.NamespacedName{Name: "scheduled-status-test"}, "test-gc", test.GroupKindNamespacedName{ Kind: gatewayapi.KindSecret, Name: "secret", }), @@ -203,8 +203,8 @@ func TestValidateSecretForReconcile(t *testing.T) { { name: "references invalid gateway", configs: []client.Object{ - test.GetGatewayClass("test-gc", "not.configured/controller"), - test.GetSecureGateway(types.NamespacedName{Name: "scheduled-status-test"}, "test-gc", test.ObjectKindNamespacedName{ + test.GetGatewayClass("test-gc", "not.configured/controller", nil), + test.GetSecureGateway(types.NamespacedName{Name: "scheduled-status-test"}, "test-gc", test.GroupKindNamespacedName{ Kind: gatewayapi.KindSecret, Name: "secret", }), @@ -215,8 +215,8 @@ func TestValidateSecretForReconcile(t *testing.T) { { name: "references SecurityPolicy OIDC", configs: []client.Object{ - test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), - test.GetGateway(types.NamespacedName{Name: "scheduled-status-test"}, "test-gc"), + test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil), + test.GetGateway(types.NamespacedName{Name: "scheduled-status-test"}, "test-gc", 8080), &v1alpha1.SecurityPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "oidc", @@ -248,8 +248,8 @@ func TestValidateSecretForReconcile(t *testing.T) { { name: "references SecurityPolicy Basic Auth", configs: []client.Object{ - test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), - test.GetGateway(types.NamespacedName{Name: "scheduled-status-test"}, "test-gc"), + test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil), + test.GetGateway(types.NamespacedName{Name: "scheduled-status-test"}, "test-gc", 8080), &v1alpha1.SecurityPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "basic-auth", @@ -275,7 +275,7 @@ func TestValidateSecretForReconcile(t *testing.T) { { name: "secret is not referenced by any EG CRs", configs: []client.Object{ - test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), + test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil), }, secret: test.GetSecret(types.NamespacedName{Name: "secret"}), expect: false, @@ -308,7 +308,7 @@ func TestValidateSecretForReconcile(t *testing.T) { // TestValidateEndpointSliceForReconcile tests the validateEndpointSliceForReconcile // predicate function. func TestValidateEndpointSliceForReconcile(t *testing.T) { - sampleGateway := test.GetGateway(types.NamespacedName{Namespace: "default", Name: "scheduled-status-test"}, "test-gc") + sampleGateway := test.GetGateway(types.NamespacedName{Namespace: "default", Name: "scheduled-status-test"}, "test-gc", 8080) testCases := []struct { name string @@ -319,7 +319,7 @@ func TestValidateEndpointSliceForReconcile(t *testing.T) { { name: "route service but no routes exist", configs: []client.Object{ - test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), + test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil), sampleGateway, }, endpointSlice: test.GetEndpointSlice(types.NamespacedName{Name: "endpointslice"}, "service"), @@ -328,7 +328,7 @@ func TestValidateEndpointSliceForReconcile(t *testing.T) { { name: "http route service routes exist, but endpointslice is associated with another service", configs: []client.Object{ - test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), + test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil), sampleGateway, test.GetHTTPRoute(types.NamespacedName{Name: "httproute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}, 80), }, @@ -338,7 +338,7 @@ func TestValidateEndpointSliceForReconcile(t *testing.T) { { name: "http route service routes exist", configs: []client.Object{ - test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), + test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil), sampleGateway, test.GetHTTPRoute(types.NamespacedName{Name: "httproute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}, 80), }, @@ -376,7 +376,8 @@ func TestValidateEndpointSliceForReconcile(t *testing.T) { // TestValidateServiceForReconcile tests the validateServiceForReconcile // predicate function. func TestValidateServiceForReconcile(t *testing.T) { - sampleGateway := test.GetGateway(types.NamespacedName{Namespace: "default", Name: "scheduled-status-test"}, "test-gc") + sampleGateway := test.GetGateway(types.NamespacedName{Namespace: "default", Name: "scheduled-status-test"}, "test-gc", 8080) + mergeGatewaysConfig := test.GetEnvoyProxy(types.NamespacedName{Namespace: "default", Name: "merge-gateways-config"}, true) testCases := []struct { name string @@ -387,7 +388,7 @@ func TestValidateServiceForReconcile(t *testing.T) { { name: "gateway service but deployment does not exist", configs: []client.Object{ - test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), + test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil), sampleGateway, }, service: test.GetService(types.NamespacedName{Name: "service"}, map[string]string{ @@ -399,7 +400,7 @@ func TestValidateServiceForReconcile(t *testing.T) { { name: "gateway service deployment also exist", configs: []client.Object{ - test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), + test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil), sampleGateway, test.GetGatewayDeployment(types.NamespacedName{Name: infraName(sampleGateway, false)}, nil), }, @@ -414,7 +415,7 @@ func TestValidateServiceForReconcile(t *testing.T) { { name: "route service but no routes exist", configs: []client.Object{ - test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), + test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil), sampleGateway, }, service: test.GetService(types.NamespacedName{Name: "service"}, nil, nil), @@ -423,7 +424,7 @@ func TestValidateServiceForReconcile(t *testing.T) { { name: "http route service routes exist", configs: []client.Object{ - test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), + test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil), sampleGateway, test.GetHTTPRoute(types.NamespacedName{Name: "httproute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}, 80), }, @@ -436,7 +437,7 @@ func TestValidateServiceForReconcile(t *testing.T) { // in which case we'll have to reconcile the bad config, and remove listeners accordingly. name: "route service routes exist but with non-existing gateway reference", configs: []client.Object{ - test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), + test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil), test.GetHTTPRoute(types.NamespacedName{Name: "httproute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}, 80), }, service: test.GetService(types.NamespacedName{Name: "service"}, nil, nil), @@ -445,7 +446,7 @@ func TestValidateServiceForReconcile(t *testing.T) { { name: "grpc route service routes exist", configs: []client.Object{ - test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), + test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil), sampleGateway, test.GetGRPCRoute(types.NamespacedName{Name: "grpcroute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}, 80), }, @@ -455,7 +456,7 @@ func TestValidateServiceForReconcile(t *testing.T) { { name: "tls route service routes exist", configs: []client.Object{ - test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), + test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil), sampleGateway, test.GetTLSRoute(types.NamespacedName{Name: "tlsroute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}, 443), @@ -466,7 +467,7 @@ func TestValidateServiceForReconcile(t *testing.T) { { name: "udp route service routes exist", configs: []client.Object{ - test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), + test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil), sampleGateway, test.GetUDPRoute(types.NamespacedName{Name: "udproute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}, 80), @@ -477,7 +478,7 @@ func TestValidateServiceForReconcile(t *testing.T) { { name: "tcp route service routes exist", configs: []client.Object{ - test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), + test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil), sampleGateway, test.GetTCPRoute(types.NamespacedName{Name: "tcproute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}, 80), @@ -512,6 +513,41 @@ func TestValidateServiceForReconcile(t *testing.T) { service: test.GetService(types.NamespacedName{Name: "ext-auth-http-service"}, nil, nil), expect: true, }, + { + name: "update status of all gateways under gatewayclass when MergeGateways enabled", + configs: []client.Object{ + test.GetGatewayClass("test-mg", v1alpha1.GatewayControllerName, &test.GroupKindNamespacedName{ + Group: gwapiv1.Group(mergeGatewaysConfig.GroupVersionKind().Group), + Kind: gwapiv1.Kind(mergeGatewaysConfig.Kind), + Namespace: gwapiv1.Namespace(mergeGatewaysConfig.Namespace), + Name: gwapiv1.ObjectName(mergeGatewaysConfig.Name), + }), + mergeGatewaysConfig, + test.GetGateway(types.NamespacedName{Name: "merged-gateway-1", Namespace: "default"}, "test-mg", 8081), + test.GetGateway(types.NamespacedName{Name: "merged-gateway-2", Namespace: "default"}, "test-mg", 8082), + test.GetGateway(types.NamespacedName{Name: "merged-gateway-3", Namespace: "default"}, "test-mg", 8083), + }, + service: test.GetService(types.NamespacedName{Name: "service"}, map[string]string{ + gatewayapi.OwningGatewayClassLabel: "test-mg", + }, nil), + expect: false, + }, + { + name: "no gateways found under gatewayclass when MergeGateways enabled", + configs: []client.Object{ + test.GetGatewayClass("test-mg", v1alpha1.GatewayControllerName, &test.GroupKindNamespacedName{ + Group: gwapiv1.Group(mergeGatewaysConfig.GroupVersionKind().Group), + Kind: gwapiv1.Kind(mergeGatewaysConfig.Kind), + Namespace: gwapiv1.Namespace(mergeGatewaysConfig.Namespace), + Name: gwapiv1.ObjectName(mergeGatewaysConfig.Name), + }), + mergeGatewaysConfig, + }, + service: test.GetService(types.NamespacedName{Name: "service"}, map[string]string{ + gatewayapi.OwningGatewayClassLabel: "test-mg", + }, nil), + expect: false, + }, } // Create the reconciler. @@ -520,6 +556,9 @@ func TestValidateServiceForReconcile(t *testing.T) { r := gatewayAPIReconciler{ classController: v1alpha1.GatewayControllerName, log: logger, + mergeGateways: map[string]bool{ + "test-mg": true, + }, } for _, tc := range testCases { @@ -544,7 +583,8 @@ func TestValidateServiceForReconcile(t *testing.T) { // TestValidateDeploymentForReconcile tests the validateDeploymentForReconcile // predicate function. func TestValidateDeploymentForReconcile(t *testing.T) { - sampleGateway := test.GetGateway(types.NamespacedName{Namespace: "default", Name: "scheduled-status-test"}, "test-gc") + sampleGateway := test.GetGateway(types.NamespacedName{Namespace: "default", Name: "scheduled-status-test"}, "test-gc", 8080) + mergeGatewaysConfig := test.GetEnvoyProxy(types.NamespacedName{Namespace: "default", Name: "merge-gateways-config"}, true) testCases := []struct { name string @@ -557,7 +597,7 @@ func TestValidateDeploymentForReconcile(t *testing.T) { // purpose of the Deployment watcher is just for update Gateway object statuses. name: "gateway deployment deployment also exist", configs: []client.Object{ - test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName), + test.GetGatewayClass("test-gc", v1alpha1.GatewayControllerName, nil), sampleGateway, test.GetService(types.NamespacedName{Name: "deployment"}, map[string]string{ gatewayapi.OwningGatewayNameLabel: "scheduled-status-test", @@ -570,6 +610,41 @@ func TestValidateDeploymentForReconcile(t *testing.T) { }), expect: false, }, + { + name: "update status of all gateways under gatewayclass when MergeGateways enabled", + configs: []client.Object{ + test.GetGatewayClass("test-mg", v1alpha1.GatewayControllerName, &test.GroupKindNamespacedName{ + Group: gwapiv1.Group(mergeGatewaysConfig.GroupVersionKind().Group), + Kind: gwapiv1.Kind(mergeGatewaysConfig.Kind), + Namespace: gwapiv1.Namespace(mergeGatewaysConfig.Namespace), + Name: gwapiv1.ObjectName(mergeGatewaysConfig.Name), + }), + mergeGatewaysConfig, + }, + deployment: test.GetGatewayDeployment(types.NamespacedName{Name: "deployment"}, map[string]string{ + gatewayapi.OwningGatewayClassLabel: "test-mg", + }), + expect: false, + }, + { + name: "no gateways found under gatewayclass when MergeGateways enabled", + configs: []client.Object{ + test.GetGatewayClass("test-mg", v1alpha1.GatewayControllerName, &test.GroupKindNamespacedName{ + Group: gwapiv1.Group(mergeGatewaysConfig.GroupVersionKind().Group), + Kind: gwapiv1.Kind(mergeGatewaysConfig.Kind), + Namespace: gwapiv1.Namespace(mergeGatewaysConfig.Namespace), + Name: gwapiv1.ObjectName(mergeGatewaysConfig.Name), + }), + mergeGatewaysConfig, + test.GetGateway(types.NamespacedName{Name: "merged-gateway-1", Namespace: "default"}, "test-mg", 8081), + test.GetGateway(types.NamespacedName{Name: "merged-gateway-2", Namespace: "default"}, "test-mg", 8082), + test.GetGateway(types.NamespacedName{Name: "merged-gateway-3", Namespace: "default"}, "test-mg", 8083), + }, + deployment: test.GetGatewayDeployment(types.NamespacedName{Name: "deployment"}, map[string]string{ + gatewayapi.OwningGatewayClassLabel: "test-mg", + }), + expect: false, + }, } // Create the reconciler. @@ -578,6 +653,9 @@ func TestValidateDeploymentForReconcile(t *testing.T) { r := gatewayAPIReconciler{ classController: v1alpha1.GatewayControllerName, log: logger, + mergeGateways: map[string]bool{ + "test-mg": true, + }, } for _, tc := range testCases { diff --git a/internal/provider/kubernetes/routes.go b/internal/provider/kubernetes/routes.go index ae0fa3fe8830..c3c02ec72c5e 100644 --- a/internal/provider/kubernetes/routes.go +++ b/internal/provider/kubernetes/routes.go @@ -17,7 +17,7 @@ import ( gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" "github.com/envoyproxy/gateway/internal/gatewayapi" - "github.com/envoyproxy/gateway/internal/provider/utils" + "github.com/envoyproxy/gateway/internal/utils" ) // processTLSRoutes finds TLSRoutes corresponding to a gatewayNamespaceName, further checks for diff --git a/internal/provider/kubernetes/routes_test.go b/internal/provider/kubernetes/routes_test.go index b7d747aa3e8e..5b31a04db8f3 100644 --- a/internal/provider/kubernetes/routes_test.go +++ b/internal/provider/kubernetes/routes_test.go @@ -8,6 +8,7 @@ package kubernetes import ( "context" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -26,10 +27,15 @@ import ( "github.com/envoyproxy/gateway/internal/envoygateway" "github.com/envoyproxy/gateway/internal/gatewayapi" "github.com/envoyproxy/gateway/internal/logging" - "github.com/envoyproxy/gateway/internal/provider/utils" + "github.com/envoyproxy/gateway/internal/utils" ) func TestProcessHTTPRoutes(t *testing.T) { + const ( + defaultWait = time.Second * 10 + defaultTick = time.Millisecond * 20 + ) + // The gatewayclass configured for the reconciler and referenced by test cases. gcCtrlName := gwapiv1.GatewayController(egv1a1.GatewayControllerName) gc := &gwapiv1.GatewayClass{ @@ -62,6 +68,8 @@ func TestProcessHTTPRoutes(t *testing.T) { invalidDuration := gwapiv1.Duration("invalid duration") + httpRouteNS := "test" + testCases := []struct { name string routes []*gwapiv1.HTTPRoute @@ -74,7 +82,7 @@ func TestProcessHTTPRoutes(t *testing.T) { routes: []*gwapiv1.HTTPRoute{ { ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", + Namespace: httpRouteNS, Name: "test", }, Spec: gwapiv1.HTTPRouteSpec{ @@ -118,7 +126,7 @@ func TestProcessHTTPRoutes(t *testing.T) { routes: []*gwapiv1.HTTPRoute{ { ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", + Namespace: httpRouteNS, Name: "test", }, Spec: gwapiv1.HTTPRouteSpec{ @@ -172,7 +180,7 @@ func TestProcessHTTPRoutes(t *testing.T) { "kind": "Foo", "metadata": map[string]interface{}{ "name": "test", - "namespace": "test", + "namespace": httpRouteNS, }, }, }, @@ -191,7 +199,7 @@ func TestProcessHTTPRoutes(t *testing.T) { routes: []*gwapiv1.HTTPRoute{ { ObjectMeta: metav1.ObjectMeta{ - Namespace: "test", + Namespace: httpRouteNS, Name: "test", }, Spec: gwapiv1.HTTPRouteSpec{ @@ -269,6 +277,15 @@ func TestProcessHTTPRoutes(t *testing.T) { WithIndex(&gwapiv1.HTTPRoute{}, gatewayHTTPRouteIndex, gatewayHTTPRouteIndexFunc). Build() + // Wait until all the httproutes have been initialized. + require.Eventually(t, func() bool { + httpRoutes := gwapiv1.HTTPRouteList{} + if err := r.client.List(ctx, &httpRoutes, client.InNamespace(httpRouteNS)); err != nil { + return false + } + return len(httpRoutes.Items) > 0 + }, defaultWait, defaultTick) + // Process the test case httproutes. resourceTree := gatewayapi.NewResources() resourceMap := newResourceMapping() diff --git a/internal/provider/kubernetes/secrets.go b/internal/provider/kubernetes/secrets.go index e14f67b7ccb6..5a2a8c7776cc 100644 --- a/internal/provider/kubernetes/secrets.go +++ b/internal/provider/kubernetes/secrets.go @@ -14,10 +14,10 @@ import ( corev1 "k8s.io/api/core/v1" kerrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" "github.com/envoyproxy/gateway/internal/crypto" + "github.com/envoyproxy/gateway/internal/utils" ) var ( @@ -86,10 +86,7 @@ func CreateOrUpdateSecrets(ctx context.Context, client client.Client, secrets [] for i := range secrets { secret := secrets[i] current := new(corev1.Secret) - key := types.NamespacedName{ - Namespace: secret.Namespace, - Name: secret.Name, - } + key := utils.NamespacedName(&secret) if err := client.Get(ctx, key, current); err != nil { // Create if not found. if kerrors.IsNotFound(err) { diff --git a/internal/provider/kubernetes/status.go b/internal/provider/kubernetes/status.go index 83f88579c46b..f26ae4c877aa 100644 --- a/internal/provider/kubernetes/status.go +++ b/internal/provider/kubernetes/status.go @@ -17,8 +17,8 @@ import ( "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/message" - "github.com/envoyproxy/gateway/internal/provider/utils" "github.com/envoyproxy/gateway/internal/status" + "github.com/envoyproxy/gateway/internal/utils" ) // subscribeAndUpdateStatus subscribes to gateway API object status updates and diff --git a/internal/provider/kubernetes/test/utils.go b/internal/provider/kubernetes/test/utils.go index bb1fe05b6888..a221d067f203 100644 --- a/internal/provider/kubernetes/test/utils.go +++ b/internal/provider/kubernetes/test/utils.go @@ -18,25 +18,29 @@ import ( egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" ) -type ObjectKindNamespacedName struct { - Kind string - Namespace string - Name string +type GroupKindNamespacedName struct { + Group gwapiv1.Group + Kind gwapiv1.Kind + Namespace gwapiv1.Namespace + Name gwapiv1.ObjectName } -// NewEnvoyProxy returns an EnvoyProxy object with the provided ns/name. -func NewEnvoyProxy(ns, name string) *egv1a1.EnvoyProxy { +// GetEnvoyProxy returns an EnvoyProxy object with the provided ns/name. +func GetEnvoyProxy(nsName types.NamespacedName, mergeGateways bool) *egv1a1.EnvoyProxy { return &egv1a1.EnvoyProxy{ ObjectMeta: metav1.ObjectMeta{ - Namespace: ns, - Name: name, + Name: nsName.Name, + Namespace: nsName.Namespace, + }, + Spec: egv1a1.EnvoyProxySpec{ + MergeGateways: &mergeGateways, }, } } // GetGatewayClass returns a sample GatewayClass. -func GetGatewayClass(name string, controller gwapiv1.GatewayController) *gwapiv1.GatewayClass { - return &gwapiv1.GatewayClass{ +func GetGatewayClass(name string, controller gwapiv1.GatewayController, envoyProxy *GroupKindNamespacedName) *gwapiv1.GatewayClass { + gwc := &gwapiv1.GatewayClass{ ObjectMeta: metav1.ObjectMeta{ Name: name, }, @@ -44,21 +48,32 @@ func GetGatewayClass(name string, controller gwapiv1.GatewayController) *gwapiv1 ControllerName: controller, }, } + + if envoyProxy != nil { + gwc.Spec.ParametersRef = &gwapiv1.ParametersReference{ + Group: envoyProxy.Group, + Kind: envoyProxy.Kind, + Name: string(envoyProxy.Name), + Namespace: &envoyProxy.Namespace, + } + } + + return gwc } // GetGateway returns a sample Gateway with single listener. -func GetGateway(nsname types.NamespacedName, gwclass string) *gwapiv1.Gateway { +func GetGateway(nsName types.NamespacedName, gwclass string, listenerPort int32) *gwapiv1.Gateway { return &gwapiv1.Gateway{ ObjectMeta: metav1.ObjectMeta{ - Namespace: nsname.Namespace, - Name: nsname.Name, + Namespace: nsName.Namespace, + Name: nsName.Name, }, Spec: gwapiv1.GatewaySpec{ GatewayClassName: gwapiv1.ObjectName(gwclass), Listeners: []gwapiv1.Listener{ { Name: "test", - Port: gwapiv1.PortNumber(int32(8080)), + Port: gwapiv1.PortNumber(listenerPort), Protocol: gwapiv1.HTTPProtocolType, }, }, @@ -67,14 +82,14 @@ func GetGateway(nsname types.NamespacedName, gwclass string) *gwapiv1.Gateway { } // GetSecureGateway returns a sample Gateway with single TLS listener. -func GetSecureGateway(nsname types.NamespacedName, gwclass string, secretKindNSName ObjectKindNamespacedName) *gwapiv1.Gateway { - secureGateway := GetGateway(nsname, gwclass) +func GetSecureGateway(nsName types.NamespacedName, gwclass string, secretKindNSName GroupKindNamespacedName) *gwapiv1.Gateway { + secureGateway := GetGateway(nsName, gwclass, 8080) secureGateway.Spec.Listeners[0].TLS = &gwapiv1.GatewayTLSConfig{ Mode: ptr.To(gwapiv1.TLSModeTerminate), CertificateRefs: []gwapiv1.SecretObjectReference{{ - Kind: (*gwapiv1.Kind)(&secretKindNSName.Kind), - Namespace: (*gwapiv1.Namespace)(&secretKindNSName.Namespace), - Name: gwapiv1.ObjectName(secretKindNSName.Name), + Kind: &secretKindNSName.Kind, + Namespace: &secretKindNSName.Namespace, + Name: secretKindNSName.Name, }}, } @@ -82,11 +97,11 @@ func GetSecureGateway(nsname types.NamespacedName, gwclass string, secretKindNSN } // GetSecret returns a sample Secret object. -func GetSecret(nsname types.NamespacedName) *corev1.Secret { +func GetSecret(nsName types.NamespacedName) *corev1.Secret { return &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Namespace: nsname.Namespace, - Name: nsname.Name, + Namespace: nsName.Namespace, + Name: nsName.Name, }, } } @@ -241,11 +256,11 @@ func GetUDPRoute(nsName types.NamespacedName, parent string, serviceName types.N } // GetGatewayDeployment returns a sample Deployment for a Gateway object. -func GetGatewayDeployment(nsname types.NamespacedName, labels map[string]string) *appsv1.Deployment { +func GetGatewayDeployment(nsName types.NamespacedName, labels map[string]string) *appsv1.Deployment { return &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ - Namespace: nsname.Namespace, - Name: nsname.Name, + Namespace: nsName.Namespace, + Name: nsName.Name, Labels: labels, }, Spec: appsv1.DeploymentSpec{ @@ -269,11 +284,11 @@ func GetGatewayDeployment(nsname types.NamespacedName, labels map[string]string) } // GetService returns a sample Service with labels and ports. -func GetService(nsname types.NamespacedName, labels map[string]string, ports map[string]int32) *corev1.Service { +func GetService(nsName types.NamespacedName, labels map[string]string, ports map[string]int32) *corev1.Service { service := &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ - Name: nsname.Name, - Namespace: nsname.Namespace, + Name: nsName.Name, + Namespace: nsName.Namespace, Labels: labels, }, Spec: corev1.ServiceSpec{ diff --git a/internal/provider/utils/utils.go b/internal/utils/misc.go similarity index 70% rename from internal/provider/utils/utils.go rename to internal/utils/misc.go index 48f3f8703f60..6e434660de64 100644 --- a/internal/provider/utils/utils.go +++ b/internal/utils/misc.go @@ -8,6 +8,7 @@ package utils import ( "crypto/sha256" "fmt" + "hash/fnv" "strings" "k8s.io/apimachinery/pkg/types" @@ -25,7 +26,7 @@ func NamespacedName(obj client.Object) types.NamespacedName { // GetHashedName returns a partially hashed name for the string including up to the given length of the original name characters before the hash. // Input `nsName` should be formatted as `{Namespace}/{ResourceName}`. func GetHashedName(nsName string, length int) string { - hashedName := HashString(nsName) + hashedName := Digest256(nsName) // replace `/` with `-` to create a valid K8s resource name resourceName := strings.ReplaceAll(nsName, "/", "-") if length > 0 && len(resourceName) > length { @@ -33,11 +34,23 @@ func GetHashedName(nsName string, length int) string { trimmedName := strings.TrimSuffix(resourceName[0:length], "-") return fmt.Sprintf("%s-%s", trimmedName, hashedName[0:8]) } + // Ideally we should use 32-bit hash instead of 64-bit hash and return the first 8 characters of the hash. + // However, we are using 64-bit hash to maintain backward compatibility. return fmt.Sprintf("%s-%s", resourceName, hashedName[0:8]) } -func HashString(str string) string { +// Digest256 returns a sha256 hash of the input string. +// The hash is represented as a hexadecimal string of length 64. +func Digest256(str string) string { h := sha256.New() // Using sha256 instead of sha1 due to Blocklisted import crypto/sha1: weak cryptographic primitive (gosec) h.Write([]byte(str)) return strings.ToLower(fmt.Sprintf("%x", h.Sum(nil))) } + +// Digest32 returns a 32-bit hash of the input string. +// The hash is represented as a hexadecimal string of length 8. +func Digest32(str string) string { + h := fnv.New32a() + _, _ = h.Write([]byte(str)) + return fmt.Sprintf("%x", h.Sum32()) +} diff --git a/internal/provider/utils/utils_test.go b/internal/utils/misc_test.go similarity index 100% rename from internal/provider/utils/utils_test.go rename to internal/utils/misc_test.go diff --git a/internal/xds/bootstrap/bootstrap.go b/internal/xds/bootstrap/bootstrap.go index 8d6b2b67b77f..5fbc63d66a40 100644 --- a/internal/xds/bootstrap/bootstrap.go +++ b/internal/xds/bootstrap/bootstrap.go @@ -24,10 +24,10 @@ const ( // envoyGatewayXdsServerHost is the DNS name of the Xds Server within Envoy Gateway. // It defaults to the Envoy Gateway Kubernetes service. envoyGatewayXdsServerHost = "envoy-gateway" - // envoyAdminAddress is the listening address of the envoy admin interface. - envoyAdminAddress = "127.0.0.1" - // envoyAdminPort is the port used to expose admin interface. - envoyAdminPort = 19000 + // EnvoyAdminAddress is the listening address of the envoy admin interface. + EnvoyAdminAddress = "127.0.0.1" + // EnvoyAdminPort is the port used to expose admin interface. + EnvoyAdminPort = 19000 // envoyAdminAccessLogPath is the path used to expose admin access log. envoyAdminAccessLogPath = "/dev/null" @@ -185,8 +185,8 @@ func GetRenderedBootstrapConfig(proxyMetrics *egv1a1.ProxyMetrics) (string, erro Port: DefaultXdsServerPort, }, AdminServer: adminServerParameters{ - Address: envoyAdminAddress, - Port: envoyAdminPort, + Address: EnvoyAdminAddress, + Port: EnvoyAdminPort, AccessLogPath: envoyAdminAccessLogPath, }, ReadyServer: readyServerParameters{ diff --git a/internal/xds/translator/jwt.go b/internal/xds/translator/jwt.go index e1bc76fa1af9..55c4005064bf 100644 --- a/internal/xds/translator/jwt.go +++ b/internal/xds/translator/jwt.go @@ -145,6 +145,10 @@ func buildJWTAuthn(irListener *ir.HTTPListener) (*jwtauthnv3.JwtAuthentication, Forward: true, } + if irProvider.RecomputeRoute != nil { + jwtProvider.ClearRouteCache = *irProvider.RecomputeRoute + } + if irProvider.ExtractFrom != nil { jwtProvider.FromHeaders = buildJwtFromHeaders(irProvider.ExtractFrom.Headers) jwtProvider.FromCookies = irProvider.ExtractFrom.Cookies diff --git a/internal/xds/translator/listener.go b/internal/xds/translator/listener.go index 268cc1dd41c7..08287738a1cb 100644 --- a/internal/xds/translator/listener.go +++ b/internal/xds/translator/listener.go @@ -148,6 +148,9 @@ func buildXdsTCPListener(name, address string, port uint32, keepalive *ir.TCPKee }, }, }, + // Remove /healthcheck/fail from endpoints that trigger a drain of listeners for better control + // over the drain process while still allowing the healthcheck to be failed during pod shutdown. + DrainType: listenerv3.Listener_MODIFY_ONLY, } } @@ -171,6 +174,9 @@ func buildXdsQuicListener(name, address string, port uint32, accesslog *ir.Acces DownstreamSocketConfig: &corev3.UdpSocketConfig{}, QuicOptions: &listenerv3.QuicProtocolOptions{}, }, + // Remove /healthcheck/fail from endpoints that trigger a drain of listeners for better control + // over the drain process while still allowing the healthcheck to be failed during pod shutdown. + DrainType: listenerv3.Listener_MODIFY_ONLY, } return xdsListener @@ -242,14 +248,6 @@ func (t *Translator) addXdsHTTPFilterChain(xdsListener *listenerv3.Listener, irL mgr.HttpFilters = append(mgr.HttpFilters, xdsfilters.GRPCWeb) // always enable grpc stats filter mgr.HttpFilters = append(mgr.HttpFilters, xdsfilters.GRPCStats) - } else { - // Allow websocket upgrades for HTTP 1.1 - // Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism - mgr.UpgradeConfigs = []*hcmv3.HttpConnectionManager_UpgradeConfig{ - { - UpgradeType: "websocket", - }, - } } if http3Listener { diff --git a/internal/xds/translator/route.go b/internal/xds/translator/route.go index c711e64daf5e..07336fa48ee1 100644 --- a/internal/xds/translator/route.go +++ b/internal/xds/translator/route.go @@ -8,6 +8,7 @@ package translator import ( "errors" "strings" + "time" corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" routev3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" @@ -57,20 +58,26 @@ func buildXdsRoute(httpRoute *ir.HTTPRoute) (*routev3.Route, error) { router.Action = &routev3.Route_Route{Route: routeAction} default: + var routeAction *routev3.RouteAction if httpRoute.BackendWeights.Invalid != 0 { // If there are invalid backends then a weighted cluster is required for the route - routeAction := buildXdsWeightedRouteAction(httpRoute) - if httpRoute.Mirrors != nil { - routeAction.RequestMirrorPolicies = buildXdsRequestMirrorPolicies(httpRoute.Mirrors) - } - router.Action = &routev3.Route_Route{Route: routeAction} + routeAction = buildXdsWeightedRouteAction(httpRoute) } else { - routeAction := buildXdsRouteAction(httpRoute.Destination.Name) - if httpRoute.Mirrors != nil { - routeAction.RequestMirrorPolicies = buildXdsRequestMirrorPolicies(httpRoute.Mirrors) + routeAction = buildXdsRouteAction(httpRoute) + } + if httpRoute.Mirrors != nil { + routeAction.RequestMirrorPolicies = buildXdsRequestMirrorPolicies(httpRoute.Mirrors) + } + if !httpRoute.IsHTTP2 { + // Allow websocket upgrades for HTTP 1.1 + // Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism + routeAction.UpgradeConfigs = []*routev3.RouteAction_UpgradeConfig{ + { + UpgradeType: "websocket", + }, } - router.Action = &routev3.Route_Route{Route: routeAction} } + router.Action = &routev3.Route_Route{Route: routeAction} } // Hash Policy @@ -201,11 +208,12 @@ func buildXdsStringMatcher(irMatch *ir.StringMatch) *matcherv3.StringMatcher { return stringMatcher } -func buildXdsRouteAction(destName string) *routev3.RouteAction { +func buildXdsRouteAction(httpRoute *ir.HTTPRoute) *routev3.RouteAction { return &routev3.RouteAction{ ClusterSpecifier: &routev3.RouteAction_Cluster{ - Cluster: destName, + Cluster: httpRoute.Destination.Name, }, + IdleTimeout: idleTimeout(httpRoute), } } @@ -233,7 +241,29 @@ func buildXdsWeightedRouteAction(httpRoute *ir.HTTPRoute) *routev3.RouteAction { Clusters: clusters, }, }, + IdleTimeout: idleTimeout(httpRoute), + } +} + +func idleTimeout(httpRoute *ir.HTTPRoute) *durationpb.Duration { + if httpRoute.Timeout != nil && httpRoute.Timeout.HTTP != nil { + if httpRoute.Timeout.HTTP.RequestTimeout != nil { + timeout := time.Hour // Default to 1 hour + + // Ensure is not less than the request timeout + if timeout < httpRoute.Timeout.HTTP.RequestTimeout.Duration { + timeout = httpRoute.Timeout.HTTP.RequestTimeout.Duration + } + + // Disable idle timeout when request timeout is disabled + if httpRoute.Timeout.HTTP.RequestTimeout.Duration == 0 { + timeout = 0 + } + + return durationpb.New(timeout) + } } + return nil } func buildXdsRedirectAction(redirection *ir.Redirect) *routev3.RedirectAction { diff --git a/internal/xds/translator/testdata/in/xds-ir/http-route-timeout.yaml b/internal/xds/translator/testdata/in/xds-ir/http-route-timeout.yaml index da1a4243aa3a..fdd2b84ef849 100644 --- a/internal/xds/translator/testdata/in/xds-ir/http-route-timeout.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/http-route-timeout.yaml @@ -23,3 +23,25 @@ http: - endpoints: - host: "1.2.3.4" port: 50000 + - name: "second-route" + hostname: "*" + timeout: + http: + requestTimeout: 4000s + destination: + name: "second-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50001 + - name: "third-route" + hostname: "*" + timeout: + http: + requestTimeout: 0s + destination: + name: "third-route-dest" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50002 diff --git a/internal/xds/translator/testdata/in/xds-ir/jwt-multi-route-multi-provider.yaml b/internal/xds/translator/testdata/in/xds-ir/jwt-multi-route-multi-provider.yaml index e3337f261eeb..558049ed5629 100644 --- a/internal/xds/translator/testdata/in/xds-ir/jwt-multi-route-multi-provider.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/jwt-multi-route-multi-provider.yaml @@ -30,6 +30,7 @@ http: - two.foo.com remoteJWKS: uri: https://192.168.1.250:8080/jwt/public-key/jwks.json + recomputeRoute: true claimToHeaders: - header: one-route-example2-key1 claim: claim.neteased.key diff --git a/internal/xds/translator/testdata/in/xds-ir/oidc.yaml b/internal/xds/translator/testdata/in/xds-ir/oidc.yaml index ee69934f1c53..b90a1c97f4ac 100644 --- a/internal/xds/translator/testdata/in/xds-ir/oidc.yaml +++ b/internal/xds/translator/testdata/in/xds-ir/oidc.yaml @@ -55,4 +55,4 @@ http: redirectURL: "https://www.example.com/bar/oauth2/callback" redirectPath: "/bar/oauth2/callback" logoutPath: "/bar/logout" - cookieSuffix: B0A1B740 + cookieSuffix: 5f93c2e4 diff --git a/internal/xds/translator/testdata/out/extension-xds-ir/http-route-extension-filter.listeners.yaml b/internal/xds/translator/testdata/out/extension-xds-ir/http-route-extension-filter.listeners.yaml index c5835215d896..ab175eb84ac4 100644 --- a/internal/xds/translator/testdata/out/extension-xds-ir/http-route-extension-filter.listeners.yaml +++ b/internal/xds/translator/testdata/out/extension-xds-ir/http-route-extension-filter.listeners.yaml @@ -28,9 +28,8 @@ routeConfigName: extension-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: extension-listener perConnectionBufferLimitBytes: 32768 statPrefix: mock-extension-inserted-prefix diff --git a/internal/xds/translator/testdata/out/extension-xds-ir/http-route-extension-filter.routes.yaml b/internal/xds/translator/testdata/out/extension-xds-ir/http-route-extension-filter.routes.yaml index 243339164de3..b259daf0c76b 100644 --- a/internal/xds/translator/testdata/out/extension-xds-ir/http-route-extension-filter.routes.yaml +++ b/internal/xds/translator/testdata/out/extension-xds-ir/http-route-extension-filter.routes.yaml @@ -29,3 +29,5 @@ value: foo.example.io/v1alpha1 route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/extension-xds-ir/http-route.listeners.yaml b/internal/xds/translator/testdata/out/extension-xds-ir/http-route.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/extension-xds-ir/http-route.listeners.yaml +++ b/internal/xds/translator/testdata/out/extension-xds-ir/http-route.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/extension-xds-ir/http-route.routes.yaml b/internal/xds/translator/testdata/out/extension-xds-ir/http-route.routes.yaml index 738eb0a2d2aa..7030f6f4cd7d 100644 --- a/internal/xds/translator/testdata/out/extension-xds-ir/http-route.routes.yaml +++ b/internal/xds/translator/testdata/out/extension-xds-ir/http-route.routes.yaml @@ -21,3 +21,5 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/accesslog.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/accesslog.listeners.yaml index a3bf0b5bc886..e6d5535eb15b 100644 --- a/internal/xds/translator/testdata/out/xds-ir/accesslog.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/accesslog.listeners.yaml @@ -138,8 +138,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/basic-auth.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/basic-auth.listeners.yaml index 11ecc856c2db..3b72788ce31f 100644 --- a/internal/xds/translator/testdata/out/xds-ir/basic-auth.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/basic-auth.listeners.yaml @@ -34,8 +34,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/basic-auth.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/basic-auth.routes.yaml index 6fdefbdf7c16..f87be11474a8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/basic-auth.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/basic-auth.routes.yaml @@ -10,6 +10,8 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket typedPerFilterConfig: envoy.filters.http.basic_auth_first-route: '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig diff --git a/internal/xds/translator/testdata/out/xds-ir/circuit-breaker.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/circuit-breaker.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/circuit-breaker.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/circuit-breaker.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/circuit-breaker.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/circuit-breaker.routes.yaml index 2734c7cc42a0..0b5b4bee7bbb 100644 --- a/internal/xds/translator/testdata/out/xds-ir/circuit-breaker.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/circuit-breaker.routes.yaml @@ -10,3 +10,5 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/client-ip-detection.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/client-ip-detection.listeners.yaml index 102b968f145b..10ee71d87bc7 100755 --- a/internal/xds/translator/testdata/out/xds-ir/client-ip-detection.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/client-ip-detection.listeners.yaml @@ -26,10 +26,9 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true xffNumTrustedHops: 2 + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 - address: @@ -66,9 +65,8 @@ routeConfigName: second-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: false + drainType: MODIFY_ONLY name: second-listener perConnectionBufferLimitBytes: 32768 - address: @@ -107,8 +105,7 @@ routeConfigName: third-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: false + drainType: MODIFY_ONLY name: third-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/client-ip-detection.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/client-ip-detection.routes.yaml index 724f80699c7d..12a38a14ef88 100755 --- a/internal/xds/translator/testdata/out/xds-ir/client-ip-detection.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/client-ip-detection.routes.yaml @@ -10,6 +10,8 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket - ignorePortInHostMatching: true name: second-listener virtualHosts: @@ -22,6 +24,8 @@ name: second-route route: cluster: second-route-dest + upgradeConfigs: + - upgradeType: websocket - ignorePortInHostMatching: true name: third-listener virtualHosts: @@ -34,3 +38,5 @@ name: third-route route: cluster: third-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/client-timeout.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/client-timeout.listeners.yaml index e6e99e720bf1..a84c776ac2ef 100644 --- a/internal/xds/translator/testdata/out/xds-ir/client-timeout.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/client-timeout.listeners.yaml @@ -29,8 +29,7 @@ requestTimeout: 5s serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/client-timeout.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/client-timeout.routes.yaml index 2734c7cc42a0..0b5b4bee7bbb 100644 --- a/internal/xds/translator/testdata/out/xds-ir/client-timeout.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/client-timeout.routes.yaml @@ -10,3 +10,5 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/cors.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/cors.listeners.yaml index b9858e6777a0..e575107a6c79 100644 --- a/internal/xds/translator/testdata/out/xds-ir/cors.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/cors.listeners.yaml @@ -31,8 +31,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/cors.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/cors.routes.yaml index fc0fdea378e2..f776257868c0 100644 --- a/internal/xds/translator/testdata/out/xds-ir/cors.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/cors.routes.yaml @@ -10,6 +10,8 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket typedPerFilterConfig: envoy.filters.http.cors: '@type': type.googleapis.com/envoy.extensions.filters.http.cors.v3.CorsPolicy diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-auth.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-auth.listeners.yaml index ec6f73b212ff..b310689402b3 100755 --- a/internal/xds/translator/testdata/out/xds-ir/ext-auth.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/ext-auth.listeners.yaml @@ -55,8 +55,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/ext-auth.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/ext-auth.routes.yaml index d8aae14302af..0b039af3da3b 100755 --- a/internal/xds/translator/testdata/out/xds-ir/ext-auth.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/ext-auth.routes.yaml @@ -10,6 +10,8 @@ name: httproute/default/httproute-1/rule/0/match/0/www_example_com route: cluster: httproute/default/httproute-1/rule/0 + upgradeConfigs: + - upgradeType: websocket typedPerFilterConfig: envoy.filters.http.ext_authz_httproute/default/httproute-1/rule/0/match/0/www_example_com: '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig @@ -19,6 +21,8 @@ name: httproute/default/httproute-2/rule/0/match/0/www_example_com route: cluster: httproute/default/httproute-2/rule/0 + upgradeConfigs: + - upgradeType: websocket typedPerFilterConfig: envoy.filters.http.ext_authz_httproute/default/httproute-2/rule/0/match/0/www_example_com: '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig diff --git a/internal/xds/translator/testdata/out/xds-ir/fault-injection.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/fault-injection.listeners.yaml index 7586adc78b07..71338b607131 100755 --- a/internal/xds/translator/testdata/out/xds-ir/fault-injection.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/fault-injection.listeners.yaml @@ -31,8 +31,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/fault-injection.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/fault-injection.routes.yaml index bed4a696e0a1..1f093f5a0c24 100755 --- a/internal/xds/translator/testdata/out/xds-ir/fault-injection.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/fault-injection.routes.yaml @@ -10,6 +10,8 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket typedPerFilterConfig: envoy.filters.http.fault: '@type': type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault @@ -23,6 +25,8 @@ name: second-route route: cluster: second-route-dest + upgradeConfigs: + - upgradeType: websocket typedPerFilterConfig: envoy.filters.http.fault: '@type': type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault @@ -36,6 +40,8 @@ name: third-route route: cluster: third-route-dest + upgradeConfigs: + - upgradeType: websocket typedPerFilterConfig: envoy.filters.http.fault: '@type': type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault @@ -54,6 +60,8 @@ name: fourth-route route: cluster: fourth-route-dest + upgradeConfigs: + - upgradeType: websocket typedPerFilterConfig: envoy.filters.http.fault: '@type': type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault @@ -72,3 +80,5 @@ name: fifth-route route: cluster: fifth-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/health-check.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/health-check.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/health-check.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/health-check.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 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 79c66f882040..de4249178e46 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 @@ -10,18 +10,26 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket - match: prefix: / name: second-route route: cluster: second-route-dest + upgradeConfigs: + - upgradeType: websocket - match: prefix: / name: third-route route: cluster: third-route-dest + upgradeConfigs: + - upgradeType: websocket - match: prefix: / name: fourth-route route: cluster: fourth-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-direct-response.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-direct-response.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-direct-response.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-direct-response.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-dns-cluster.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-dns-cluster.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-dns-cluster.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-dns-cluster.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-dns-cluster.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-dns-cluster.routes.yaml index 7b23a59dfeeb..c27e2ea57790 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-dns-cluster.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-dns-cluster.routes.yaml @@ -14,3 +14,5 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-mirror.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-mirror.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-mirror.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-mirror.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-mirror.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-mirror.routes.yaml index c5f6e70b2546..c5a187d2c266 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-mirror.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-mirror.routes.yaml @@ -10,3 +10,5 @@ name: mirror-route route: cluster: route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-matches.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-matches.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-matches.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-matches.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-matches.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-matches.routes.yaml index 2db7970b38af..25584aa3a911 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-matches.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-matches.routes.yaml @@ -14,11 +14,15 @@ name: envoy-gateway/httproute-2/rule/0/match/0/example.com route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket - match: pathSeparatedPrefix: /v1/example name: envoy-gateway/httproute-3/rule/0/match/0/example.com route: cluster: second-route-dest + upgradeConfigs: + - upgradeType: websocket - domains: - example.net name: first-listener/example_net @@ -32,11 +36,15 @@ name: envoy-gateway/httproute-4/rule/0/match/0/example.net route: cluster: third-route-dest + upgradeConfigs: + - upgradeType: websocket - match: pathSeparatedPrefix: /v1/status name: envoy-gateway/httproute-5/rule/0/match/0/example.net route: cluster: fourth-route-dest + upgradeConfigs: + - upgradeType: websocket - domains: - '*.com' name: first-listener/*_com @@ -46,6 +54,8 @@ name: envoy-gateway/httproute-1/rule/0/match/0/*.com route: cluster: fifth-route-dest + upgradeConfigs: + - upgradeType: websocket - domains: - '*.net' name: first-listener/*_net @@ -55,6 +65,8 @@ name: envoy-gateway/httproute-1/rule/0/match/0/*.net route: cluster: sixth-route-dest + upgradeConfigs: + - upgradeType: websocket - domains: - '*' name: first-listener/* @@ -64,3 +76,5 @@ name: envoy-gateway/httproute-1/rule/0/match/0/* route: cluster: seventh-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-mirrors.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-mirrors.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-mirrors.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-mirrors.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-mirrors.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-mirrors.routes.yaml index 1429b4da64e7..f46cc50eb529 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-mirrors.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-multiple-mirrors.routes.yaml @@ -13,3 +13,5 @@ requestMirrorPolicies: - cluster: mirror-route-dest - cluster: mirror-route-dest1 + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-partial-invalid.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-partial-invalid.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-partial-invalid.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-partial-invalid.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-partial-invalid.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-partial-invalid.routes.yaml index ac7c41d98468..61face5a3a36 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-partial-invalid.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-partial-invalid.routes.yaml @@ -21,6 +21,8 @@ name: valid-route route: cluster: valid-route-dest + upgradeConfigs: + - upgradeType: websocket - match: headers: - name: user @@ -37,3 +39,5 @@ name: invalid-route route: cluster: invalid-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-redirect.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-redirect.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-redirect.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-redirect.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-regex.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-regex.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-regex.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-regex.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-regex.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-regex.routes.yaml index a3c115b6da97..7bc7d162a85c 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-regex.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-regex.routes.yaml @@ -21,3 +21,5 @@ name: regex-route route: cluster: regex-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-request-headers.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-request-headers.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-request-headers.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-request-headers.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 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 3ded1e7105d3..f91a70cb2ee7 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 @@ -32,3 +32,5 @@ - some-header6 route: cluster: request-header-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-headers.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-headers.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-headers.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-headers.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-headers.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-headers.routes.yaml index a57c32ff84ad..b2241a1181c2 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-headers.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-headers.routes.yaml @@ -29,3 +29,5 @@ keepEmptyValue: true route: cluster: response-header-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-remove-headers.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-remove-headers.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-remove-headers.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-remove-headers.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-remove-headers.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-remove-headers.routes.yaml index f8c7a7ff5bb0..b09594aecda2 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-remove-headers.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-response-add-remove-headers.routes.yaml @@ -32,3 +32,5 @@ - some-header6 route: cluster: response-header-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-response-remove-headers.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-response-remove-headers.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-response-remove-headers.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-response-remove-headers.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-response-remove-headers.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-response-remove-headers.routes.yaml index 4052f973e28a..58a4e272090a 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-response-remove-headers.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-response-remove-headers.routes.yaml @@ -13,3 +13,5 @@ - some-header6 route: cluster: response-header-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-root-path-url-prefix.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-root-path-url-prefix.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-root-path-url-prefix.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-root-path-url-prefix.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-fullpath.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-fullpath.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-fullpath.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-fullpath.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-host.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-host.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-host.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-host.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-prefix.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-prefix.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-prefix.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-prefix.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-timeout.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-timeout.clusters.yaml index c8692b816025..869321c6504a 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-timeout.clusters.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-timeout.clusters.yaml @@ -12,3 +12,31 @@ outlierDetection: {} perConnectionBufferLimitBytes: 32768 type: EDS +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: second-route-dest + lbPolicy: LEAST_REQUEST + name: second-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS +- commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: third-route-dest + lbPolicy: LEAST_REQUEST + name: third-route-dest + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-timeout.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-timeout.endpoints.yaml index 3b3f2d09076e..42a346c4041a 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-timeout.endpoints.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-timeout.endpoints.yaml @@ -10,3 +10,27 @@ loadBalancingWeight: 1 locality: region: first-route-dest/backend/0 +- clusterName: second-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50001 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: second-route-dest/backend/0 +- clusterName: third-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50002 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: third-route-dest/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-timeout.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-timeout.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-timeout.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-timeout.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-timeout.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-timeout.routes.yaml index 52a166770bc4..23d2bf4b701b 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-timeout.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-timeout.routes.yaml @@ -14,4 +14,25 @@ name: first-route route: cluster: first-route-dest + idleTimeout: 3600s timeout: 5s + upgradeConfigs: + - upgradeType: websocket + - match: + prefix: / + name: second-route + route: + cluster: second-route-dest + idleTimeout: 4000s + timeout: 4000s + upgradeConfigs: + - upgradeType: websocket + - match: + prefix: / + name: third-route + route: + cluster: third-route-dest + idleTimeout: 0s + timeout: 0s + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend.routes.yaml index 2734c7cc42a0..0b5b4bee7bbb 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-backend.routes.yaml @@ -10,3 +10,5 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-invalid-backend.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-invalid-backend.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-invalid-backend.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-invalid-backend.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-invalid-backend.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-invalid-backend.routes.yaml index 5b56c04dbae1..235dea427290 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-invalid-backend.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-weighted-invalid-backend.routes.yaml @@ -10,6 +10,8 @@ name: first-route route: clusterNotFoundResponseCode: INTERNAL_SERVER_ERROR + upgradeConfigs: + - upgradeType: websocket weightedClusters: clusters: - name: invalid-backend-cluster diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route.routes.yaml index 738eb0a2d2aa..7030f6f4cd7d 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http-route.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http-route.routes.yaml @@ -21,3 +21,5 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http1-preserve-case.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http1-preserve-case.listeners.yaml index 51679103175f..4e9632a690cc 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http1-preserve-case.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http1-preserve-case.listeners.yaml @@ -34,9 +34,8 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 - address: @@ -76,8 +75,7 @@ routeConfigName: second-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: second-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http1-preserve-case.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http1-preserve-case.routes.yaml index d36b9824e31c..ff93cfff360b 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http1-preserve-case.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http1-preserve-case.routes.yaml @@ -10,6 +10,8 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket - ignorePortInHostMatching: true name: second-listener virtualHosts: @@ -22,3 +24,5 @@ name: second-route route: cluster: second-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http1-trailers.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http1-trailers.listeners.yaml index 59592df658ab..085095a8cf60 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http1-trailers.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http1-trailers.listeners.yaml @@ -30,8 +30,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http1-trailers.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http1-trailers.routes.yaml index 2734c7cc42a0..0b5b4bee7bbb 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http1-trailers.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http1-trailers.routes.yaml @@ -10,3 +10,5 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http10.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http10.listeners.yaml index cb4e1c75776f..63e2883ccba5 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http10.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http10.listeners.yaml @@ -31,8 +31,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http10.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http10.routes.yaml index 2734c7cc42a0..0b5b4bee7bbb 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http10.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http10.routes.yaml @@ -10,3 +10,5 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http2-route.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http2-route.listeners.yaml index 299ae39cd94c..15b0ce9f9436 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http2-route.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http2-route.listeners.yaml @@ -37,5 +37,6 @@ serverHeaderTransformation: PASS_THROUGH statPrefix: http useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http2-route.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http2-route.routes.yaml index 59831c3176d3..a32852fcd881 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http2-route.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http2-route.routes.yaml @@ -18,3 +18,5 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/http3.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http3.listeners.yaml index 5c05193ce62c..6f8a9dc42268 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http3.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http3.listeners.yaml @@ -3,6 +3,7 @@ address: 0.0.0.0 portValue: 10443 protocol: UDP + drainType: MODIFY_ONLY filterChains: - filters: - name: envoy.filters.network.http_connection_manager @@ -31,8 +32,6 @@ routeConfigName: envoy-gateway/gateway-1/tls serverHeaderTransformation: PASS_THROUGH statPrefix: https - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true transportSocket: name: envoy.transport_sockets.quic @@ -55,6 +54,7 @@ socketAddress: address: 0.0.0.0 portValue: 10443 + drainType: MODIFY_ONLY filterChains: - filters: - name: envoy.filters.network.http_connection_manager @@ -81,8 +81,6 @@ routeConfigName: envoy-gateway/gateway-1/tls serverHeaderTransformation: PASS_THROUGH statPrefix: https - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true transportSocket: name: envoy.transport_sockets.tls diff --git a/internal/xds/translator/testdata/out/xds-ir/http3.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http3.routes.yaml index d129cf7589d9..0680b361d153 100644 --- a/internal/xds/translator/testdata/out/xds-ir/http3.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/http3.routes.yaml @@ -15,3 +15,5 @@ value: h3=":10443"; ma=86400 route: cluster: httproute/default/httproute-1/rule/0 + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-without-value.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-without-value.listeners.yaml index d0e88f02b413..4347e1ff749c 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-without-value.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-without-value.listeners.yaml @@ -2,6 +2,7 @@ socketAddress: address: 0.0.0.0 portValue: 10080 + drainType: MODIFY_ONLY filterChains: - filters: - name: envoy.filters.network.http_connection_manager @@ -39,8 +40,6 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: https - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true transportSocket: name: envoy.transport_sockets.tls diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-without-value.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-without-value.routes.yaml index dc48be196468..4a412b3576a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-without-value.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-add-op-without-value.routes.yaml @@ -14,3 +14,5 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-invalid-patch.envoypatchpolicies.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-invalid-patch.envoypatchpolicies.yaml index 8d9f6918bd1e..dee45a3b4441 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-invalid-patch.envoypatchpolicies.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-invalid-patch.envoypatchpolicies.yaml @@ -3,8 +3,8 @@ status: conditions: - lastTransitionTime: null - message: 'unable to unmarshal xds resource {"name":"first-listener","address":{"socket_address":{"address":"0.0.0.0","port_value":10080}},"default_filter_chain":{"filters":[{"name":"envoy.filters.network.http_connection_manager","typed_config":{"@type":"type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager","stat_prefix":"http","rds":{"config_source":{"ads":{},"resource_api_version":"V3"},"route_config_name":"first-listener"},"http_filters":[{"name":"envoy.filters.http.router","typed_config":{"@type":"type.googleapis.com/envoy.extensions.filters.http.router.v3.Router","suppress_envoy_headers":true}}],"common_http_protocol_options":{"headers_with_underscores_action":"REJECT_REQUEST"},"http2_protocol_options":{"max_concurrent_streams":100,"initial_stream_window_size":65536,"initial_connection_window_size":1048576},"server_header_transformation":"PASS_THROUGH","use_remote_address":true,"upgrade_configs":[{"upgrade_type":"websocket"}],"normalize_path":true,"merge_slashes":true,"path_with_escaped_slashes_action":"UNESCAPE_AND_REDIRECT"}}]},"per_connection_buffer_limit_bytes":32768,"this":{"path":{"never":{"existed":{"name":"envoy.filters.http.ratelimit","typed_config":{"@type":"type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit","domain":"eg-ratelimit","failure_mode_deny":true,"rate_limit_service":{"grpc_service":{"envoy_grpc":{"cluster_name":"rate-limit-cluster"}},"transport_api_version":"V3"},"timeout":"1s"}}}}}}, - err:proto: (line 1:1099): unknown field "this"' + message: 'unable to unmarshal xds resource {"name":"first-listener","address":{"socket_address":{"address":"0.0.0.0","port_value":10080}},"default_filter_chain":{"filters":[{"name":"envoy.filters.network.http_connection_manager","typed_config":{"@type":"type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager","stat_prefix":"http","rds":{"config_source":{"ads":{},"resource_api_version":"V3"},"route_config_name":"first-listener"},"http_filters":[{"name":"envoy.filters.http.router","typed_config":{"@type":"type.googleapis.com/envoy.extensions.filters.http.router.v3.Router","suppress_envoy_headers":true}}],"common_http_protocol_options":{"headers_with_underscores_action":"REJECT_REQUEST"},"http2_protocol_options":{"max_concurrent_streams":100,"initial_stream_window_size":65536,"initial_connection_window_size":1048576},"server_header_transformation":"PASS_THROUGH","use_remote_address":true,"normalize_path":true,"merge_slashes":true,"path_with_escaped_slashes_action":"UNESCAPE_AND_REDIRECT"}}]},"per_connection_buffer_limit_bytes":32768,"drain_type":"MODIFY_ONLY","this":{"path":{"never":{"existed":{"name":"envoy.filters.http.ratelimit","typed_config":{"@type":"type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit","domain":"eg-ratelimit","failure_mode_deny":true,"rate_limit_service":{"grpc_service":{"envoy_grpc":{"cluster_name":"rate-limit-cluster"}},"transport_api_version":"V3"},"timeout":"1s"}}}}}}, + err:proto: (line 1:1077): unknown field "this"' reason: Invalid status: "False" type: Programmed diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-invalid-patch.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-invalid-patch.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-invalid-patch.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-invalid-patch.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-invalid-patch.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-invalid-patch.routes.yaml index dc48be196468..4a412b3576a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-invalid-patch.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-invalid-patch.routes.yaml @@ -14,3 +14,5 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-missing-resource.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-missing-resource.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-missing-resource.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-missing-resource.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-missing-resource.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-missing-resource.routes.yaml index dc48be196468..4a412b3576a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-missing-resource.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-missing-resource.routes.yaml @@ -14,3 +14,5 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-move-op-with-value.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-move-op-with-value.listeners.yaml index d0e88f02b413..4347e1ff749c 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-move-op-with-value.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-move-op-with-value.listeners.yaml @@ -2,6 +2,7 @@ socketAddress: address: 0.0.0.0 portValue: 10080 + drainType: MODIFY_ONLY filterChains: - filters: - name: envoy.filters.network.http_connection_manager @@ -39,8 +40,6 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: https - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true transportSocket: name: envoy.transport_sockets.tls diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-move-op-with-value.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-move-op-with-value.routes.yaml index dc48be196468..4a412b3576a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jsonpatch-move-op-with-value.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch-move-op-with-value.routes.yaml @@ -14,3 +14,5 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch.listeners.yaml index d0e88f02b413..4347e1ff749c 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jsonpatch.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch.listeners.yaml @@ -2,6 +2,7 @@ socketAddress: address: 0.0.0.0 portValue: 10080 + drainType: MODIFY_ONLY filterChains: - filters: - name: envoy.filters.network.http_connection_manager @@ -39,8 +40,6 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: https - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true transportSocket: name: envoy.transport_sockets.tls diff --git a/internal/xds/translator/testdata/out/xds-ir/jsonpatch.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jsonpatch.routes.yaml index fae73436c2f5..3f4a7333a605 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jsonpatch.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jsonpatch.routes.yaml @@ -17,3 +17,5 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-custom-extractor.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-custom-extractor.listeners.yaml index b8a88fd79378..25b3516557bc 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-custom-extractor.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-custom-extractor.listeners.yaml @@ -56,8 +56,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-custom-extractor.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-custom-extractor.routes.yaml index c73bec09093d..321ecc1ced2f 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-custom-extractor.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-custom-extractor.routes.yaml @@ -10,6 +10,8 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket typedPerFilterConfig: envoy.filters.http.jwt_authn: '@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.listeners.yaml index df761c63a077..d502c744f91b 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.listeners.yaml @@ -44,6 +44,7 @@ headerName: one-route-example2-key1 - claimName: name headerName: one-route-example2-key2 + clearRouteCache: true forward: true issuer: https://www.two.example.com payloadInMetadata: https://www.two.example.com @@ -112,8 +113,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.routes.yaml index 630157c4b40e..5cd81b5d475c 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-multi-provider.routes.yaml @@ -10,6 +10,8 @@ name: first-route-www.test.com route: cluster: first-route-www.test.com-dest + upgradeConfigs: + - upgradeType: websocket typedPerFilterConfig: envoy.filters.http.jwt_authn: '@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig @@ -19,6 +21,8 @@ name: second-route-www.test.com route: cluster: second-route-www.test.com-dest + upgradeConfigs: + - upgradeType: websocket typedPerFilterConfig: envoy.filters.http.jwt_authn: '@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.listeners.yaml index e16c2673208b..d4d44caa7a88 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.listeners.yaml @@ -90,8 +90,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.routes.yaml index 2078809a6948..7c52b6de16d9 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-multi-route-single-provider.routes.yaml @@ -10,6 +10,8 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket typedPerFilterConfig: envoy.filters.http.jwt_authn: '@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig @@ -19,6 +21,8 @@ name: second-route route: cluster: second-route-dest + upgradeConfigs: + - upgradeType: websocket typedPerFilterConfig: envoy.filters.http.jwt_authn: '@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.listeners.yaml index 72c2f332e637..acb5affc32cd 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.listeners.yaml @@ -59,8 +59,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.routes.yaml index 019897bf021d..0e312fd928c0 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-ratelimit.routes.yaml @@ -23,6 +23,8 @@ - name: x-user-id stringMatch: exact: one + upgradeConfigs: + - upgradeType: websocket typedPerFilterConfig: envoy.filters.http.jwt_authn: '@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig @@ -40,6 +42,8 @@ - requestHeaders: descriptorKey: rule-0-match-0 headerName: x-user-id + upgradeConfigs: + - upgradeType: websocket - match: path: test name: third-route @@ -53,3 +57,5 @@ - genericKey: descriptorKey: rule-0-match--1 descriptorValue: rule-0-match--1 + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.listeners.yaml index 945509a05224..1dd635a7aace 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.listeners.yaml @@ -49,8 +49,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.routes.yaml index c73bec09093d..321ecc1ced2f 100644 --- a/internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/jwt-single-route-single-match.routes.yaml @@ -10,6 +10,8 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket typedPerFilterConfig: envoy.filters.http.jwt_authn: '@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.PerRouteConfig diff --git a/internal/xds/translator/testdata/out/xds-ir/listener-proxy-protocol.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/listener-proxy-protocol.listeners.yaml index 4df723a03072..015275e8c6ea 100644 --- a/internal/xds/translator/testdata/out/xds-ir/listener-proxy-protocol.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/listener-proxy-protocol.listeners.yaml @@ -2,6 +2,7 @@ socketAddress: address: 0.0.0.0 portValue: 10080 + drainType: MODIFY_ONLY filterChains: - filterChainMatch: serverNames: @@ -31,8 +32,6 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: https - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true transportSocket: name: envoy.transport_sockets.tls diff --git a/internal/xds/translator/testdata/out/xds-ir/listener-proxy-protocol.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/listener-proxy-protocol.routes.yaml index 2734c7cc42a0..0b5b4bee7bbb 100644 --- a/internal/xds/translator/testdata/out/xds-ir/listener-proxy-protocol.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/listener-proxy-protocol.routes.yaml @@ -10,3 +10,5 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.listeners.yaml index 203f36be5a5b..df60e562394e 100644 --- a/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.listeners.yaml @@ -28,9 +28,8 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 socketOptions: @@ -68,9 +67,8 @@ routeConfigName: second-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: second-listener perConnectionBufferLimitBytes: 32768 socketOptions: @@ -94,6 +92,7 @@ socketAddress: address: 0.0.0.0 portValue: 10082 + drainType: MODIFY_ONLY filterChains: - filterChainMatch: serverNames: @@ -119,6 +118,7 @@ socketAddress: address: 0.0.0.0 portValue: 10083 + drainType: MODIFY_ONLY filterChains: - filters: - name: envoy.filters.network.tcp_proxy diff --git a/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.routes.yaml index d36b9824e31c..ff93cfff360b 100644 --- a/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/listener-tcp-keepalive.routes.yaml @@ -10,6 +10,8 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket - ignorePortInHostMatching: true name: second-listener virtualHosts: @@ -22,3 +24,5 @@ name: second-route route: cluster: second-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/load-balancer.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/load-balancer.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/load-balancer.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/load-balancer.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/load-balancer.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/load-balancer.routes.yaml index d2a33c648492..49db596538b0 100644 --- a/internal/xds/translator/testdata/out/xds-ir/load-balancer.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/load-balancer.routes.yaml @@ -10,16 +10,22 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket - match: prefix: / name: second-route route: cluster: second-route-dest + upgradeConfigs: + - upgradeType: websocket - match: prefix: / name: third-route route: cluster: third-route-dest + upgradeConfigs: + - upgradeType: websocket - match: prefix: / name: fourth-route @@ -28,13 +34,19 @@ hashPolicy: - connectionProperties: sourceIp: true + upgradeConfigs: + - upgradeType: websocket - match: prefix: / name: fifth-route route: cluster: fifth-route-dest + upgradeConfigs: + - upgradeType: websocket - match: prefix: / name: sixth-route route: cluster: sixth-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/local-ratelimit.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/local-ratelimit.listeners.yaml index 3841aa65768a..1634c60872f9 100644 --- a/internal/xds/translator/testdata/out/xds-ir/local-ratelimit.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/local-ratelimit.listeners.yaml @@ -32,8 +32,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/local-ratelimit.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/local-ratelimit.routes.yaml index 3f28acd5a153..9b5dd3f7d03e 100644 --- a/internal/xds/translator/testdata/out/xds-ir/local-ratelimit.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/local-ratelimit.routes.yaml @@ -28,6 +28,8 @@ - name: x-org-id stringMatch: exact: foo + upgradeConfigs: + - upgradeType: websocket typedPerFilterConfig: envoy.filters.http.local_ratelimit: '@type': type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit @@ -95,6 +97,8 @@ exact: bar - maskedRemoteAddress: v4PrefixMaskLen: 16 + upgradeConfigs: + - upgradeType: websocket typedPerFilterConfig: envoy.filters.http.local_ratelimit: '@type': type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit @@ -136,6 +140,8 @@ name: third-route-ratelimit-no-rule route: cluster: third-route-dest + upgradeConfigs: + - upgradeType: websocket typedPerFilterConfig: envoy.filters.http.local_ratelimit: '@type': type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit diff --git a/internal/xds/translator/testdata/out/xds-ir/metrics-virtual-host.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/metrics-virtual-host.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/metrics-virtual-host.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/metrics-virtual-host.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/metrics-virtual-host.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/metrics-virtual-host.routes.yaml index 0d2cb8567b8d..41594a227db0 100644 --- a/internal/xds/translator/testdata/out/xds-ir/metrics-virtual-host.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/metrics-virtual-host.routes.yaml @@ -10,6 +10,8 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket virtualClusters: - headers: - name: :authority diff --git a/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port.listeners.yaml index 102fe74e0704..c04233837598 100644 --- a/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port.listeners.yaml @@ -28,9 +28,8 @@ routeConfigName: third-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY filterChains: - filterChainMatch: serverNames: @@ -60,8 +59,6 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: https - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true transportSocket: name: envoy.transport_sockets.tls @@ -104,8 +101,6 @@ routeConfigName: second-listener serverHeaderTransformation: PASS_THROUGH statPrefix: https - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true transportSocket: name: envoy.transport_sockets.tls diff --git a/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port.routes.yaml index cd8f24c1194b..c94d2c09f700 100644 --- a/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/multiple-listeners-same-port.routes.yaml @@ -10,6 +10,8 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket - ignorePortInHostMatching: true name: second-listener virtualHosts: @@ -22,6 +24,8 @@ name: second-route route: cluster: second-route-dest + upgradeConfigs: + - upgradeType: websocket - ignorePortInHostMatching: true name: third-listener virtualHosts: @@ -34,6 +38,8 @@ name: third-route route: cluster: third-route-dest + upgradeConfigs: + - upgradeType: websocket - domains: - '*' name: fourth-listener/* @@ -43,3 +49,5 @@ name: fourth-route route: cluster: fourth-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/multiple-simple-tcp-route-same-port.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/multiple-simple-tcp-route-same-port.listeners.yaml index 663e7b989088..33e4073d897a 100644 --- a/internal/xds/translator/testdata/out/xds-ir/multiple-simple-tcp-route-same-port.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/multiple-simple-tcp-route-same-port.listeners.yaml @@ -2,6 +2,7 @@ socketAddress: address: 0.0.0.0 portValue: 10080 + drainType: MODIFY_ONLY filterChains: - filters: - name: envoy.filters.network.tcp_proxy diff --git a/internal/xds/translator/testdata/out/xds-ir/mutual-tls.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/mutual-tls.listeners.yaml index 4726fb8aa0e8..918ac04ae55c 100644 --- a/internal/xds/translator/testdata/out/xds-ir/mutual-tls.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/mutual-tls.listeners.yaml @@ -2,6 +2,7 @@ socketAddress: address: 0.0.0.0 portValue: 10080 + drainType: MODIFY_ONLY filterChains: - filters: - name: envoy.filters.network.http_connection_manager @@ -28,8 +29,6 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: https - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true transportSocket: name: envoy.transport_sockets.tls diff --git a/internal/xds/translator/testdata/out/xds-ir/mutual-tls.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/mutual-tls.routes.yaml index 2734c7cc42a0..0b5b4bee7bbb 100644 --- a/internal/xds/translator/testdata/out/xds-ir/mutual-tls.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/mutual-tls.routes.yaml @@ -10,3 +10,5 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/oidc.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/oidc.listeners.yaml index abadd4dd23c9..73388e331ed8 100644 --- a/internal/xds/translator/testdata/out/xds-ir/oidc.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/oidc.listeners.yaml @@ -69,11 +69,11 @@ credentials: clientId: client.oauth.bar.com cookieNames: - bearerToken: BearerToken-B0A1B740 - idToken: IdToken-B0A1B740 - oauthExpires: OauthExpires-B0A1B740 - oauthHmac: OauthHMAC-B0A1B740 - refreshToken: RefreshToken-B0A1B740 + bearerToken: BearerToken-5f93c2e4 + idToken: IdToken-5f93c2e4 + oauthExpires: OauthExpires-5f93c2e4 + oauthHmac: OauthHMAC-5f93c2e4 + refreshToken: RefreshToken-5f93c2e4 hmacSecret: name: second-route/oauth2/hmac_secret sdsConfig: @@ -110,8 +110,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/oidc.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/oidc.routes.yaml index f4ba1044899d..a093d6967ac9 100644 --- a/internal/xds/translator/testdata/out/xds-ir/oidc.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/oidc.routes.yaml @@ -10,6 +10,8 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket typedPerFilterConfig: envoy.filters.http.oauth2_first-route: '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig @@ -19,6 +21,8 @@ name: second-route route: cluster: second-route-dest + upgradeConfigs: + - upgradeType: websocket typedPerFilterConfig: envoy.filters.http.oauth2_second-route: '@type': type.googleapis.com/envoy.config.route.v3.FilterConfig diff --git a/internal/xds/translator/testdata/out/xds-ir/path-settings.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/path-settings.listeners.yaml index 88def256e956..28a815e39e73 100644 --- a/internal/xds/translator/testdata/out/xds-ir/path-settings.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/path-settings.listeners.yaml @@ -27,8 +27,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/path-settings.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/path-settings.routes.yaml index 2734c7cc42a0..0b5b4bee7bbb 100644 --- a/internal/xds/translator/testdata/out/xds-ir/path-settings.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/path-settings.routes.yaml @@ -10,3 +10,5 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/proxy-protocol-upstream.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/proxy-protocol-upstream.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/proxy-protocol-upstream.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/proxy-protocol-upstream.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/proxy-protocol-upstream.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/proxy-protocol-upstream.routes.yaml index 2734c7cc42a0..0b5b4bee7bbb 100644 --- a/internal/xds/translator/testdata/out/xds-ir/proxy-protocol-upstream.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/proxy-protocol-upstream.routes.yaml @@ -10,3 +10,5 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/ratelimit-custom-domain.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/ratelimit-custom-domain.listeners.yaml index be0d4a05bfd0..d6f261b7cd53 100644 --- a/internal/xds/translator/testdata/out/xds-ir/ratelimit-custom-domain.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/ratelimit-custom-domain.listeners.yaml @@ -38,8 +38,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/ratelimit-custom-domain.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/ratelimit-custom-domain.routes.yaml index 8146d71a2263..479c2cd143c7 100644 --- a/internal/xds/translator/testdata/out/xds-ir/ratelimit-custom-domain.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/ratelimit-custom-domain.routes.yaml @@ -23,6 +23,8 @@ - name: x-user-id stringMatch: exact: one + upgradeConfigs: + - upgradeType: websocket - match: path: example name: second-route @@ -36,6 +38,8 @@ - requestHeaders: descriptorKey: rule-0-match-0 headerName: x-user-id + upgradeConfigs: + - upgradeType: websocket - match: path: test name: third-route @@ -49,3 +53,5 @@ - genericKey: descriptorKey: rule-0-match--1 descriptorValue: rule-0-match--1 + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/ratelimit-sourceip.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/ratelimit-sourceip.listeners.yaml index be0d4a05bfd0..d6f261b7cd53 100644 --- a/internal/xds/translator/testdata/out/xds-ir/ratelimit-sourceip.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/ratelimit-sourceip.listeners.yaml @@ -38,8 +38,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/ratelimit-sourceip.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/ratelimit-sourceip.routes.yaml index cb60f39a5dba..a82f9d5c4591 100644 --- a/internal/xds/translator/testdata/out/xds-ir/ratelimit-sourceip.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/ratelimit-sourceip.routes.yaml @@ -17,6 +17,8 @@ descriptorValue: first-route - maskedRemoteAddress: v4PrefixMaskLen: 16 + upgradeConfigs: + - upgradeType: websocket - match: path: example name: second-route @@ -29,6 +31,8 @@ descriptorValue: second-route - maskedRemoteAddress: v4PrefixMaskLen: 24 + upgradeConfigs: + - upgradeType: websocket - match: path: test name: third-route @@ -42,6 +46,8 @@ - genericKey: descriptorKey: rule-0-match--1 descriptorValue: rule-0-match--1 + upgradeConfigs: + - upgradeType: websocket - match: path: distinct name: fourth-route @@ -55,3 +61,5 @@ - maskedRemoteAddress: v4PrefixMaskLen: 16 - remoteAddress: {} + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/ratelimit.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/ratelimit.listeners.yaml index be0d4a05bfd0..d6f261b7cd53 100644 --- a/internal/xds/translator/testdata/out/xds-ir/ratelimit.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/ratelimit.listeners.yaml @@ -38,8 +38,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/ratelimit.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/ratelimit.routes.yaml index 8146d71a2263..479c2cd143c7 100644 --- a/internal/xds/translator/testdata/out/xds-ir/ratelimit.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/ratelimit.routes.yaml @@ -23,6 +23,8 @@ - name: x-user-id stringMatch: exact: one + upgradeConfigs: + - upgradeType: websocket - match: path: example name: second-route @@ -36,6 +38,8 @@ - requestHeaders: descriptorKey: rule-0-match-0 headerName: x-user-id + upgradeConfigs: + - upgradeType: websocket - match: path: test name: third-route @@ -49,3 +53,5 @@ - genericKey: descriptorKey: rule-0-match--1 descriptorValue: rule-0-match--1 + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/retry-partial-invalid.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/retry-partial-invalid.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/retry-partial-invalid.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/retry-partial-invalid.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/retry-partial-invalid.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/retry-partial-invalid.routes.yaml index e71f0c41be5c..e1b4ffe7bf1d 100644 --- a/internal/xds/translator/testdata/out/xds-ir/retry-partial-invalid.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/retry-partial-invalid.routes.yaml @@ -20,6 +20,8 @@ baseInterval: 0.100s maxInterval: 10s retryOn: connect-failure,retriable-status-codes + upgradeConfigs: + - upgradeType: websocket - domains: - foo name: first-listener/foo @@ -34,6 +36,8 @@ retriableStatusCodes: - 503 retryOn: connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes + upgradeConfigs: + - upgradeType: websocket - domains: - bar name: first-listener/bar diff --git a/internal/xds/translator/testdata/out/xds-ir/simple-tls.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/simple-tls.listeners.yaml index 3fd6384f903e..ab0a9c44248d 100644 --- a/internal/xds/translator/testdata/out/xds-ir/simple-tls.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/simple-tls.listeners.yaml @@ -2,6 +2,7 @@ socketAddress: address: 0.0.0.0 portValue: 10080 + drainType: MODIFY_ONLY filterChains: - filters: - name: envoy.filters.network.http_connection_manager @@ -28,8 +29,6 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: https - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true transportSocket: name: envoy.transport_sockets.tls diff --git a/internal/xds/translator/testdata/out/xds-ir/simple-tls.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/simple-tls.routes.yaml index 2734c7cc42a0..0b5b4bee7bbb 100644 --- a/internal/xds/translator/testdata/out/xds-ir/simple-tls.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/simple-tls.routes.yaml @@ -10,3 +10,5 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.listeners.yaml index 9c68dc1ab546..383c56abb27c 100644 --- a/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.listeners.yaml @@ -2,6 +2,7 @@ socketAddress: address: 0.0.0.0 portValue: 10080 + drainType: MODIFY_ONLY filterChains: - filterChainMatch: serverNames: @@ -30,8 +31,6 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: https - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true transportSocket: name: envoy.transport_sockets.tls diff --git a/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.routes.yaml index 2734c7cc42a0..0b5b4bee7bbb 100644 --- a/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/suppress-envoy-headers.routes.yaml @@ -10,3 +10,5 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/tcp-route-complex.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/tcp-route-complex.listeners.yaml index fb16f3e53ae1..0c343d46e191 100644 --- a/internal/xds/translator/testdata/out/xds-ir/tcp-route-complex.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/tcp-route-complex.listeners.yaml @@ -2,6 +2,7 @@ socketAddress: address: 0.0.0.0 portValue: 10080 + drainType: MODIFY_ONLY filterChains: - filterChainMatch: serverNames: diff --git a/internal/xds/translator/testdata/out/xds-ir/tcp-route-simple.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/tcp-route-simple.listeners.yaml index ee24bc19f558..7fb5696df18d 100644 --- a/internal/xds/translator/testdata/out/xds-ir/tcp-route-simple.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/tcp-route-simple.listeners.yaml @@ -2,6 +2,7 @@ socketAddress: address: 0.0.0.0 portValue: 10080 + drainType: MODIFY_ONLY filterChains: - filters: - name: envoy.filters.network.tcp_proxy diff --git a/internal/xds/translator/testdata/out/xds-ir/tcp-route-tls-terminate.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/tcp-route-tls-terminate.listeners.yaml index cb355428d860..34bc646e4db3 100644 --- a/internal/xds/translator/testdata/out/xds-ir/tcp-route-tls-terminate.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/tcp-route-tls-terminate.listeners.yaml @@ -2,6 +2,7 @@ socketAddress: address: 0.0.0.0 portValue: 10080 + drainType: MODIFY_ONLY filterChains: - filters: - name: envoy.filters.network.tcp_proxy diff --git a/internal/xds/translator/testdata/out/xds-ir/tcp-route-weighted-backend.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/tcp-route-weighted-backend.listeners.yaml index 75d5b912e49a..74cd0effc0a9 100644 --- a/internal/xds/translator/testdata/out/xds-ir/tcp-route-weighted-backend.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/tcp-route-weighted-backend.listeners.yaml @@ -2,6 +2,7 @@ socketAddress: address: 0.0.0.0 portValue: 10080 + drainType: MODIFY_ONLY filterChains: - filterChainMatch: serverNames: diff --git a/internal/xds/translator/testdata/out/xds-ir/timeout.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/timeout.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/timeout.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/timeout.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/timeout.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/timeout.routes.yaml index 2734c7cc42a0..0b5b4bee7bbb 100644 --- a/internal/xds/translator/testdata/out/xds-ir/timeout.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/timeout.routes.yaml @@ -10,3 +10,5 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/tls-route-passthrough.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/tls-route-passthrough.listeners.yaml index f2f1197f943f..4e0f498aea65 100644 --- a/internal/xds/translator/testdata/out/xds-ir/tls-route-passthrough.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/tls-route-passthrough.listeners.yaml @@ -2,6 +2,7 @@ socketAddress: address: 0.0.0.0 portValue: 10080 + drainType: MODIFY_ONLY filterChains: - filterChainMatch: serverNames: diff --git a/internal/xds/translator/testdata/out/xds-ir/tls-with-ciphers-versions-alpn.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/tls-with-ciphers-versions-alpn.listeners.yaml index a404ab4d9f62..443779305c7e 100644 --- a/internal/xds/translator/testdata/out/xds-ir/tls-with-ciphers-versions-alpn.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/tls-with-ciphers-versions-alpn.listeners.yaml @@ -2,6 +2,7 @@ socketAddress: address: 0.0.0.0 portValue: 10080 + drainType: MODIFY_ONLY filterChains: - filterChainMatch: serverNames: @@ -31,8 +32,6 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: https - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true transportSocket: name: envoy.transport_sockets.tls diff --git a/internal/xds/translator/testdata/out/xds-ir/tls-with-ciphers-versions-alpn.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/tls-with-ciphers-versions-alpn.routes.yaml index 2734c7cc42a0..0b5b4bee7bbb 100644 --- a/internal/xds/translator/testdata/out/xds-ir/tls-with-ciphers-versions-alpn.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/tls-with-ciphers-versions-alpn.routes.yaml @@ -10,3 +10,5 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/internal/xds/translator/testdata/out/xds-ir/tracing.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/tracing.listeners.yaml index e27bb6fec3a1..a69d0bb9e44a 100644 --- a/internal/xds/translator/testdata/out/xds-ir/tracing.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/tracing.listeners.yaml @@ -56,8 +56,7 @@ serviceName: fake-name.fake-ns randomSampling: value: 90 - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/upstream-tcpkeepalive.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/upstream-tcpkeepalive.listeners.yaml index 046589e0fd89..17a4871056a6 100644 --- a/internal/xds/translator/testdata/out/xds-ir/upstream-tcpkeepalive.listeners.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/upstream-tcpkeepalive.listeners.yaml @@ -28,8 +28,7 @@ routeConfigName: first-listener serverHeaderTransformation: PASS_THROUGH statPrefix: http - upgradeConfigs: - - upgradeType: websocket useRemoteAddress: true + drainType: MODIFY_ONLY name: first-listener perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/upstream-tcpkeepalive.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/upstream-tcpkeepalive.routes.yaml index 2734c7cc42a0..0b5b4bee7bbb 100644 --- a/internal/xds/translator/testdata/out/xds-ir/upstream-tcpkeepalive.routes.yaml +++ b/internal/xds/translator/testdata/out/xds-ir/upstream-tcpkeepalive.routes.yaml @@ -10,3 +10,5 @@ name: first-route route: cluster: first-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index d86bfa39c097..7ebe5f166691 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -881,6 +881,7 @@ _Appears in:_ | `concurrency` | _integer_ | false | Concurrency defines the number of worker threads to run. If unset, it defaults to the number of cpuset threads on the platform. | | `extraArgs` | _string array_ | false | ExtraArgs defines additional command line options that are provided to Envoy. More info: https://www.envoyproxy.io/docs/envoy/latest/operations/cli#command-line-options Note: some command line options are used internally(e.g. --log-level) so they cannot be provided here. | | `mergeGateways` | _boolean_ | false | MergeGateways defines if Gateway resources should be merged onto the same Envoy Proxy Infrastructure. Setting this field to true would merge all Gateway Listeners under the parent Gateway Class. This means that the port, protocol and hostname tuple must be unique for every listener. If a duplicate listener is detected, the newer listener (based on timestamp) will be rejected and its status will be updated with a "Accepted=False" condition. | +| `shutdown` | _[ShutdownConfig](#shutdownconfig)_ | false | Shutdown defines configuration for graceful envoy shutdown process. | @@ -1374,7 +1375,8 @@ _Appears in:_ | `issuer` | _string_ | false | Issuer is the principal that issued the JWT and takes the form of a URL or email address. For additional details, see https://tools.ietf.org/html/rfc7519#section-4.1.1 for URL format and https://rfc-editor.org/rfc/rfc5322.html for email format. If not provided, the JWT issuer is not checked. | | `audiences` | _string array_ | false | Audiences is a list of JWT audiences allowed access. For additional details, see https://tools.ietf.org/html/rfc7519#section-4.1.3. If not provided, JWT audiences are not checked. | | `remoteJWKS` | _[RemoteJWKS](#remotejwks)_ | true | RemoteJWKS defines how to fetch and cache JSON Web Key Sets (JWKS) from a remote HTTP/HTTPS endpoint. | -| `claimToHeaders` | _[ClaimToHeader](#claimtoheader) array_ | true | ClaimToHeaders is a list of JWT claims that must be extracted into HTTP request headers For examples, following config: The claim must be of type; string, int, double, bool. Array type claims are not supported | +| `claimToHeaders` | _[ClaimToHeader](#claimtoheader) array_ | false | ClaimToHeaders is a list of JWT claims that must be extracted into HTTP request headers For examples, following config: The claim must be of type; string, int, double, bool. Array type claims are not supported | +| `recomputeRoute` | _boolean_ | false | RecomputeRoute clears the route cache and recalculates the routing decision. This field must be enabled if the headers generated from the claim are used for route matching decisions. If the recomputation selects a new route, features targeting the new matched route will be applied. | | `extractFrom` | _[JWTExtractor](#jwtextractor)_ | false | ExtractFrom defines different ways to extract the JWT token from HTTP request. If empty, it defaults to extract JWT token from the Authorization HTTP request header using Bearer schema or access_token from query parameters. | @@ -1419,6 +1421,7 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | +| `patch` | _[KubernetesPatchSpec](#kubernetespatchspec)_ | false | Patch defines how to perform the patch operation to deployment | | `replicas` | _integer_ | false | Replicas is the number of desired pods. Defaults to 1. | | `strategy` | _[DeploymentStrategy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#deploymentstrategy-v1-apps)_ | false | The deployment strategy to use to replace existing pods with new ones. | | `pod` | _[KubernetesPodSpec](#kubernetespodspec)_ | false | Pod defines the desired specification of pod. | @@ -1443,6 +1446,21 @@ _Appears in:_ | `behavior` | _[HorizontalPodAutoscalerBehavior](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#horizontalpodautoscalerbehavior-v2-autoscaling)_ | false | behavior configures the scaling behavior of the target in both Up and Down directions (scaleUp and scaleDown fields respectively). If not set, the default HPAScalingRules for scale up and scale down are used. See k8s.io.autoscaling.v2.HorizontalPodAutoScalerBehavior. | +#### KubernetesPatchSpec + + + +KubernetesPatchSpec defines how to perform the patch operation + +_Appears in:_ +- [KubernetesDeploymentSpec](#kubernetesdeploymentspec) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `type` | _[MergeType](#mergetype)_ | false | Type is the type of merge operation to perform

By default, StrategicMerge is used as the patch type. | +| `value` | _[JSON](#json)_ | true | Object contains the raw configuration for merged object | + + #### KubernetesPodSpec @@ -1579,6 +1597,8 @@ _Appears in:_ + + #### MetricSinkType _Underlying type:_ _string_ @@ -2272,6 +2292,21 @@ _Appears in:_ +#### ShutdownConfig + + + +ShutdownConfig defines configuration for graceful envoy shutdown process. + +_Appears in:_ +- [EnvoyProxySpec](#envoyproxyspec) + +| Field | Type | Required | Description | +| --- | --- | --- | --- | +| `drainTimeout` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ | false | DrainTimeout defines the graceful drain timeout. This should be less than the pod's terminationGracePeriodSeconds. If unspecified, defaults to 600 seconds. | +| `minDrainDuration` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#duration-v1-meta)_ | false | MinDrainDuration defines the minimum drain duration allowing time for endpoint deprogramming to complete. If unspecified, defaults to 5 seconds. | + + #### SlowStart diff --git a/site/content/en/latest/design/egctl.md b/site/content/en/latest/design/egctl.md index 0f67d99f1005..4bc8876092d0 100644 --- a/site/content/en/latest/design/egctl.md +++ b/site/content/en/latest/design/egctl.md @@ -54,6 +54,6 @@ egctl config envoy-proxy all # Retrieve listener information about proxy configuration from envoy egctl config envoy-proxy listener -# Retrieve information about envoy gateway -egctl config envoy-gateway +# Retrieve the relevant rate limit configuration from the Rate Limit instance +egctl config envoy-ratelimit ``` diff --git a/site/content/en/latest/user/circuit-breaker.md b/site/content/en/latest/user/circuit-breaker.md index 9247d1799556..b870b116a133 100644 --- a/site/content/en/latest/user/circuit-breaker.md +++ b/site/content/en/latest/user/circuit-breaker.md @@ -20,109 +20,17 @@ This instantiated resource can be linked to a [Gateway][], [HTTPRoute][] or [GRP ### Install Envoy Gateway -* Follow the installation step from the [Quickstart Guide](../quickstart) to install Envoy Gateway. There is no need to apply the quickstart manifests. - -### Install the httpbin backend - -* We will use the [Httpbin project] as a backend in order to simulate a degraded service that responds slowly. Install `httpbin` and other Envoy Gateway resources (`GatewayClass`, `Gateway`, `HTTPRoute`) by applying the following manifests: - -```shell -cat <