From 0d1ccae0f546271f25765594d7f7ab79dcc96977 Mon Sep 17 00:00:00 2001 From: Luv Date: Sat, 21 Sep 2024 05:16:17 +0530 Subject: [PATCH 01/13] fix: Reconcile on HTTPRoute labels change (#4279) * added label change predicate Signed-off-by: Luv * added labels predicate for xroute and gw Signed-off-by: Luv * changed predicate to use .Or Signed-off-by: Luv --------- Signed-off-by: Luv Co-authored-by: zirain --- internal/provider/kubernetes/controller.go | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go index a07ca6ab1204..877723fa6821 100644 --- a/internal/provider/kubernetes/controller.go +++ b/internal/provider/kubernetes/controller.go @@ -1080,7 +1080,8 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M // Watch Gateway CRUDs and reconcile affected GatewayClass. gPredicates := []predicate.TypedPredicate[*gwapiv1.Gateway]{ - predicate.TypedGenerationChangedPredicate[*gwapiv1.Gateway]{}, + predicate.Or(predicate.TypedGenerationChangedPredicate[*gwapiv1.Gateway]{}, + predicate.TypedLabelChangedPredicate[*gwapiv1.Gateway]{}), predicate.NewTypedPredicateFuncs(func(gtw *gwapiv1.Gateway) bool { return r.validateGatewayForReconcile(gtw) }), @@ -1104,7 +1105,8 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M // Watch HTTPRoute CRUDs and process affected Gateways. httprPredicates := []predicate.TypedPredicate[*gwapiv1.HTTPRoute]{ - predicate.TypedGenerationChangedPredicate[*gwapiv1.HTTPRoute]{}, + predicate.Or(predicate.TypedGenerationChangedPredicate[*gwapiv1.HTTPRoute]{}, + predicate.TypedLabelChangedPredicate[*gwapiv1.HTTPRoute]{}), } if r.namespaceLabel != nil { httprPredicates = append(httprPredicates, predicate.NewTypedPredicateFuncs(func(hr *gwapiv1.HTTPRoute) bool { @@ -1113,8 +1115,8 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M } if err := c.Watch( source.Kind(mgr.GetCache(), &gwapiv1.HTTPRoute{}, - handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, t *gwapiv1.HTTPRoute) []reconcile.Request { - return r.enqueueClass(ctx, t) + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, route *gwapiv1.HTTPRoute) []reconcile.Request { + return r.enqueueClass(ctx, route) }), httprPredicates...)); err != nil { return err @@ -1125,7 +1127,8 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M // Watch GRPCRoute CRUDs and process affected Gateways. grpcrPredicates := []predicate.TypedPredicate[*gwapiv1.GRPCRoute]{ - predicate.TypedGenerationChangedPredicate[*gwapiv1.GRPCRoute]{}, + predicate.Or(predicate.TypedGenerationChangedPredicate[*gwapiv1.GRPCRoute]{}, + predicate.TypedLabelChangedPredicate[*gwapiv1.GRPCRoute]{}), } if r.namespaceLabel != nil { grpcrPredicates = append(grpcrPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1.GRPCRoute](func(grpc *gwapiv1.GRPCRoute) bool { @@ -1146,7 +1149,8 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M // Watch TLSRoute CRUDs and process affected Gateways. tlsrPredicates := []predicate.TypedPredicate[*gwapiv1a2.TLSRoute]{ - predicate.TypedGenerationChangedPredicate[*gwapiv1a2.TLSRoute]{}, + predicate.Or(predicate.TypedGenerationChangedPredicate[*gwapiv1a2.TLSRoute]{}, + predicate.TypedLabelChangedPredicate[*gwapiv1a2.TLSRoute]{}), } if r.namespaceLabel != nil { tlsrPredicates = append(tlsrPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1a2.TLSRoute](func(route *gwapiv1a2.TLSRoute) bool { @@ -1167,7 +1171,8 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M // Watch UDPRoute CRUDs and process affected Gateways. udprPredicates := []predicate.TypedPredicate[*gwapiv1a2.UDPRoute]{ - predicate.TypedGenerationChangedPredicate[*gwapiv1a2.UDPRoute]{}, + predicate.Or(predicate.TypedGenerationChangedPredicate[*gwapiv1a2.UDPRoute]{}, + predicate.TypedLabelChangedPredicate[*gwapiv1a2.UDPRoute]{}), } if r.namespaceLabel != nil { udprPredicates = append(udprPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1a2.UDPRoute](func(route *gwapiv1a2.UDPRoute) bool { @@ -1188,7 +1193,8 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M // Watch TCPRoute CRUDs and process affected Gateways. tcprPredicates := []predicate.TypedPredicate[*gwapiv1a2.TCPRoute]{ - predicate.TypedGenerationChangedPredicate[*gwapiv1a2.TCPRoute]{}, + predicate.Or(predicate.TypedGenerationChangedPredicate[*gwapiv1a2.TCPRoute]{}, + predicate.TypedLabelChangedPredicate[*gwapiv1a2.TCPRoute]{}), } if r.namespaceLabel != nil { tcprPredicates = append(tcprPredicates, predicate.NewTypedPredicateFuncs[*gwapiv1a2.TCPRoute](func(route *gwapiv1a2.TCPRoute) bool { From 73c223e5ef8e12ad2ddafae0f3a1e5df00aa0373 Mon Sep 17 00:00:00 2001 From: Arko Dasgupta Date: Fri, 20 Sep 2024 18:03:43 -0700 Subject: [PATCH 02/13] fix: handle invalid sectionName in BackendTLSPolicy for Backend (#4296) --- internal/gatewayapi/backendtlspolicy.go | 5 +- .../backendtlspolicy-default-ns.in.yaml | 39 +++++++++++-- .../backendtlspolicy-default-ns.out.yaml | 57 +++++++++++++++++-- 3 files changed, 91 insertions(+), 10 deletions(-) diff --git a/internal/gatewayapi/backendtlspolicy.go b/internal/gatewayapi/backendtlspolicy.go index d58f2789c8b9..a04f93c9c19b 100644 --- a/internal/gatewayapi/backendtlspolicy.go +++ b/internal/gatewayapi/backendtlspolicy.go @@ -145,7 +145,10 @@ func backendTLSTargetMatched(policy gwapiv1a3.BackendTLSPolicy, target gwapiv1a2 target.Kind == currTarget.Kind && backendNamespace == policy.Namespace && target.Name == currTarget.Name { - if currTarget.SectionName != nil && *currTarget.SectionName != *target.SectionName { + if currTarget.SectionName != nil { + if target.SectionName != nil && *currTarget.SectionName == *target.SectionName { + return true + } return false } return true diff --git a/internal/gatewayapi/testdata/backendtlspolicy-default-ns.in.yaml b/internal/gatewayapi/testdata/backendtlspolicy-default-ns.in.yaml index a92a6be60230..5a13fba2fc25 100644 --- a/internal/gatewayapi/testdata/backendtlspolicy-default-ns.in.yaml +++ b/internal/gatewayapi/testdata/backendtlspolicy-default-ns.in.yaml @@ -33,7 +33,11 @@ httpRoutes: - name: http-backend namespace: default port: 8080 - - name: backend-ip-tls + - name: backend-ip-tls-1 + namespace: default + kind: Backend + group: gateway.envoyproxy.io + - name: backend-ip-tls-2 namespace: default kind: Backend group: gateway.envoyproxy.io @@ -140,13 +144,30 @@ backendTLSPolicies: - apiVersion: gateway.networking.k8s.io/v1alpha2 kind: BackendTLSPolicy metadata: - name: policy-btls-backend-ip + name: policy-btls-backend-ip-1 namespace: default spec: targetRefs: - group: gateway.envoyproxy.io kind: Backend - name: backend-ip-tls + name: backend-ip-tls-1 + validation: + caCertificateRefs: + - name: ca-cmap + group: '' + kind: ConfigMap + hostname: ip-backend + - apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + name: policy-btls-backend-ip-2 + namespace: default + spec: + targetRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip-tls-2 + sectionName: 3443 validation: caCertificateRefs: - name: ca-cmap @@ -157,10 +178,20 @@ backends: - apiVersion: gateway.envoyproxy.io/v1alpha1 kind: Backend metadata: - name: backend-ip-tls + name: backend-ip-tls-1 namespace: default spec: endpoints: - ip: address: 2.2.2.2 port: 3443 + - apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-ip-tls-2 + namespace: default + spec: + endpoints: + - ip: + address: 3.3.3.3 + port: 3443 diff --git a/internal/gatewayapi/testdata/backendtlspolicy-default-ns.out.yaml b/internal/gatewayapi/testdata/backendtlspolicy-default-ns.out.yaml index 66dfad1a10aa..d07083f26cfd 100644 --- a/internal/gatewayapi/testdata/backendtlspolicy-default-ns.out.yaml +++ b/internal/gatewayapi/testdata/backendtlspolicy-default-ns.out.yaml @@ -34,13 +34,13 @@ backendTLSPolicies: kind: BackendTLSPolicy metadata: creationTimestamp: null - name: policy-btls-backend-ip + name: policy-btls-backend-ip-1 namespace: default spec: targetRefs: - group: gateway.envoyproxy.io kind: Backend - name: backend-ip-tls + name: backend-ip-tls-1 validation: caCertificateRefs: - group: "" @@ -60,12 +60,32 @@ backendTLSPolicies: status: "True" type: Accepted controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.networking.k8s.io/v1alpha2 + kind: BackendTLSPolicy + metadata: + creationTimestamp: null + name: policy-btls-backend-ip-2 + namespace: default + spec: + targetRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip-tls-2 + sectionName: "3443" + validation: + caCertificateRefs: + - group: "" + kind: ConfigMap + name: ca-cmap + hostname: ip-backend + status: + ancestors: null backends: - apiVersion: gateway.envoyproxy.io/v1alpha1 kind: Backend metadata: creationTimestamp: null - name: backend-ip-tls + name: backend-ip-tls-1 namespace: default spec: endpoints: @@ -79,6 +99,24 @@ backends: reason: Accepted status: "True" type: Accepted +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + creationTimestamp: null + name: backend-ip-tls-2 + namespace: default + spec: + endpoints: + - ip: + address: 3.3.3.3 + port: 3443 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Accepted gateways: - apiVersion: gateway.networking.k8s.io/v1 kind: Gateway @@ -139,7 +177,11 @@ httpRoutes: port: 8080 - group: gateway.envoyproxy.io kind: Backend - name: backend-ip-tls + name: backend-ip-tls-1 + namespace: default + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip-tls-2 namespace: default matches: - path: @@ -221,9 +263,14 @@ xdsIR: tls: caCertificate: certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K - name: policy-btls-backend-ip/default-ca + name: policy-btls-backend-ip-1/default-ca sni: ip-backend weight: 1 + - addressType: IP + endpoints: + - host: 3.3.3.3 + port: 3443 + weight: 1 hostname: '*' isHTTP2: false metadata: From f4ae934ba34090de887f3491623ef83b40d0d660 Mon Sep 17 00:00:00 2001 From: Qiu Yu Date: Fri, 20 Sep 2024 18:10:42 -0700 Subject: [PATCH 03/13] chore: e2e: expose --allow-crds-mismatch from conformace test (#4297) e2e: expose --allow-crds-mismatch from conformace test This is to align `test/e2e` package with `test/conformance` package for consistency (i.e. --allow-crds-mismatch for both test suites). This is needed to run e2e test in cluster with pre-installed Gateway API CRDs. Signed-off-by: Qiu Yu --- test/e2e/e2e_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go index e0e71f95173b..ef186153eeff 100644 --- a/test/e2e/e2e_test.go +++ b/test/e2e/e2e_test.go @@ -50,6 +50,7 @@ func TestE2E(t *testing.T) { SkipTests: []string{ tests.GatewayInfraResourceTest.ShortName, // https://github.com/envoyproxy/gateway/issues/3191 }, + AllowCRDsMismatch: *flags.AllowCRDsMismatch, }) if err != nil { t.Fatalf("Failed to create ConformanceTestSuite: %v", err) From 475cd61389c2f71e6fce8b9cc81c29ee5e18cc29 Mon Sep 17 00:00:00 2001 From: Arko Dasgupta Date: Fri, 20 Sep 2024 18:33:19 -0700 Subject: [PATCH 04/13] revisit envoy shutdown settings (#4288) * Set default minDrainDuration to `10s` . Since the default `readinessProbe.periodSeconds` is `5s`, this gives any LB controller `5s` to update its endpoint pool if its basing it off the k8s API server * Set default `drainTimeout` to `60s`. This ensures clients holding persistent connections, can be closed sooner. Fixes: https://github.com/envoyproxy/gateway/issues/4125 * Updates the default `terminationGracePeriodSeconds` to `360s` which is `300s` more than the default drain timeout Signed-off-by: Arko Dasgupta Co-authored-by: zirain --- api/v1alpha1/envoyproxy_types.go | 4 ++-- .../crds/generated/gateway.envoyproxy.io_envoyproxies.yaml | 4 ++-- internal/cmd/envoy.go | 4 ++-- internal/infrastructure/kubernetes/proxy/resource.go | 5 ++++- .../infrastructure/kubernetes/proxy/resource_provider.go | 2 +- .../proxy/testdata/daemonsets/component-level.yaml | 3 ++- .../kubernetes/proxy/testdata/daemonsets/custom.yaml | 3 ++- .../kubernetes/proxy/testdata/daemonsets/default-env.yaml | 3 ++- .../kubernetes/proxy/testdata/daemonsets/default.yaml | 3 ++- .../proxy/testdata/daemonsets/disable-prometheus.yaml | 3 ++- .../kubernetes/proxy/testdata/daemonsets/extension-env.yaml | 3 ++- .../testdata/daemonsets/override-labels-and-annotations.yaml | 3 ++- .../proxy/testdata/daemonsets/patch-daemonset.yaml | 3 ++- .../kubernetes/proxy/testdata/daemonsets/volumes.yaml | 3 ++- .../proxy/testdata/daemonsets/with-annotations.yaml | 3 ++- .../proxy/testdata/daemonsets/with-concurrency.yaml | 3 ++- .../proxy/testdata/daemonsets/with-extra-args.yaml | 3 ++- .../proxy/testdata/daemonsets/with-image-pull-secrets.yaml | 3 ++- .../kubernetes/proxy/testdata/daemonsets/with-name.yaml | 3 ++- .../proxy/testdata/daemonsets/with-node-selector.yaml | 3 ++- .../daemonsets/with-topology-spread-constraints.yaml | 3 ++- .../kubernetes/proxy/testdata/deployments/bootstrap.yaml | 3 ++- .../proxy/testdata/deployments/component-level.yaml | 3 ++- .../kubernetes/proxy/testdata/deployments/custom.yaml | 3 ++- .../testdata/deployments/custom_with_initcontainers.yaml | 3 ++- .../kubernetes/proxy/testdata/deployments/default-env.yaml | 3 ++- .../kubernetes/proxy/testdata/deployments/default.yaml | 3 ++- .../proxy/testdata/deployments/disable-prometheus.yaml | 3 ++- .../kubernetes/proxy/testdata/deployments/extension-env.yaml | 3 ++- .../deployments/override-labels-and-annotations.yaml | 3 ++- .../proxy/testdata/deployments/patch-deployment.yaml | 3 ++- .../kubernetes/proxy/testdata/deployments/volumes.yaml | 3 ++- .../proxy/testdata/deployments/with-annotations.yaml | 3 ++- .../proxy/testdata/deployments/with-concurrency.yaml | 3 ++- .../proxy/testdata/deployments/with-empty-memory-limits.yaml | 3 ++- .../proxy/testdata/deployments/with-extra-args.yaml | 3 ++- .../proxy/testdata/deployments/with-image-pull-secrets.yaml | 3 ++- .../kubernetes/proxy/testdata/deployments/with-name.yaml | 3 ++- .../proxy/testdata/deployments/with-node-selector.yaml | 3 ++- .../deployments/with-topology-spread-constraints.yaml | 3 ++- site/content/en/latest/api/extension_types.md | 4 ++-- site/content/zh/latest/api/extension_types.md | 4 ++-- 42 files changed, 85 insertions(+), 47 deletions(-) diff --git a/api/v1alpha1/envoyproxy_types.go b/api/v1alpha1/envoyproxy_types.go index 74218aad20b0..d7a2a73abe81 100644 --- a/api/v1alpha1/envoyproxy_types.go +++ b/api/v1alpha1/envoyproxy_types.go @@ -256,12 +256,12 @@ type EnvoyProxyProvider struct { // 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. + // If unspecified, defaults to 60 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. + // If unspecified, defaults to 10 seconds. // // +optional MinDrainDuration *metav1.Duration `json:"minDrainDuration,omitempty"` 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 145a3e4d41a2..e5488fd636bc 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -10248,12 +10248,12 @@ spec: drainTimeout: description: |- DrainTimeout defines the graceful drain timeout. This should be less than the pod's terminationGracePeriodSeconds. - If unspecified, defaults to 600 seconds. + If unspecified, defaults to 60 seconds. type: string minDrainDuration: description: |- MinDrainDuration defines the minimum drain duration allowing time for endpoint deprogramming to complete. - If unspecified, defaults to 5 seconds. + If unspecified, defaults to 10 seconds. type: string type: object telemetry: diff --git a/internal/cmd/envoy.go b/internal/cmd/envoy.go index 20cf95bb412a..87eccf8a520e 100644 --- a/internal/cmd/envoy.go +++ b/internal/cmd/envoy.go @@ -40,10 +40,10 @@ func getShutdownCommand() *cobra.Command { }, } - cmd.PersistentFlags().DurationVar(&drainTimeout, "drain-timeout", 600*time.Second, + cmd.PersistentFlags().DurationVar(&drainTimeout, "drain-timeout", 60*time.Second, "Graceful shutdown timeout. This should be less than the pod's terminationGracePeriodSeconds.") - cmd.PersistentFlags().DurationVar(&minDrainDuration, "min-drain-duration", 5*time.Second, + cmd.PersistentFlags().DurationVar(&minDrainDuration, "min-drain-duration", 10*time.Second, "Minimum drain duration allowing time for endpoint deprogramming to complete.") cmd.PersistentFlags().IntVar(&exitAtConnections, "exit-at-connections", 0, diff --git a/internal/infrastructure/kubernetes/proxy/resource.go b/internal/infrastructure/kubernetes/proxy/resource.go index f689910bfda8..32ca695e5dac 100644 --- a/internal/infrastructure/kubernetes/proxy/resource.go +++ b/internal/infrastructure/kubernetes/proxy/resource.go @@ -183,9 +183,12 @@ func expectedProxyContainers(infra *ir.ProxyInfra, args = append(args, fmt.Sprintf("--component-log-level %s", componentsLogLevel)) } + // Default + drainTimeout := 60.0 if shutdownConfig != nil && shutdownConfig.DrainTimeout != nil { - args = append(args, fmt.Sprintf("--drain-time-s %.0f", shutdownConfig.DrainTimeout.Seconds())) + drainTimeout = shutdownConfig.DrainTimeout.Seconds() } + args = append(args, fmt.Sprintf("--drain-time-s %.0f", drainTimeout)) if infra.Config != nil { args = append(args, infra.Config.Spec.ExtraArgs...) diff --git a/internal/infrastructure/kubernetes/proxy/resource_provider.go b/internal/infrastructure/kubernetes/proxy/resource_provider.go index 7795c145c77d..27edd2949b3b 100644 --- a/internal/infrastructure/kubernetes/proxy/resource_provider.go +++ b/internal/infrastructure/kubernetes/proxy/resource_provider.go @@ -442,7 +442,7 @@ func (r *ResourceRender) HorizontalPodAutoscaler() (*autoscalingv2.HorizontalPod } func expectedTerminationGracePeriodSeconds(cfg *egv1a1.ShutdownConfig) *int64 { - s := 900 // default + s := 360 // default if cfg != nil && cfg.DrainTimeout != nil { s = int(cfg.DrainTimeout.Seconds() + 300) // 5 minutes longer than drain timeout } diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/component-level.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/component-level.yaml index e707811b7250..b81eac520be9 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/component-level.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/component-level.yaml @@ -42,6 +42,7 @@ spec: - --cpuset-threads - --drain-strategy immediate - --component-log-level filter:info + - --drain-time-s 60 command: - envoy env: @@ -185,7 +186,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/custom.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/custom.yaml index 0f6a997d4c6a..dd3d30cb87cf 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/custom.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/custom.yaml @@ -225,6 +225,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -366,7 +367,7 @@ spec: securityContext: runAsUser: 1000 serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default-env.yaml index 6fdf1da0e605..2756e0ac6677 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default-env.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default-env.yaml @@ -224,6 +224,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -365,7 +366,7 @@ spec: securityContext: runAsUser: 1000 serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml index a72d157d29ce..cdecbf11accf 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml @@ -209,6 +209,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -352,7 +353,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml index 4ce178c37020..cb14c7d01025 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml @@ -183,6 +183,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -323,7 +324,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/extension-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/extension-env.yaml index c79f727f345d..844e8c38b8a4 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/extension-env.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/extension-env.yaml @@ -224,6 +224,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -369,7 +370,7 @@ spec: securityContext: runAsUser: 1000 serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml index 1ad3c6a3e601..3e2631cf7a25 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml @@ -218,6 +218,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -361,7 +362,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml index fb0fd20619a8..894bd9597d49 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml @@ -209,6 +209,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -353,7 +354,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/volumes.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/volumes.yaml index 1e0c7f755e73..74555834ecf7 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/volumes.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/volumes.yaml @@ -224,6 +224,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -369,7 +370,7 @@ spec: securityContext: runAsUser: 1000 serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml index 208984e9e672..708f586ffc27 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml @@ -214,6 +214,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -357,7 +358,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-concurrency.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-concurrency.yaml index 0f5de423806e..10911bdec5d0 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-concurrency.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-concurrency.yaml @@ -42,6 +42,7 @@ spec: - --cpuset-threads - --drain-strategy immediate - --concurrency 4 + - --drain-time-s 60 command: - envoy env: @@ -185,7 +186,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml index 4ac38c0a96e2..558e51410c06 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml @@ -209,6 +209,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 - --key1 val1 - --key2 val2 command: @@ -354,7 +355,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml index 62f40dc8db94..bb6d7bcebc5f 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml @@ -209,6 +209,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -355,7 +356,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml index 9fee30ccc12d..7df24d4b5c48 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml @@ -209,6 +209,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -352,7 +353,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml index d5afd458ecd0..6fb612dad300 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml @@ -209,6 +209,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -355,7 +356,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml index 2299126ab977..cc863ceb2cd5 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml @@ -209,6 +209,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -352,7 +353,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 topologySpreadConstraints: - labelSelector: matchLabels: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml index 74f15989fe5b..7c9798100847 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml @@ -45,6 +45,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -188,7 +189,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 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 25a181a6c759..b9076bc915f2 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml @@ -46,6 +46,7 @@ spec: - --cpuset-threads - --drain-strategy immediate - --component-log-level filter:info + - --drain-time-s 60 command: - envoy env: @@ -189,7 +190,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 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 a723d5e5e2f6..b770e10c5ab2 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml @@ -230,6 +230,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -371,7 +372,7 @@ spec: securityContext: runAsUser: 1000 serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: 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 3a86964c9260..3b7f4c131315 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml @@ -230,6 +230,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -386,7 +387,7 @@ spec: securityContext: runAsUser: 1000 serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml index 98dfc7fd8a4b..11fc90e2e6f5 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml @@ -229,6 +229,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -370,7 +371,7 @@ spec: securityContext: runAsUser: 1000 serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml index d1ce99db4bea..a1efff9d4503 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml @@ -213,6 +213,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -356,7 +357,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml index 0687d1f12e46..cf2503cc1427 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml @@ -187,6 +187,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -327,7 +328,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 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 e23b1bf1c245..97f116c06206 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml @@ -229,6 +229,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -374,7 +375,7 @@ spec: securityContext: runAsUser: 1000 serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: 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 575869b3c10a..3f5c31be439e 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 @@ -222,6 +222,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -365,7 +366,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 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 index 470b6fcd9261..725c4994a52c 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml @@ -213,6 +213,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -357,7 +358,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml index 121b7efbc681..4c5819a87863 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml @@ -229,6 +229,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -374,7 +375,7 @@ spec: securityContext: runAsUser: 1000 serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml index b3b7c2cd4bde..f0a9014ec9fe 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml @@ -218,6 +218,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -361,7 +362,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 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 e678283368c4..2902e865bf25 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml @@ -46,6 +46,7 @@ spec: - --cpuset-threads - --drain-strategy immediate - --concurrency 4 + - --drain-time-s 60 command: - envoy env: @@ -189,7 +190,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml index d7e3740acd2f..cc950e452e9e 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml @@ -213,6 +213,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -355,7 +356,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 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 254055d791fb..d31d189e6160 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml @@ -213,6 +213,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 - --key1 val1 - --key2 val2 command: @@ -358,7 +359,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 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 956d8ab72ecb..a60b4d2169eb 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 @@ -213,6 +213,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -359,7 +360,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml index 291429e724a2..2dd44b08dd95 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml @@ -213,6 +213,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -356,7 +357,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 volumes: - name: certs secret: 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 844489965e1e..235b1e992f90 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml @@ -213,6 +213,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -359,7 +360,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 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 26ede99c55aa..60fb354d5a7f 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 @@ -213,6 +213,7 @@ spec: - --log-level warn - --cpuset-threads - --drain-strategy immediate + - --drain-time-s 60 command: - envoy env: @@ -356,7 +357,7 @@ spec: restartPolicy: Always schedulerName: default-scheduler serviceAccountName: envoy-default-37a8eec1 - terminationGracePeriodSeconds: 900 + terminationGracePeriodSeconds: 360 topologySpreadConstraints: - labelSelector: matchLabels: diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index 70b7608406e6..d02a1686171c 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -3559,8 +3559,8 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | -| `drainTimeout` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#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.29/#duration-v1-meta)_ | false | MinDrainDuration defines the minimum drain duration allowing time for endpoint deprogramming to complete.
If unspecified, defaults to 5 seconds. | +| `drainTimeout` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | false | DrainTimeout defines the graceful drain timeout. This should be less than the pod's terminationGracePeriodSeconds.
If unspecified, defaults to 60 seconds. | +| `minDrainDuration` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | false | MinDrainDuration defines the minimum drain duration allowing time for endpoint deprogramming to complete.
If unspecified, defaults to 10 seconds. | #### ShutdownManager diff --git a/site/content/zh/latest/api/extension_types.md b/site/content/zh/latest/api/extension_types.md index 70b7608406e6..d02a1686171c 100644 --- a/site/content/zh/latest/api/extension_types.md +++ b/site/content/zh/latest/api/extension_types.md @@ -3559,8 +3559,8 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | -| `drainTimeout` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#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.29/#duration-v1-meta)_ | false | MinDrainDuration defines the minimum drain duration allowing time for endpoint deprogramming to complete.
If unspecified, defaults to 5 seconds. | +| `drainTimeout` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | false | DrainTimeout defines the graceful drain timeout. This should be less than the pod's terminationGracePeriodSeconds.
If unspecified, defaults to 60 seconds. | +| `minDrainDuration` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ | false | MinDrainDuration defines the minimum drain duration allowing time for endpoint deprogramming to complete.
If unspecified, defaults to 10 seconds. | #### ShutdownManager From 697fbed6d49c4a513a2e1d3848c56d086a6a5051 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 14:01:05 +0800 Subject: [PATCH 05/13] build(deps): bump github/codeql-action from 3.26.7 to 3.26.8 (#4310) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.7 to 3.26.8. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/8214744c546c1e5c8f03dde8fab3a7353211988d...294a9d92911152fe08befb9ec03e240add280cb3) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 6 +++--- .github/workflows/scorecard.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 509117893671..90ad9f95da59 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@8214744c546c1e5c8f03dde8fab3a7353211988d # v3.26.7 + uses: github/codeql-action/init@294a9d92911152fe08befb9ec03e240add280cb3 # v3.26.8 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@8214744c546c1e5c8f03dde8fab3a7353211988d # v3.26.7 + uses: github/codeql-action/autobuild@294a9d92911152fe08befb9ec03e240add280cb3 # v3.26.8 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@8214744c546c1e5c8f03dde8fab3a7353211988d # v3.26.7 + uses: github/codeql-action/analyze@294a9d92911152fe08befb9ec03e240add280cb3 # v3.26.8 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 3a03313309da..9c574f263df6 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@8214744c546c1e5c8f03dde8fab3a7353211988d # v3.26.7 + uses: github/codeql-action/upload-sarif@294a9d92911152fe08befb9ec03e240add280cb3 # v3.26.8 with: sarif_file: results.sarif From 2bd27ddecaf5d92e447cd1d3cf6d5c83ecfb6d48 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 18:13:41 +0800 Subject: [PATCH 06/13] build(deps): bump github.com/ohler55/ojg from 1.24.0 to 1.24.1 (#4302) Bumps [github.com/ohler55/ojg](https://github.com/ohler55/ojg) from 1.24.0 to 1.24.1. - [Release notes](https://github.com/ohler55/ojg/releases) - [Changelog](https://github.com/ohler55/ojg/blob/develop/CHANGELOG.md) - [Commits](https://github.com/ohler55/ojg/compare/v1.24.0...v1.24.1) --- updated-dependencies: - dependency-name: github.com/ohler55/ojg dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Huabing Zhao --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0fe4eb4422ee..ed12f773dc1b 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/google/go-containerregistry v0.20.2 github.com/hashicorp/go-multierror v1.1.1 github.com/miekg/dns v1.1.62 - github.com/ohler55/ojg v1.24.0 + github.com/ohler55/ojg v1.24.1 github.com/prometheus/client_golang v1.20.3 github.com/prometheus/common v0.59.1 github.com/spf13/cobra v1.8.1 diff --git a/go.sum b/go.sum index 50c9631fe336..b89829f41ac8 100644 --- a/go.sum +++ b/go.sum @@ -612,8 +612,8 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/ohler55/ojg v1.24.0 h1:y2AVez6fPTszK/jPhaAYMCAzAoSleConMqSDD5wJKJg= -github.com/ohler55/ojg v1.24.0/go.mod h1:gQhDVpQLqrmnd2eqGAvJtn+NfKoYJbe/A4Sj3/Vro4o= +github.com/ohler55/ojg v1.24.1 h1:PaVLelrNgT5/0ppPaUtey54tOVp245z33fkhL2jljjY= +github.com/ohler55/ojg v1.24.1/go.mod h1:gQhDVpQLqrmnd2eqGAvJtn+NfKoYJbe/A4Sj3/Vro4o= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= From 13b1fd848f74fe6fc1d542408784163db20db498 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 10:44:08 -0700 Subject: [PATCH 07/13] build(deps): bump distroless/static from `42d15c6` to `dcd3f1f` in /tools/docker/envoy-gateway (#4311) build(deps): bump distroless/static in /tools/docker/envoy-gateway Bumps distroless/static from `42d15c6` to `dcd3f1f`. --- updated-dependencies: - dependency-name: distroless/static dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/docker/envoy-gateway/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/docker/envoy-gateway/Dockerfile b/tools/docker/envoy-gateway/Dockerfile index 73eece8b9908..2f30eec54686 100644 --- a/tools/docker/envoy-gateway/Dockerfile +++ b/tools/docker/envoy-gateway/Dockerfile @@ -4,7 +4,7 @@ RUN mkdir -p /var/lib/eg # Use distroless as minimal base image to package the manager binary # Refer to https://github.com/GoogleContainerTools/distroless for more details -FROM gcr.io/distroless/static:nonroot@sha256:42d15c647a762d3ce3a67eab394220f5268915d6ddba9006871e16e4698c3a24 +FROM gcr.io/distroless/static:nonroot@sha256:dcd3f1f09adef5689088c9c4d96a8d98c889d8281d3946145074f89eafe7e1af ARG TARGETPLATFORM COPY $TARGETPLATFORM/envoy-gateway /usr/local/bin/ COPY --from=source --chown=65532:65532 /var/lib /var/lib From c37657eae9ea034def5547035352f078720dd785 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 10:44:39 -0700 Subject: [PATCH 08/13] build(deps): bump github.com/docker/cli from 27.2.0+incompatible to 27.3.1+incompatible (#4306) build(deps): bump github.com/docker/cli Bumps [github.com/docker/cli](https://github.com/docker/cli) from 27.2.0+incompatible to 27.3.1+incompatible. - [Commits](https://github.com/docker/cli/compare/v27.2.0...v27.3.1) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ed12f773dc1b..e699b776d3e4 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/Masterminds/semver/v3 v3.3.0 github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc - github.com/docker/cli v27.2.0+incompatible + github.com/docker/cli v27.3.1+incompatible github.com/dominikbraun/graph v0.23.0 github.com/envoyproxy/go-control-plane v0.13.1-0.20240917224354-20d038a70568 github.com/envoyproxy/ratelimit v1.4.1-0.20230427142404-e2a87f41d3a7 diff --git a/go.sum b/go.sum index b89829f41ac8..0ed7d5b1a996 100644 --- a/go.sum +++ b/go.sum @@ -179,8 +179,8 @@ github.com/distribution/distribution/v3 v3.0.0-beta.1 h1:X+ELTxPuZ1Xe5MsD3kp2wfG github.com/distribution/distribution/v3 v3.0.0-beta.1/go.mod h1:O9O8uamhHzWWQVTjuQpyYUVm/ShPHPUDgvQMpHGVBDs= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/cli v27.2.0+incompatible h1:yHD1QEB1/0vr5eBNpu8tncu8gWxg8EydFPOSKHzXSMM= -github.com/docker/cli v27.2.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v27.3.1+incompatible h1:qEGdFBF3Xu6SCvCYhc7CzaQTlBmqDuzxPDpigSyeKQQ= +github.com/docker/cli v27.3.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= From 19b6119ab88689f802b33b047c4b13b7273011dc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 10:45:27 -0700 Subject: [PATCH 09/13] build(deps): bump google.golang.org/grpc from 1.66.2 to 1.67.0 in /examples/extension-server (#4307) build(deps): bump google.golang.org/grpc in /examples/extension-server Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.66.2 to 1.67.0. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.66.2...v1.67.0) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/extension-server/go.mod | 6 +++--- examples/extension-server/go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/extension-server/go.mod b/examples/extension-server/go.mod index c023ad3e2168..c4d2cbcf7287 100644 --- a/examples/extension-server/go.mod +++ b/examples/extension-server/go.mod @@ -6,7 +6,7 @@ require ( github.com/envoyproxy/gateway v1.0.2 github.com/envoyproxy/go-control-plane v0.13.1-0.20240917224354-20d038a70568 github.com/urfave/cli/v2 v2.27.2 - google.golang.org/grpc v1.66.2 + google.golang.org/grpc v1.67.0 google.golang.org/protobuf v1.34.2 k8s.io/apimachinery v0.31.1 sigs.k8s.io/controller-runtime v0.19.0 @@ -14,9 +14,9 @@ require ( ) require ( - cel.dev/expr v0.15.0 // indirect + cel.dev/expr v0.16.0 // indirect github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect - github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b // indirect + github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect diff --git a/examples/extension-server/go.sum b/examples/extension-server/go.sum index 920c977fbca8..99b3fb50e28e 100644 --- a/examples/extension-server/go.sum +++ b/examples/extension-server/go.sum @@ -1,9 +1,9 @@ -cel.dev/expr v0.15.0 h1:O1jzfJCQBfL5BFoYktaxwIhuttaQPsVWerH9/EEKx0w= -cel.dev/expr v0.15.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= +cel.dev/expr v0.16.0 h1:yloc84fytn4zmJX2GU3TkXGsaieaV7dQ057Qs4sIG2Y= +cel.dev/expr v0.16.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= -github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw= -github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20 h1:N+3sFI5GUjRKBi+i0TxYVST9h4Ie192jJWpHvthBBgg= +github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -109,8 +109,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1: google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I= google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw= +google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 4c31efae289dc3306e692c620412770e8dce2481 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 10:45:48 -0700 Subject: [PATCH 10/13] build(deps): bump github.com/bufbuild/buf from 1.41.0 to 1.42.0 in /tools/src/buf (#4308) build(deps): bump github.com/bufbuild/buf in /tools/src/buf Bumps [github.com/bufbuild/buf](https://github.com/bufbuild/buf) from 1.41.0 to 1.42.0. - [Release notes](https://github.com/bufbuild/buf/releases) - [Changelog](https://github.com/bufbuild/buf/blob/main/CHANGELOG.md) - [Commits](https://github.com/bufbuild/buf/compare/v1.41.0...v1.42.0) --- updated-dependencies: - dependency-name: github.com/bufbuild/buf dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/src/buf/go.mod | 9 +++++---- tools/src/buf/go.sum | 26 ++++++++++++-------------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/tools/src/buf/go.mod b/tools/src/buf/go.mod index e719faa3857b..7dcf60d5c511 100644 --- a/tools/src/buf/go.mod +++ b/tools/src/buf/go.mod @@ -2,7 +2,7 @@ module local go 1.23.1 -require github.com/bufbuild/buf v1.41.0 +require github.com/bufbuild/buf v1.42.0 require ( buf.build/gen/go/bufbuild/bufplugin/protocolbuffers/go v1.34.2-20240904181154-a0be11449112.2 // indirect @@ -11,6 +11,7 @@ require ( buf.build/gen/go/bufbuild/registry/protocolbuffers/go v1.34.2-20240821192916-45ba72cdd479.2 // indirect buf.build/gen/go/pluginrpc/pluginrpc/protocolbuffers/go v1.34.2-20240828222655-5345c0a56177.2 // indirect buf.build/go/bufplugin v0.2.0 // indirect + buf.build/go/protoyaml v0.2.0 // indirect connectrpc.com/connect v1.16.2 // indirect connectrpc.com/otelconnect v0.7.1 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect @@ -20,7 +21,6 @@ require ( github.com/bufbuild/protocompile v0.14.1 // indirect github.com/bufbuild/protoplugin v0.0.0-20240911180120-7bb73e41a54a // indirect github.com/bufbuild/protovalidate-go v0.6.5 // indirect - github.com/bufbuild/protoyaml-go v0.1.12 // indirect github.com/containerd/cgroups/v3 v3.0.3 // indirect github.com/containerd/containerd v1.7.22 // indirect github.com/containerd/continuity v0.4.3 // indirect @@ -78,6 +78,7 @@ require ( github.com/pkg/profile v1.7.0 // indirect github.com/quic-go/qpack v0.5.1 // indirect github.com/quic-go/quic-go v0.47.0 // indirect + github.com/rogpeppe/go-internal v1.10.0 // indirect github.com/rs/cors v1.11.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect @@ -86,7 +87,7 @@ require ( github.com/stoewer/go-strcase v1.3.0 // indirect github.com/vbatts/tar-split v0.11.5 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 // indirect go.opentelemetry.io/otel v1.30.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 // indirect go.opentelemetry.io/otel/metric v1.30.0 // indirect @@ -107,7 +108,7 @@ require ( golang.org/x/tools v0.25.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect - google.golang.org/grpc v1.66.1 // indirect + google.golang.org/grpc v1.66.2 // indirect google.golang.org/protobuf v1.34.3-0.20240816073751-94ecbc261689 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect pluginrpc.com/pluginrpc v0.3.0 // indirect diff --git a/tools/src/buf/go.sum b/tools/src/buf/go.sum index 49fa12e2c0a6..e76ce65da22c 100644 --- a/tools/src/buf/go.sum +++ b/tools/src/buf/go.sum @@ -10,6 +10,8 @@ buf.build/gen/go/pluginrpc/pluginrpc/protocolbuffers/go v1.34.2-20240828222655-5 buf.build/gen/go/pluginrpc/pluginrpc/protocolbuffers/go v1.34.2-20240828222655-5345c0a56177.2/go.mod h1:GjH0gjlY/ns16X8d6eaXV2W+6IFwsO5Ly9WVnzyd1E0= buf.build/go/bufplugin v0.2.0 h1:nnNvWzUgQXitRDmjWWIkuXj9klreAAE94sVCsL+0v5g= buf.build/go/bufplugin v0.2.0/go.mod h1:ZZYGt6PDcjbBSywdz/G8NdXkIuWi2rzR8CduGzbCPdk= +buf.build/go/protoyaml v0.2.0 h1:2g3OHjtLDqXBREIOjpZGHmQ+U/4mkN1YiQjxNB68Ip8= +buf.build/go/protoyaml v0.2.0/go.mod h1:L/9QvTDkTWcDTzAL6HMfN+mYC6CmZRm2KnsUA054iL0= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= connectrpc.com/connect v1.16.2 h1:ybd6y+ls7GOlb7Bh5C8+ghA6SvCBajHwxssO2CGFjqE= connectrpc.com/connect v1.16.2/go.mod h1:n2kgwskMHXC+lVqb18wngEpF95ldBHXjZYJussz5FRc= @@ -26,16 +28,14 @@ github.com/Microsoft/hcsshim v0.12.6 h1:qEnZjoHXv+4/s0LmKZWE0/AiZmMWEIkFfWBSf1a0 github.com/Microsoft/hcsshim v0.12.6/go.mod h1:ZABCLVcvLMjIkzr9rUGcQ1QA0p0P3Ps+d3N1g2DsFfk= github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ= github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw= -github.com/bufbuild/buf v1.41.0 h1:4z4r7bysUZ8EAseRjQ/AWQNpOP3M1v15N+vhLe8U1WU= -github.com/bufbuild/buf v1.41.0/go.mod h1:4fMd9FF67dUbuzMFg5rIJy+6Iu6oKldAG2Z9A8zAlEk= +github.com/bufbuild/buf v1.42.0 h1:awh6dZ1qjC468Wq9FN/3WAeBLoe6LV8GeFSHlL3ltvE= +github.com/bufbuild/buf v1.42.0/go.mod h1:AKKOqvsTLjeFXTEc7h9KsxsVBY/hETalmy7k8e0FVEo= github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw= github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c= github.com/bufbuild/protoplugin v0.0.0-20240911180120-7bb73e41a54a h1:l3RhVoG0RtC61h6TVWnkniGj4TgBebuyPQRdleFAmTg= github.com/bufbuild/protoplugin v0.0.0-20240911180120-7bb73e41a54a/go.mod h1:c5D8gWRIZ2HLWO3gXYTtUfw/hbJyD8xikv2ooPxnklQ= github.com/bufbuild/protovalidate-go v0.6.5 h1:WucDKXIbK22WjkO8A8J6Yyxxy0jl91Oe9LSMduq3YEE= github.com/bufbuild/protovalidate-go v0.6.5/go.mod h1:LHDiGCWSM3GagZEnyEZ1sPtFwi6Ja4tVTi/DCc+iDFI= -github.com/bufbuild/protoyaml-go v0.1.12 h1:tIJrwvGxumVpNwLsw/AevT1QnkPDBuAObBSuBAdmAWY= -github.com/bufbuild/protoyaml-go v0.1.12/go.mod h1:Xmz3wct+08Va+g9gjIuLTAmxW2w6sre5Wrgw7K3gn0I= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -132,8 +132,6 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/cel-go v0.21.0 h1:cl6uW/gxN+Hy50tNYvI691+sXxioCnstFzLp2WO4GCI= github.com/google/cel-go v0.21.0/go.mod h1:rHUlWCcBKgyEk+eV03RPdZUekPp6YcJwV0FxuUksYxc= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -161,8 +159,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jdx/go-netrc v1.0.0 h1:QbLMLyCZGj0NA8glAhxUpf1zDg6cxnWgMBbjq40W0gQ= github.com/jdx/go-netrc v1.0.0/go.mod h1:Gh9eFQJnoTNIRHXl2j5bJXA1u84hQWJWgGh569zF3v8= -github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94= -github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8= +github.com/jhump/protoreflect/v2 v2.0.0-beta.2 h1:qZU+rEZUOYTz1Bnhi3xbwn+VxdXkLVeEpAeZzVXLY88= +github.com/jhump/protoreflect/v2 v2.0.0-beta.2/go.mod h1:4tnOYkB/mq7QTyS3YKtVtNrJv4Psqout8HA1U+hZtgM= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -228,8 +226,8 @@ github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= github.com/quic-go/quic-go v0.47.0 h1:yXs3v7r2bm1wmPTYNLKAAJTHMYkPEsfYJmTazXrCZ7Y= github.com/quic-go/quic-go v0.47.0/go.mod h1:3bCapYsJvXGZcipOHuu7plYtaV6tnF+z7wIFsU0WK9E= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -257,8 +255,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 h1:ZIg3ZT/aQ7AfKqdwp7ECpOK6vHqquXXuyTjIO8ZdmPs= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0/go.mod h1:DQAwmETtZV00skUwgD6+0U89g80NKsJE3DCKeLLPQMI= go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts= go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= @@ -367,8 +365,8 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.66.1 h1:hO5qAXR19+/Z44hmvIM4dQFMSYX9XcWsByfoxutBpAM= -google.golang.org/grpc v1.66.1/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= +google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From 7f24294d7ee9278341cc83a7aefe9bf91cb55dea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 10:46:18 -0700 Subject: [PATCH 11/13] build(deps): bump actions/setup-node from 4.0.3 to 4.0.4 (#4309) Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4.0.3 to 4.0.4. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/1e60f620b9541d16bece96c5465dc8ee9832be0b...0a44ba7841725637a19e28fa30b79a866c81b0a6) --- updated-dependencies: - dependency-name: actions/setup-node dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 0b4cb36ecf62..c30624a0493e 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -62,7 +62,7 @@ jobs: extended: true - name: Setup Node - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.1.0 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.1.0 with: node-version: '18' From e5fe8496a97d81d8cf4540005b08005123956c9a Mon Sep 17 00:00:00 2001 From: Dean Coakley Date: Mon, 23 Sep 2024 21:25:10 +0100 Subject: [PATCH 12/13] docs: fix patch command for adding TLS gateway listener (#4316) docs: fix patch command adding TLS gateway listener Signed-off-by: Dean Coakley --- site/content/en/docs/tasks/security/tls-cert-manager.md | 4 ++-- site/content/en/latest/tasks/security/tls-cert-manager.md | 4 ++-- site/content/en/v0.5/user/tls-cert-manager.md | 4 ++-- site/content/en/v0.6/user/tls-cert-manager.md | 4 ++-- site/content/en/v1.0/tasks/security/tls-cert-manager.md | 4 ++-- site/content/en/v1.1/tasks/security/tls-cert-manager.md | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/site/content/en/docs/tasks/security/tls-cert-manager.md b/site/content/en/docs/tasks/security/tls-cert-manager.md index d51fa469e8c4..d2b217d0545c 100644 --- a/site/content/en/docs/tasks/security/tls-cert-manager.md +++ b/site/content/en/docs/tasks/security/tls-cert-manager.md @@ -76,7 +76,7 @@ EOF We now have to patch the example Gateway to reference cert-manager: ```console -$ kubectl patch gateway/eg --patch-file - < Date: Mon, 23 Sep 2024 19:20:30 -0500 Subject: [PATCH 13/13] feat(translator): implement httproutefilter and path regex rewrite (#4258) * impl: httpfilter Signed-off-by: Guy Daich * fix review comments Signed-off-by: Guy Daich --------- Signed-off-by: Guy Daich --- api/v1alpha1/httproutefilter_types.go | 6 +- ...ateway.envoyproxy.io_httproutefilters.yaml | 8 +- charts/gateway-helm/templates/_rbac.tpl | 1 + internal/gatewayapi/filters.go | 116 +++++- internal/gatewayapi/helpers.go | 3 + internal/gatewayapi/resource/load.go | 14 + internal/gatewayapi/resource/resource.go | 2 + .../gatewayapi/resource/supported_kind.go | 1 + .../resource/zz_generated.deepcopy.go | 11 + ...te-filter-regex-match-replace-http.in.yaml | 147 +++++++ ...e-filter-regex-match-replace-http.out.yaml | 366 +++++++++++++++++ ...filter-regex-match-replace-invalid.in.yaml | 230 +++++++++++ ...ilter-regex-match-replace-invalid.out.yaml | 383 ++++++++++++++++++ internal/ir/xds.go | 55 ++- internal/ir/xds_test.go | 14 +- internal/ir/zz_generated.deepcopy.go | 38 +- internal/provider/kubernetes/controller.go | 25 ++ internal/provider/kubernetes/filters.go | 11 + internal/provider/kubernetes/indexers.go | 27 +- .../provider/kubernetes/kubernetes_test.go | 22 +- internal/provider/kubernetes/predicates.go | 26 ++ .../provider/kubernetes/predicates_test.go | 120 ++++-- internal/provider/kubernetes/routes.go | 42 +- internal/provider/kubernetes/test/utils.go | 40 +- internal/xds/translator/route.go | 12 +- .../xds-ir/http-route-rewrite-url-regex.yaml | 26 ++ ...http-route-rewrite-url-regex.clusters.yaml | 17 + ...ttp-route-rewrite-url-regex.endpoints.yaml | 12 + ...ttp-route-rewrite-url-regex.listeners.yaml | 34 ++ .../http-route-rewrite-url-regex.routes.yaml | 18 + site/content/en/latest/api/extension_types.md | 2 +- .../latest/tasks/traffic/http-urlrewrite.md | 156 +++++++ site/content/zh/latest/api/extension_types.md | 2 +- test/cel-validation/httproutefilter_test.go | 120 ++++++ .../httproute-rewrite-regex-path.yaml | 35 ++ .../e2e/tests/httproute_rewrite_regex_path.go | 59 +++ .../certjen-custom-scheduling.out.yaml | 1 + .../control-plane-with-pdb.out.yaml | 1 + .../helm/gateway-helm/default-config.out.yaml | 1 + .../deployment-custom-topology.out.yaml | 1 + .../deployment-images-config.out.yaml | 1 + .../envoy-gateway-config.out.yaml | 1 + .../global-images-config.out.yaml | 1 + 43 files changed, 2114 insertions(+), 94 deletions(-) create mode 100644 internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-regex-match-replace-http.in.yaml create mode 100644 internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-regex-match-replace-http.out.yaml create mode 100644 internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-regex-match-replace-invalid.in.yaml create mode 100644 internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-regex-match-replace-invalid.out.yaml create mode 100644 internal/xds/translator/testdata/in/xds-ir/http-route-rewrite-url-regex.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-regex.clusters.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-regex.endpoints.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-regex.listeners.yaml create mode 100644 internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-regex.routes.yaml create mode 100644 test/cel-validation/httproutefilter_test.go create mode 100644 test/e2e/testdata/httproute-rewrite-regex-path.yaml create mode 100644 test/e2e/tests/httproute_rewrite_regex_path.go diff --git a/api/v1alpha1/httproutefilter_types.go b/api/v1alpha1/httproutefilter_types.go index b8fe13f5296d..e0e4755f214b 100644 --- a/api/v1alpha1/httproutefilter_types.go +++ b/api/v1alpha1/httproutefilter_types.go @@ -56,14 +56,17 @@ const ( type ReplaceRegexMatch struct { // Pattern matches a regular expression against the value of the HTTP Path.The regex string must // adhere to the syntax documented in https://github.com/google/re2/wiki/Syntax. + // +kubebuilder:validation:MinLength=1 Pattern string `json:"pattern"` // Substitution is an expression that replaces the matched portion.The expression may include numbered // capture groups that adhere to syntax documented in https://github.com/google/re2/wiki/Syntax. Substitution string `json:"substitution"` } +// +kubebuilder:validation:XValidation:rule="self.type == 'ReplaceRegexMatch' ? has(self.replaceRegexMatch) : !has(self.replaceRegexMatch)",message="If HTTPPathModifier type is ReplaceRegexMatch, replaceRegexMatch field needs to be set." type HTTPPathModifier struct { - // +kubebuilder:validation:Enum=RegexHTTPPathModifier + // +kubebuilder:validation:Enum=ReplaceRegexMatch + // +kubebuilder:validation:Required Type HTTPPathModifierType `json:"type"` // ReplaceRegexMatch defines a path regex rewrite. The path portions matched by the regex pattern are replaced by the defined substitution. // https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-field-config-route-v3-routeaction-regex-rewrite @@ -84,6 +87,7 @@ type HTTPPathModifier struct { // pattern: (?i)/xxx/ // substitution: /yyy/ // Would transform path /aaa/XxX/bbb into /aaa/yyy/bbb (case-insensitive). + // +optional ReplaceRegexMatch *ReplaceRegexMatch `json:"replaceRegexMatch,omitempty"` } diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_httproutefilters.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_httproutefilters.yaml index 2bba4d20ff15..11447cc470e4 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_httproutefilters.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_httproutefilters.yaml @@ -82,6 +82,7 @@ spec: description: |- Pattern matches a regular expression against the value of the HTTP Path.The regex string must adhere to the syntax documented in https://github.com/google/re2/wiki/Syntax. + minLength: 1 type: string substitution: description: |- @@ -96,11 +97,16 @@ spec: description: HTTPPathModifierType defines the type of path redirect or rewrite. enum: - - RegexHTTPPathModifier + - ReplaceRegexMatch type: string required: - type type: object + x-kubernetes-validations: + - message: If HTTPPathModifier type is ReplaceRegexMatch, replaceRegexMatch + field needs to be set. + rule: 'self.type == ''ReplaceRegexMatch'' ? has(self.replaceRegexMatch) + : !has(self.replaceRegexMatch)' type: object type: object required: diff --git a/charts/gateway-helm/templates/_rbac.tpl b/charts/gateway-helm/templates/_rbac.tpl index fb9304e7d89f..27e90061b0ce 100644 --- a/charts/gateway-helm/templates/_rbac.tpl +++ b/charts/gateway-helm/templates/_rbac.tpl @@ -71,6 +71,7 @@ resources: - securitypolicies - envoyextensionpolicies - backends +- httproutefilters verbs: - get - list diff --git a/internal/gatewayapi/filters.go b/internal/gatewayapi/filters.go index de6be3528158..41acc4c76ba3 100644 --- a/internal/gatewayapi/filters.go +++ b/internal/gatewayapi/filters.go @@ -7,11 +7,13 @@ package gatewayapi import ( "fmt" + "regexp" "strings" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/gatewayapi/resource" "github.com/envoyproxy/gateway/internal/gatewayapi/status" "github.com/envoyproxy/gateway/internal/ir" @@ -150,16 +152,20 @@ func (t *Translator) processURLRewriteFilter( filterContext *HTTPFiltersContext, ) { if filterContext.URLRewrite != nil { - routeStatus := GetRouteStatus(filterContext.Route) - status.SetRouteStatusCondition(routeStatus, - filterContext.ParentRef.routeParentStatusIdx, - filterContext.Route.GetGeneration(), - gwapiv1.RouteConditionAccepted, - metav1.ConditionFalse, - gwapiv1.RouteReasonUnsupportedValue, - "Cannot configure multiple urlRewrite filters for a single HTTPRouteRule", - ) - return + if filterContext.URLRewrite.Hostname != nil || + filterContext.URLRewrite.Path.FullReplace != nil || + filterContext.URLRewrite.Path.PrefixMatchReplace != nil { + routeStatus := GetRouteStatus(filterContext.Route) + status.SetRouteStatusCondition(routeStatus, + filterContext.ParentRef.routeParentStatusIdx, + filterContext.Route.GetGeneration(), + gwapiv1.RouteConditionAccepted, + metav1.ConditionFalse, + gwapiv1.RouteReasonUnsupportedValue, + "Cannot configure multiple urlRewrite filters for a single HTTPRouteRule", + ) + return + } } if rewrite == nil { @@ -215,8 +221,10 @@ func (t *Translator) processURLRewriteFilter( return } if rewrite.Path.ReplaceFullPath != nil { - newURLRewrite.Path = &ir.HTTPPathModifier{ - FullReplace: rewrite.Path.ReplaceFullPath, + newURLRewrite.Path = &ir.ExtendedHTTPPathModifier{ + HTTPPathModifier: ir.HTTPPathModifier{ + FullReplace: rewrite.Path.ReplaceFullPath, + }, } } case gwapiv1.PrefixMatchHTTPPathModifier: @@ -247,8 +255,10 @@ func (t *Translator) processURLRewriteFilter( return } if rewrite.Path.ReplacePrefixMatch != nil { - newURLRewrite.Path = &ir.HTTPPathModifier{ - PrefixMatchReplace: rewrite.Path.ReplacePrefixMatch, + newURLRewrite.Path = &ir.ExtendedHTTPPathModifier{ + HTTPPathModifier: ir.HTTPPathModifier{ + PrefixMatchReplace: rewrite.Path.ReplacePrefixMatch, + }, } } default: @@ -738,6 +748,84 @@ func (t *Translator) processExtensionRefHTTPFilter(extFilter *gwapiv1.LocalObjec } filterNs := filterContext.Route.GetNamespace() + + if string(extFilter.Kind) == egv1a1.KindHTTPRouteFilter { + for _, hrf := range resources.HTTPRouteFilters { + if hrf.Namespace == filterNs && hrf.Name == string(extFilter.Name) && + hrf.Spec.URLRewrite.Path.Type == egv1a1.RegexHTTPPathModifier { + + if hrf.Spec.URLRewrite.Path.ReplaceRegexMatch == nil || + hrf.Spec.URLRewrite.Path.ReplaceRegexMatch.Pattern == "" { + errMsg := "ReplaceRegexMatch Pattern must be set when rewrite path type is \"ReplaceRegexMatch\"" + routeStatus := GetRouteStatus(filterContext.Route) + status.SetRouteStatusCondition(routeStatus, + filterContext.ParentRef.routeParentStatusIdx, + filterContext.Route.GetGeneration(), + gwapiv1.RouteConditionAccepted, + metav1.ConditionFalse, + gwapiv1.RouteReasonUnsupportedValue, + errMsg, + ) + return + } else if _, err := regexp.Compile(hrf.Spec.URLRewrite.Path.ReplaceRegexMatch.Pattern); err != nil { + // Avoid envoy NACKs due to invalid regex. + // Golang's regexp is almost identical to RE2: https://pkg.go.dev/regexp/syntax + errMsg := "ReplaceRegexMatch must be a valid RE2 regular expression" + routeStatus := GetRouteStatus(filterContext.Route) + status.SetRouteStatusCondition(routeStatus, + filterContext.ParentRef.routeParentStatusIdx, + filterContext.Route.GetGeneration(), + gwapiv1.RouteConditionAccepted, + metav1.ConditionFalse, + gwapiv1.RouteReasonUnsupportedValue, + errMsg, + ) + return + } + + rmr := &ir.RegexMatchReplace{ + Pattern: hrf.Spec.URLRewrite.Path.ReplaceRegexMatch.Pattern, + Substitution: hrf.Spec.URLRewrite.Path.ReplaceRegexMatch.Substitution, + } + + if filterContext.HTTPFilterIR.URLRewrite != nil { + // If path IR is already set - check for a conflict + if filterContext.HTTPFilterIR.URLRewrite.Path != nil { + path := filterContext.HTTPFilterIR.URLRewrite.Path + if path.RegexMatchReplace != nil || path.PrefixMatchReplace != nil || path.FullReplace != nil { + routeStatus := GetRouteStatus(filterContext.Route) + status.SetRouteStatusCondition(routeStatus, + filterContext.ParentRef.routeParentStatusIdx, + filterContext.Route.GetGeneration(), + gwapiv1.RouteConditionAccepted, + metav1.ConditionFalse, + gwapiv1.RouteReasonUnsupportedValue, + "Cannot configure multiple urlRewrite filters for a single HTTPRouteRule", + ) + return + } + } else { // no path + filterContext.HTTPFilterIR.URLRewrite.Path = &ir.ExtendedHTTPPathModifier{ + RegexMatchReplace: rmr, + } + return + } + } else { // no url rewrite + filterContext.HTTPFilterIR.URLRewrite = &ir.URLRewrite{ + Path: &ir.ExtendedHTTPPathModifier{ + RegexMatchReplace: rmr, + }, + } + return + } + } + } + errMsg := fmt.Sprintf("Unable to translate HTTPRouteFilter: %s/%s", filterNs, + extFilter.Name) + t.processUnresolvedHTTPFilter(errMsg, filterContext) + return + } + // This list of resources will be empty unless an extension is loaded (and introduces resources) for _, res := range resources.ExtensionRefFilters { if res.GetKind() == string(extFilter.Kind) && res.GetName() == string(extFilter.Name) && res.GetNamespace() == filterNs { diff --git a/internal/gatewayapi/helpers.go b/internal/gatewayapi/helpers.go index 885077f5cc36..9c5626d75249 100644 --- a/internal/gatewayapi/helpers.go +++ b/internal/gatewayapi/helpers.go @@ -179,6 +179,9 @@ func ValidateHTTPRouteFilter(filter *gwapiv1.HTTPRouteFilter, extGKs ...schema.G switch { case filter.ExtensionRef == nil: return errors.New("extensionRef field must be specified for an extended filter") + case string(filter.ExtensionRef.Group) == egv1a1.GroupVersion.Group && + string(filter.ExtensionRef.Kind) == egv1a1.KindHTTPRouteFilter: + return nil default: for _, gk := range extGKs { if filter.ExtensionRef.Group == gwapiv1.Group(gk.Group) && diff --git a/internal/gatewayapi/resource/load.go b/internal/gatewayapi/resource/load.go index cacc3ebe61a0..317ad93418cf 100644 --- a/internal/gatewayapi/resource/load.go +++ b/internal/gatewayapi/resource/load.go @@ -265,6 +265,20 @@ func kubernetesYAMLToResources(str string, addMissingResources bool) (*Resources Spec: typedSpec.(egv1a1.SecurityPolicySpec), } resources.SecurityPolicies = append(resources.SecurityPolicies, securityPolicy) + case KindHTTPRouteFilter: + typedSpec := spec.Interface() + httpRouteFilter := &egv1a1.HTTPRouteFilter{ + TypeMeta: metav1.TypeMeta{ + Kind: KindHTTPRouteFilter, + APIVersion: egv1a1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: name, + }, + Spec: typedSpec.(egv1a1.HTTPRouteFilterSpec), + } + resources.HTTPRouteFilters = append(resources.HTTPRouteFilters, httpRouteFilter) } } diff --git a/internal/gatewayapi/resource/resource.go b/internal/gatewayapi/resource/resource.go index a5d9e6fffb57..97468511fa83 100644 --- a/internal/gatewayapi/resource/resource.go +++ b/internal/gatewayapi/resource/resource.go @@ -63,6 +63,7 @@ type Resources struct { EnvoyExtensionPolicies []*egv1a1.EnvoyExtensionPolicy `json:"envoyExtensionPolicies,omitempty" yaml:"envoyExtensionPolicies,omitempty"` ExtensionServerPolicies []unstructured.Unstructured `json:"extensionServerPolicies,omitempty" yaml:"extensionServerPolicies,omitempty"` Backends []*egv1a1.Backend `json:"backends,omitempty" yaml:"backends,omitempty"` + HTTPRouteFilters []*egv1a1.HTTPRouteFilter `json:"httpFilters,omitempty" yaml:"httpFilters,omitempty"` } func NewResources() *Resources { @@ -86,6 +87,7 @@ func NewResources() *Resources { EnvoyExtensionPolicies: []*egv1a1.EnvoyExtensionPolicy{}, ExtensionServerPolicies: []unstructured.Unstructured{}, Backends: []*egv1a1.Backend{}, + HTTPRouteFilters: []*egv1a1.HTTPRouteFilter{}, } } diff --git a/internal/gatewayapi/resource/supported_kind.go b/internal/gatewayapi/resource/supported_kind.go index 5c2c21954a96..e9d76e66c3d8 100644 --- a/internal/gatewayapi/resource/supported_kind.go +++ b/internal/gatewayapi/resource/supported_kind.go @@ -26,4 +26,5 @@ const ( KindService = "Service" KindServiceImport = "ServiceImport" KindSecret = "Secret" + KindHTTPRouteFilter = "HTTPRouteFilter" ) diff --git a/internal/gatewayapi/resource/zz_generated.deepcopy.go b/internal/gatewayapi/resource/zz_generated.deepcopy.go index 61cf9dfb46e0..06925b1467d6 100644 --- a/internal/gatewayapi/resource/zz_generated.deepcopy.go +++ b/internal/gatewayapi/resource/zz_generated.deepcopy.go @@ -279,6 +279,17 @@ func (in *Resources) DeepCopyInto(out *Resources) { } } } + if in.HTTPRouteFilters != nil { + in, out := &in.HTTPRouteFilters, &out.HTTPRouteFilters + *out = make([]*v1alpha1.HTTPRouteFilter, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(v1alpha1.HTTPRouteFilter) + (*in).DeepCopyInto(*out) + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources. diff --git a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-regex-match-replace-http.in.yaml b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-regex-match-replace-http.in.yaml new file mode 100644 index 000000000000..fd0fea29fd45 --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-regex-match-replace-http.in.yaml @@ -0,0 +1,147 @@ +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 + hostname: "*.envoyproxy.io" + allowedRoutes: + namespaces: + from: All +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-1 + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/valid" + backendRefs: + - name: service-1 + port: 8080 + filters: + - type: ExtensionRef + extensionRef: + group: gateway.envoyproxy.io + kind: HTTPRouteFilter + name: valid +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-2 + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/host-and-regex-path" + backendRefs: + - name: service-1 + port: 8080 + filters: + - type: URLRewrite + urlRewrite: + hostname: "rewrite.com" + - type: ExtensionRef + extensionRef: + group: gateway.envoyproxy.io + kind: HTTPRouteFilter + name: valid +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-3 + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/regex-path-and-host" + backendRefs: + - name: service-1 + port: 8080 + filters: + - type: ExtensionRef + extensionRef: + group: gateway.envoyproxy.io + kind: HTTPRouteFilter + name: valid + - type: URLRewrite + urlRewrite: + hostname: "rewrite.com" +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-missing-substitution + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/missing-substitution" + backendRefs: + - name: service-1 + port: 8080 + filters: + - type: ExtensionRef + extensionRef: + group: gateway.envoyproxy.io + kind: HTTPRouteFilter + name: missing-substitution +httpFilters: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: HTTPRouteFilter + metadata: + name: valid + namespace: default + spec: + urlRewrite: + path: + type: ReplaceRegexMatch + replaceRegexMatch: + pattern: '.*' + substitution: foo +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: HTTPRouteFilter + metadata: + name: missing-substitution + namespace: default + spec: + urlRewrite: + path: + type: ReplaceRegexMatch + replaceRegexMatch: + pattern: '.*' diff --git a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-regex-match-replace-http.out.yaml b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-regex-match-replace-http.out.yaml new file mode 100644 index 000000000000..5c8d2527a1ff --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-regex-match-replace-http.out.yaml @@ -0,0 +1,366 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + hostname: '*.envoyproxy.io' + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 4 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-1 + namespace: default + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + filters: + - extensionRef: + group: gateway.envoyproxy.io + kind: HTTPRouteFilter + name: valid + type: ExtensionRef + matches: + - path: + value: /valid + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-2 + namespace: default + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + filters: + - type: URLRewrite + urlRewrite: + hostname: rewrite.com + - extensionRef: + group: gateway.envoyproxy.io + kind: HTTPRouteFilter + name: valid + type: ExtensionRef + matches: + - path: + value: /host-and-regex-path + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-3 + namespace: default + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + filters: + - extensionRef: + group: gateway.envoyproxy.io + kind: HTTPRouteFilter + name: valid + type: ExtensionRef + - type: URLRewrite + urlRewrite: + hostname: rewrite.com + matches: + - path: + value: /regex-path-and-host + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-missing-substitution + namespace: default + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + filters: + - extensionRef: + group: gateway.envoyproxy.io + kind: HTTPRouteFilter + name: missing-substitution + type: ExtensionRef + matches: + - path: + value: /missing-substitution + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-1/http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-1 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*.envoyproxy.io' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/default/httproute-missing-substitution/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: gateway.envoyproxy.io + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-missing-substitution + namespace: default + name: httproute/default/httproute-missing-substitution/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: /missing-substitution + urlRewrite: + path: + fullReplace: null + prefixMatchReplace: null + regexMatchReplace: + pattern: .* + substitution: "" + - 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 + metadata: + kind: HTTPRoute + name: httproute-2 + namespace: default + name: httproute/default/httproute-2/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: /host-and-regex-path + urlRewrite: + hostname: rewrite.com + path: + fullReplace: null + prefixMatchReplace: null + regexMatchReplace: + pattern: .* + substitution: foo + - destination: + name: httproute/default/httproute-3/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: gateway.envoyproxy.io + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-3 + namespace: default + name: httproute/default/httproute-3/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: /regex-path-and-host + urlRewrite: + hostname: rewrite.com + - 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 + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: /valid + urlRewrite: + path: + fullReplace: null + prefixMatchReplace: null + regexMatchReplace: + pattern: .* + substitution: foo diff --git a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-regex-match-replace-invalid.in.yaml b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-regex-match-replace-invalid.in.yaml new file mode 100644 index 000000000000..1ad75975b560 --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-regex-match-replace-invalid.in.yaml @@ -0,0 +1,230 @@ +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 + hostname: "*.envoyproxy.io" + allowedRoutes: + namespaces: + from: All +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-invalid-pattern + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/invalid-pattern" + backendRefs: + - name: service-1 + port: 8080 + filters: + - type: ExtensionRef + extensionRef: + group: gateway.envoyproxy.io + kind: HTTPRouteFilter + name: invalid-pattern +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-missing-pattern + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/missing-pattern" + backendRefs: + - name: service-1 + port: 8080 + filters: + - type: ExtensionRef + extensionRef: + group: gateway.envoyproxy.io + kind: HTTPRouteFilter + name: missing-pattern +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-multiple-path-rewrites-1 + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/ext-first" + backendRefs: + - name: service-1 + port: 8080 + filters: + - type: ExtensionRef + extensionRef: + group: gateway.envoyproxy.io + kind: HTTPRouteFilter + name: valid + - type: URLRewrite + urlRewrite: + path: + type: ReplacePrefixMatch + replacePrefixMatch: /rewrite +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-multiple-path-rewrites-2 + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/inline-first" + backendRefs: + - name: service-1 + port: 8080 + filters: + - type: URLRewrite + urlRewrite: + path: + type: ReplacePrefixMatch + replacePrefixMatch: /rewrite + - type: ExtensionRef + extensionRef: + group: gateway.envoyproxy.io + kind: HTTPRouteFilter + name: valid +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-multiple-regex-path-rewrites + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/two-regex" + backendRefs: + - name: service-1 + port: 8080 + filters: + - type: ExtensionRef + extensionRef: + group: gateway.envoyproxy.io + kind: HTTPRouteFilter + name: valid + - type: ExtensionRef + extensionRef: + group: gateway.envoyproxy.io + kind: HTTPRouteFilter + name: valid-2 +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-not-found + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/notfound" + backendRefs: + - name: service-1 + port: 8080 + filters: + - type: ExtensionRef + extensionRef: + group: gateway.envoyproxy.io + kind: HTTPRouteFilter + name: notfound +httpFilters: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: HTTPRouteFilter + metadata: + name: valid + namespace: default + spec: + urlRewrite: + path: + type: ReplaceRegexMatch + replaceRegexMatch: + pattern: '.*' + substitution: foo +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: HTTPRouteFilter + metadata: + name: valid-2 + namespace: default + spec: + urlRewrite: + path: + type: ReplaceRegexMatch + replaceRegexMatch: + pattern: '.*' + substitution: foo +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: HTTPRouteFilter + metadata: + name: invalid-pattern + namespace: default + spec: + urlRewrite: + path: + type: ReplaceRegexMatch + replaceRegexMatch: + pattern: '"([a-z]+)"*+?' + substitution: foo +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: HTTPRouteFilter + metadata: + name: missing-pattern + namespace: default + spec: + urlRewrite: + path: + type: ReplaceRegexMatch + replaceRegexMatch: + substitution: foo diff --git a/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-regex-match-replace-invalid.out.yaml b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-regex-match-replace-invalid.out.yaml new file mode 100644 index 000000000000..fb9e85a632df --- /dev/null +++ b/internal/gatewayapi/testdata/httproute-with-urlrewrite-filter-regex-match-replace-invalid.out.yaml @@ -0,0 +1,383 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + creationTimestamp: null + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + hostname: '*.envoyproxy.io' + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 6 + 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-invalid-pattern + namespace: default + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + filters: + - extensionRef: + group: gateway.envoyproxy.io + kind: HTTPRouteFilter + name: invalid-pattern + type: ExtensionRef + matches: + - path: + value: /invalid-pattern + status: + parents: + - conditions: + - lastTransitionTime: null + message: ReplaceRegexMatch must be a valid RE2 regular expression + reason: UnsupportedValue + status: "False" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-missing-pattern + namespace: default + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + filters: + - extensionRef: + group: gateway.envoyproxy.io + kind: HTTPRouteFilter + name: missing-pattern + type: ExtensionRef + matches: + - path: + value: /missing-pattern + status: + parents: + - conditions: + - lastTransitionTime: null + message: ReplaceRegexMatch Pattern must be set when rewrite path type is "ReplaceRegexMatch" + reason: UnsupportedValue + status: "False" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-multiple-path-rewrites-1 + namespace: default + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + filters: + - extensionRef: + group: gateway.envoyproxy.io + kind: HTTPRouteFilter + name: valid + type: ExtensionRef + - type: URLRewrite + urlRewrite: + path: + replacePrefixMatch: /rewrite + type: ReplacePrefixMatch + matches: + - path: + value: /ext-first + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-multiple-path-rewrites-2 + namespace: default + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + filters: + - type: URLRewrite + urlRewrite: + path: + replacePrefixMatch: /rewrite + type: ReplacePrefixMatch + - extensionRef: + group: gateway.envoyproxy.io + kind: HTTPRouteFilter + name: valid + type: ExtensionRef + matches: + - path: + value: /inline-first + status: + parents: + - conditions: + - lastTransitionTime: null + message: Cannot configure multiple urlRewrite filters for a single HTTPRouteRule + reason: UnsupportedValue + status: "False" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-multiple-regex-path-rewrites + namespace: default + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + filters: + - extensionRef: + group: gateway.envoyproxy.io + kind: HTTPRouteFilter + name: valid + type: ExtensionRef + - extensionRef: + group: gateway.envoyproxy.io + kind: HTTPRouteFilter + name: valid-2 + type: ExtensionRef + matches: + - path: + value: /two-regex + status: + parents: + - conditions: + - lastTransitionTime: null + message: Cannot configure multiple urlRewrite filters for a single HTTPRouteRule + reason: UnsupportedValue + status: "False" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + creationTimestamp: null + name: httproute-not-found + namespace: default + spec: + hostnames: + - gateway.envoyproxy.io + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + filters: + - extensionRef: + group: gateway.envoyproxy.io + kind: HTTPRouteFilter + name: notfound + type: ExtensionRef + matches: + - path: + value: /notfound + status: + parents: + - conditions: + - lastTransitionTime: null + message: 'Unable to translate HTTPRouteFilter: default/notfound' + reason: UnsupportedValue + status: "False" + type: Accepted + - lastTransitionTime: null + message: 'Unable to translate HTTPRouteFilter: default/notfound' + reason: BackendNotFound + status: "False" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - address: null + name: envoy-gateway/gateway-1/http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + name: envoy-gateway/gateway-1 +xdsIR: + envoy-gateway/gateway-1: + accessLog: + text: + - path: /dev/stdout + http: + - address: 0.0.0.0 + hostnames: + - '*.envoyproxy.io' + isHTTP2: false + metadata: + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + name: httproute/default/httproute-multiple-path-rewrites-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + protocol: HTTP + weight: 1 + hostname: gateway.envoyproxy.io + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-multiple-path-rewrites-1 + namespace: default + name: httproute/default/httproute-multiple-path-rewrites-1/rule/0/match/0/gateway_envoyproxy_io + pathMatch: + distinct: false + name: "" + prefix: /ext-first + urlRewrite: + path: + fullReplace: null + prefixMatchReplace: /rewrite diff --git a/internal/ir/xds.go b/internal/ir/xds.go index a40cd8547665..86a2d39569f2 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -51,8 +51,9 @@ var ( ErrDirectResponseStatusInvalid = errors.New("only HTTP status codes 100 - 599 are supported for DirectResponse") ErrRedirectUnsupportedStatus = errors.New("only HTTP status codes 301 and 302 are supported for redirect filters") ErrRedirectUnsupportedScheme = errors.New("only http and https are supported for the scheme in redirect filters") - ErrHTTPPathModifierDoubleReplace = errors.New("redirect filter cannot have a path modifier that supplies both fullPathReplace and prefixMatchReplace") - ErrHTTPPathModifierNoReplace = errors.New("redirect filter cannot have a path modifier that does not supply either fullPathReplace or prefixMatchReplace") + ErrHTTPPathModifierDoubleReplace = errors.New("redirect filter cannot have a path modifier that supplies more than one of fullPathReplace, prefixMatchReplace and regexMatchReplace") + ErrHTTPPathModifierNoReplace = errors.New("redirect filter cannot have a path modifier that does not supply either fullPathReplace, prefixMatchReplace or regexMatchReplace") + ErrHTTPPathRegexModifierNoSetting = errors.New("redirect filter cannot have a path modifier that does not supply either fullPathReplace, prefixMatchReplace or regexMatchReplace") ErrAddHeaderEmptyName = errors.New("header modifier filter cannot configure a header without a name to be added") ErrAddHeaderDuplicate = errors.New("header modifier filter attempts to add the same header more than once (case insensitive)") ErrRemoveHeaderDuplicate = errors.New("header modifier filter attempts to remove the same header more than once (case insensitive)") @@ -729,6 +730,18 @@ type UnstructuredRef struct { Object *unstructured.Unstructured `json:"object,omitempty" yaml:"object,omitempty"` } +// RegexMatchReplace defines the schema for modifying HTTP request path using regex. +// +// +k8s:deepcopy-gen=true +type RegexMatchReplace struct { + // Pattern matches a regular expression against the value of the HTTP Path.The regex string must + // adhere to the syntax documented in https://github.com/google/re2/wiki/Syntax. + Pattern string `json:"pattern" yaml:"pattern"` + // Substitution is an expression that replaces the matched portion.The expression may include numbered + // capture groups that adhere to syntax documented in https://github.com/google/re2/wiki/Syntax. + Substitution string `json:"substitution" yaml:"substitution"` +} + // CORS holds the Cross-Origin Resource Sharing (CORS) policy for the route. // // +k8s:deepcopy-gen=true @@ -1293,7 +1306,7 @@ func (r DirectResponse) Validate() error { // +k8s:deepcopy-gen=true type URLRewrite struct { // Path contains config for rewriting the path of the request. - Path *HTTPPathModifier `json:"path,omitempty" yaml:"path,omitempty"` + Path *ExtendedHTTPPathModifier `json:"path,omitempty" yaml:"path,omitempty"` // Hostname configures the replacement of the request's hostname. Hostname *string `json:"hostname,omitempty" yaml:"hostname,omitempty"` } @@ -1375,6 +1388,42 @@ func (r HTTPPathModifier) Validate() error { return errs } +// ExtendedHTTPPathModifier holds instructions for how to modify the path of a request on a redirect response +// with both core gateway-api and extended envoy gateway capabilities +// +k8s:deepcopy-gen=true +type ExtendedHTTPPathModifier struct { + HTTPPathModifier `json:",inline" yaml:",inline"` + // RegexMatchReplace provides a regex to match an a replacement to perform on the path. + RegexMatchReplace *RegexMatchReplace `json:"regexMatchReplace,omitempty" yaml:"regexMatchReplace,omitempty"` +} + +// Validate the fields within the HTTPPathModifier structure +func (r ExtendedHTTPPathModifier) Validate() error { + var errs error + + rewrites := []bool{r.RegexMatchReplace != nil, r.PrefixMatchReplace != nil, r.FullReplace != nil} + rwc := 0 + for _, rw := range rewrites { + if rw { + rwc++ + } + } + + if rwc > 1 { + errs = errors.Join(errs, ErrHTTPPathModifierDoubleReplace) + } + + if r.FullReplace == nil && r.PrefixMatchReplace == nil && r.RegexMatchReplace == nil { + errs = errors.Join(errs, ErrHTTPPathModifierNoReplace) + } + + if r.RegexMatchReplace != nil && (r.RegexMatchReplace.Pattern == "" || r.RegexMatchReplace.Substitution == "") { + errs = errors.Join(errs, ErrHTTPPathModifierNoReplace) + } + + return errs +} + // StringMatch holds the various match conditions. // Only one of Exact, Prefix, SafeRegex or Distinct can be set. // +k8s:deepcopy-gen=true diff --git a/internal/ir/xds_test.go b/internal/ir/xds_test.go index 882aa090e552..14b624f22f3f 100644 --- a/internal/ir/xds_test.go +++ b/internal/ir/xds_test.go @@ -309,8 +309,10 @@ var ( }, URLRewrite: &URLRewrite{ Hostname: ptr.To("rewrite.example.com"), - Path: &HTTPPathModifier{ - FullReplace: ptr.To("/rewrite"), + Path: &ExtendedHTTPPathModifier{ + HTTPPathModifier: HTTPPathModifier{ + FullReplace: ptr.To("/rewrite"), + }, }, }, } @@ -323,9 +325,11 @@ var ( }, URLRewrite: &URLRewrite{ Hostname: ptr.To("rewrite.example.com"), - Path: &HTTPPathModifier{ - FullReplace: ptr.To("/rewrite"), - PrefixMatchReplace: ptr.To("/rewrite"), + Path: &ExtendedHTTPPathModifier{ + HTTPPathModifier: HTTPPathModifier{ + FullReplace: ptr.To("/rewrite"), + PrefixMatchReplace: ptr.To("/rewrite"), + }, }, }, } diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go index 1639262be2e6..0b964d5fc41e 100644 --- a/internal/ir/zz_generated.deepcopy.go +++ b/internal/ir/zz_generated.deepcopy.go @@ -909,6 +909,27 @@ func (in *ExtProc) DeepCopy() *ExtProc { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExtendedHTTPPathModifier) DeepCopyInto(out *ExtendedHTTPPathModifier) { + *out = *in + in.HTTPPathModifier.DeepCopyInto(&out.HTTPPathModifier) + if in.RegexMatchReplace != nil { + in, out := &in.RegexMatchReplace, &out.RegexMatchReplace + *out = new(RegexMatchReplace) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtendedHTTPPathModifier. +func (in *ExtendedHTTPPathModifier) DeepCopy() *ExtendedHTTPPathModifier { + if in == nil { + return nil + } + out := new(ExtendedHTTPPathModifier) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FaultInjection) DeepCopyInto(out *FaultInjection) { *out = *in @@ -2296,6 +2317,21 @@ func (in *Redirect) DeepCopy() *Redirect { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RegexMatchReplace) DeepCopyInto(out *RegexMatchReplace) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RegexMatchReplace. +func (in *RegexMatchReplace) DeepCopy() *RegexMatchReplace { + if in == nil { + return nil + } + out := new(RegexMatchReplace) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ResourceMetadata) DeepCopyInto(out *ResourceMetadata) { *out = *in @@ -3136,7 +3172,7 @@ func (in *URLRewrite) DeepCopyInto(out *URLRewrite) { *out = *in if in.Path != nil { in, out := &in.Path, &out.Path - *out = new(HTTPPathModifier) + *out = new(ExtendedHTTPPathModifier) (*in).DeepCopyInto(*out) } if in.Hostname != nil { diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go index 877723fa6821..dac8f1780a86 100644 --- a/internal/provider/kubernetes/controller.go +++ b/internal/provider/kubernetes/controller.go @@ -148,6 +148,9 @@ type resourceMappings struct { // The key is the namespaced name, group and kind of the filter and the value is the // unstructured form of the resource. extensionRefFilters map[utils.NamespacedNameWithGroupKind]unstructured.Unstructured + // httpRouteFilters is a map of HTTPRouteFilters, where the key is the namespaced name, + // group and kind of the HTTPFilter. + httpRouteFilters map[utils.NamespacedNameWithGroupKind]*egv1a1.HTTPRouteFilter } func newResourceMapping() *resourceMappings { @@ -161,6 +164,7 @@ func newResourceMapping() *resourceMappings { allAssociatedUDPRoutes: sets.New[string](), allAssociatedBackendRefs: sets.New[gwapiv1.BackendObjectReference](), extensionRefFilters: map[utils.NamespacedNameWithGroupKind]unstructured.Unstructured{}, + httpRouteFilters: map[utils.NamespacedNameWithGroupKind]*egv1a1.HTTPRouteFilter{}, } } @@ -1568,6 +1572,27 @@ func (r *gatewayAPIReconciler) watchResources(ctx context.Context, mgr manager.M r.log.Info("Watching additional policy resource", "resource", gvk.String()) } + // Watch HTTPRouteFilter CRUDs and process affected HTTPRoute objects. + httpRouteFilter := []predicate.TypedPredicate[*egv1a1.HTTPRouteFilter]{ + predicate.TypedGenerationChangedPredicate[*egv1a1.HTTPRouteFilter]{}, + predicate.NewTypedPredicateFuncs[*egv1a1.HTTPRouteFilter](func(be *egv1a1.HTTPRouteFilter) bool { + return r.validateHTTPRouteFilterForReconcile(be) + }), + } + if r.namespaceLabel != nil { + httpRouteFilter = append(httpRouteFilter, predicate.NewTypedPredicateFuncs[*egv1a1.HTTPRouteFilter](func(be *egv1a1.HTTPRouteFilter) bool { + return r.hasMatchingNamespaceLabels(be) + })) + } + if err := c.Watch( + source.Kind(mgr.GetCache(), &egv1a1.HTTPRouteFilter{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, be *egv1a1.HTTPRouteFilter) []reconcile.Request { + return r.enqueueClass(ctx, be) + }), + httpRouteFilter...)); err != nil { + return err + } + return nil } diff --git a/internal/provider/kubernetes/filters.go b/internal/provider/kubernetes/filters.go index 985990fef147..109c0314dd0c 100644 --- a/internal/provider/kubernetes/filters.go +++ b/internal/provider/kubernetes/filters.go @@ -10,6 +10,8 @@ import ( "fmt" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" ) func (r *gatewayAPIReconciler) getExtensionRefFilters(ctx context.Context) ([]unstructured.Unstructured, error) { @@ -43,3 +45,12 @@ func (r *gatewayAPIReconciler) getExtensionRefFilters(ctx context.Context) ([]un return resourceItems, nil } + +func (r *gatewayAPIReconciler) getHTTPRouteFilters(ctx context.Context) ([]egv1a1.HTTPRouteFilter, error) { + httpFilterList := new(egv1a1.HTTPRouteFilterList) + if err := r.client.List(ctx, httpFilterList); err != nil { + return nil, fmt.Errorf("failed to list HTTPRouteFilters: %w", err) + } + + return httpFilterList.Items, nil +} diff --git a/internal/provider/kubernetes/indexers.go b/internal/provider/kubernetes/indexers.go index 395b1c6809d1..68a58dd872dd 100644 --- a/internal/provider/kubernetes/indexers.go +++ b/internal/provider/kubernetes/indexers.go @@ -45,6 +45,7 @@ const ( backendEnvoyProxyTelemetryIndex = "backendEnvoyProxyTelemetryIndex" secretEnvoyProxyIndex = "secretEnvoyProxyIndex" secretEnvoyExtensionPolicyIndex = "secretEnvoyExtensionPolicyIndex" + httpRouteFilterHTTPRouteIndex = "httpRouteFilterHTTPRouteIndex" ) func addReferenceGrantIndexers(ctx context.Context, mgr manager.Manager) error { @@ -73,6 +74,10 @@ func addHTTPRouteIndexers(ctx context.Context, mgr manager.Manager) error { return err } + if err := mgr.GetFieldIndexer().IndexField(ctx, &gwapiv1.HTTPRoute{}, httpRouteFilterHTTPRouteIndex, httpRouteFilterHTTPRouteIndexFunc); err != nil { + return err + } + return nil } @@ -100,8 +105,6 @@ func backendHTTPRouteIndexFunc(rawObj client.Object) []string { for _, rule := range httproute.Spec.Rules { for _, backend := range rule.BackendRefs { if backend.Kind == nil || string(*backend.Kind) == resource.KindService || string(*backend.Kind) == egv1a1.KindBackend { - // If an explicit Backend namespace is not provided, use the HTTPRoute namespace to - // lookup the provided Gateway Name. backendRefs = append(backendRefs, types.NamespacedName{ Namespace: gatewayapi.NamespaceDerefOr(backend.Namespace, httproute.Namespace), @@ -114,6 +117,26 @@ func backendHTTPRouteIndexFunc(rawObj client.Object) []string { return backendRefs } +func httpRouteFilterHTTPRouteIndexFunc(rawObj client.Object) []string { + httproute := rawObj.(*gwapiv1.HTTPRoute) + var httpRouteFilterRefs []string + for _, rule := range httproute.Spec.Rules { + for _, filter := range rule.Filters { + if filter.ExtensionRef != nil && string(filter.ExtensionRef.Kind) == resource.KindHTTPRouteFilter { + // If an explicit Backend namespace is not provided, use the HTTPRoute namespace to + // lookup the provided Gateway Name. + httpRouteFilterRefs = append(httpRouteFilterRefs, + types.NamespacedName{ + Namespace: httproute.Namespace, + Name: string(filter.ExtensionRef.Name), + }.String(), + ) + } + } + } + return httpRouteFilterRefs +} + func secretEnvoyProxyIndexFunc(rawObj client.Object) []string { ep := rawObj.(*egv1a1.EnvoyProxy) var secretReferences []string diff --git a/internal/provider/kubernetes/kubernetes_test.go b/internal/provider/kubernetes/kubernetes_test.go index d673def5c88f..669a790af559 100644 --- a/internal/provider/kubernetes/kubernetes_test.go +++ b/internal/provider/kubernetes/kubernetes_test.go @@ -1430,26 +1430,20 @@ func TestNamespaceSelectorProvider(t *testing.T) { require.NoError(t, cli.Delete(ctx, nonWatchedSvc)) }() - watchedHTTPRoute := test.GetHTTPRoute( - types.NamespacedName{ - Namespace: watchedNS.Name, - Name: "watched-http-route", - }, - watchedGateway.Name, - types.NamespacedName{Name: watchedSvc.Name}, 80) + watchedHTTPRoute := test.GetHTTPRoute(types.NamespacedName{ + Namespace: watchedNS.Name, + Name: "watched-http-route", + }, watchedGateway.Name, types.NamespacedName{Name: watchedSvc.Name}, 80, "") require.NoError(t, cli.Create(ctx, watchedHTTPRoute)) defer func() { require.NoError(t, cli.Delete(ctx, watchedHTTPRoute)) }() - nonWatchedHTTPRoute := test.GetHTTPRoute( - types.NamespacedName{ - Namespace: nonWatchedNS.Name, - Name: "non-watched-http-route", - }, - nonWatchedGateway.Name, - types.NamespacedName{Name: nonWatchedSvc.Name}, 8001) + nonWatchedHTTPRoute := test.GetHTTPRoute(types.NamespacedName{ + Namespace: nonWatchedNS.Name, + Name: "non-watched-http-route", + }, nonWatchedGateway.Name, types.NamespacedName{Name: nonWatchedSvc.Name}, 8001, "") require.NoError(t, cli.Create(ctx, nonWatchedHTTPRoute)) defer func() { require.NoError(t, cli.Delete(ctx, nonWatchedHTTPRoute)) diff --git a/internal/provider/kubernetes/predicates.go b/internal/provider/kubernetes/predicates.go index d14fceacb38f..9fb3fe86fd18 100644 --- a/internal/provider/kubernetes/predicates.go +++ b/internal/provider/kubernetes/predicates.go @@ -647,3 +647,29 @@ func (r *gatewayAPIReconciler) isExtensionPolicyReferencingSecret(nsName *types. return len(eepList.Items) > 0 } + +// isRouteReferencingHTTPRouteFilter returns true if the HTTPRouteFilter is referenced by an HTTPRoute +func (r *gatewayAPIReconciler) isRouteReferencingHTTPRouteFilter(nsName *types.NamespacedName) bool { + ctx := context.Background() + httpRouteList := &gwapiv1.HTTPRouteList{} + if err := r.client.List(ctx, httpRouteList, &client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector(httpRouteFilterHTTPRouteIndex, nsName.String()), + }); err != nil { + r.log.Error(err, "unable to find associated HTTPRoutes") + return false + } + + return len(httpRouteList.Items) != 0 +} + +// validateHTTPRouteFilterForReconcile tries finding the referencing HTTPRoute of the filter +func (r *gatewayAPIReconciler) validateHTTPRouteFilterForReconcile(obj client.Object) bool { + hrf, ok := obj.(*egv1a1.HTTPRouteFilter) + if !ok { + r.log.Info("unexpected object type, bypassing reconciliation", "object", obj) + return false + } + + nsName := utils.NamespacedName(hrf) + return r.isRouteReferencingHTTPRouteFilter(&nsName) +} diff --git a/internal/provider/kubernetes/predicates_test.go b/internal/provider/kubernetes/predicates_test.go index a442ddcf2a40..61a09ffb8aea 100644 --- a/internal/provider/kubernetes/predicates_test.go +++ b/internal/provider/kubernetes/predicates_test.go @@ -124,15 +124,10 @@ func TestGatewayClassHasMatchingNamespaceLabels(t *testing.T) { } t.Run(tc.name, func(t *testing.T) { res := r.hasMatchingNamespaceLabels( - test.GetHTTPRoute( - types.NamespacedName{ - Namespace: ns, - Name: "httproute-test", - }, - "scheduled-status-test", - types.NamespacedName{Name: "service"}, - 80, - )) + test.GetHTTPRoute(types.NamespacedName{ + Namespace: ns, + Name: "httproute-test", + }, "scheduled-status-test", types.NamespacedName{Name: "service"}, 80, "")) require.Equal(t, tc.expect, res) }) } @@ -405,7 +400,7 @@ func TestValidateEndpointSliceForReconcile(t *testing.T) { configs: []client.Object{ test.GetGatewayClass("test-gc", egv1a1.GatewayControllerName, nil), sampleGateway, - test.GetHTTPRoute(types.NamespacedName{Name: "httproute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}, 80), + test.GetHTTPRoute(types.NamespacedName{Name: "httproute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}, 80, ""), }, endpointSlice: test.GetEndpointSlice(types.NamespacedName{Name: "endpointslice"}, "other-service"), expect: false, @@ -415,7 +410,7 @@ func TestValidateEndpointSliceForReconcile(t *testing.T) { configs: []client.Object{ test.GetGatewayClass("test-gc", egv1a1.GatewayControllerName, nil), sampleGateway, - test.GetHTTPRoute(types.NamespacedName{Name: "httproute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}, 80), + test.GetHTTPRoute(types.NamespacedName{Name: "httproute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}, 80, ""), }, endpointSlice: test.GetEndpointSlice(types.NamespacedName{Name: "endpointslice"}, "service"), expect: true, @@ -570,7 +565,7 @@ func TestValidateServiceForReconcile(t *testing.T) { configs: []client.Object{ test.GetGatewayClass("test-gc", egv1a1.GatewayControllerName, nil), sampleGateway, - test.GetHTTPRoute(types.NamespacedName{Name: "httproute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}, 80), + test.GetHTTPRoute(types.NamespacedName{Name: "httproute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}, 80, ""), }, service: test.GetService(types.NamespacedName{Name: "service"}, nil, nil), expect: true, @@ -582,7 +577,7 @@ func TestValidateServiceForReconcile(t *testing.T) { name: "route service routes exist but with non-existing gateway reference", configs: []client.Object{ test.GetGatewayClass("test-gc", egv1a1.GatewayControllerName, nil), - test.GetHTTPRoute(types.NamespacedName{Name: "httproute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}, 80), + test.GetHTTPRoute(types.NamespacedName{Name: "httproute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}, 80, ""), }, service: test.GetService(types.NamespacedName{Name: "service"}, nil, nil), expect: true, @@ -966,18 +961,13 @@ func TestCheckObjectNamespaceLabels(t *testing.T) { }{ { name: "matching labels of namespace of the object is a subset of namespaceLabels", - object: test.GetHTTPRoute( - types.NamespacedName{ - Name: "foo-route", - Namespace: "foo", - }, - "eg", - types.NamespacedName{ - Name: "foo-svc", - Namespace: "foo", - }, - 8080, - ), + object: test.GetHTTPRoute(types.NamespacedName{ + Name: "foo-route", + Namespace: "foo", + }, "eg", types.NamespacedName{ + Name: "foo-svc", + Namespace: "foo", + }, 8080, ""), ns: &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", @@ -991,18 +981,13 @@ func TestCheckObjectNamespaceLabels(t *testing.T) { }, { name: "non-matching labels of namespace of the object is a subset of namespaceLabels", - object: test.GetHTTPRoute( - types.NamespacedName{ - Name: "bar-route", - Namespace: "bar", - }, - "eg", - types.NamespacedName{ - Name: "bar-svc", - Namespace: "bar", - }, - 8080, - ), + object: test.GetHTTPRoute(types.NamespacedName{ + Name: "bar-route", + Namespace: "bar", + }, "eg", types.NamespacedName{ + Name: "bar-svc", + Namespace: "bar", + }, 8080, ""), ns: &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: "bar", @@ -1149,3 +1134,64 @@ func TestMatchLabelsAndExpressions(t *testing.T) { }) } } + +// TestValidateHTTPRouteFilerForReconcile tests the vlidateHTTPRouteFilerForReconcile +// predicate function. +func TestValidateHTTPRouteFilerForReconcile(t *testing.T) { + sampleGWC := test.GetGatewayClass("test-gc", egv1a1.GatewayControllerName, nil) + sampleGateway := test.GetGateway(types.NamespacedName{Namespace: "default", Name: "scheduled-status-test"}, "test-gc", 8080) + sampleService := test.GetService(types.NamespacedName{Name: "service"}, nil, nil) + sampleHTTPRouteFilter := test.GetHTTPRouteFilter(types.NamespacedName{Name: "httproutefilter"}) + + testCases := []struct { + name string + configs []client.Object + httpRouteFilter client.Object + expect bool + }{ + { + name: "httproutefilter but not referenced by route", + configs: []client.Object{ + sampleGWC, + sampleGateway, + sampleService, + sampleHTTPRouteFilter, + }, + httpRouteFilter: sampleHTTPRouteFilter, + expect: false, + }, + { + name: "httproutefitler referenced by route", + configs: []client.Object{ + sampleGWC, + sampleGateway, + sampleService, + sampleHTTPRouteFilter, + test.GetHTTPRoute(types.NamespacedName{Name: "httproute-test"}, "scheduled-status-test", types.NamespacedName{Name: "service"}, 80, "httproutefilter"), + }, + httpRouteFilter: sampleHTTPRouteFilter, + expect: true, + }, + } + + // Create the reconciler. + logger := logging.DefaultLogger(egv1a1.LogLevelInfo) + + r := gatewayAPIReconciler{ + classController: egv1a1.GatewayControllerName, + log: logger, + } + + for _, tc := range testCases { + r.client = fakeclient.NewClientBuilder(). + WithScheme(envoygateway.GetScheme()). + WithObjects(tc.configs...). + WithIndex(&gwapiv1.HTTPRoute{}, backendHTTPRouteIndex, backendHTTPRouteIndexFunc). + WithIndex(&gwapiv1.HTTPRoute{}, httpRouteFilterHTTPRouteIndex, httpRouteFilterHTTPRouteIndexFunc). + Build() + t.Run(tc.name, func(t *testing.T) { + res := r.validateHTTPRouteFilterForReconcile(tc.httpRouteFilter) + require.Equal(t, tc.expect, res) + }) + } +} diff --git a/internal/provider/kubernetes/routes.go b/internal/provider/kubernetes/routes.go index d298e7e0e465..3a0a9f8131e6 100644 --- a/internal/provider/kubernetes/routes.go +++ b/internal/provider/kubernetes/routes.go @@ -16,6 +16,7 @@ import ( gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/gatewayapi" "github.com/envoyproxy/gateway/internal/gatewayapi/resource" "github.com/envoyproxy/gateway/internal/utils" @@ -231,6 +232,15 @@ func (r *gatewayAPIReconciler) processHTTPRoutes(ctx context.Context, gatewayNam ) error { httpRouteList := &gwapiv1.HTTPRouteList{} + httpFilters, err := r.getHTTPRouteFilters(ctx) + if err != nil { + return err + } + for i := range httpFilters { + filter := httpFilters[i] + resourceMap.httpRouteFilters[utils.GetNamespacedNameWithGroupKind(&filter)] = &filter + } + extensionRefFilters, err := r.getExtensionRefFilters(ctx) if err != nil { return err @@ -385,17 +395,29 @@ func (r *gatewayAPIReconciler) processHTTPRoutes(ctx context.Context, gatewayNam Kind: string(filter.ExtensionRef.Kind), }, } - extRefFilter, ok := resourceMap.extensionRefFilters[key] - if !ok { - r.log.Error( - errors.New("filter not found; bypassing rule"), - "Filter not found; bypassing rule", - "name", filter.ExtensionRef.Name, - "index", i) - continue - } - resourceTree.ExtensionRefFilters = append(resourceTree.ExtensionRefFilters, extRefFilter) + switch string(filter.ExtensionRef.Kind) { + case egv1a1.KindHTTPRouteFilter: + httpFilter, ok := resourceMap.httpRouteFilters[key] + if !ok { + r.log.Error(err, "HTTPRouteFilters not found; bypassing rule", "index", i) + continue + } + + resourceTree.HTTPRouteFilters = append(resourceTree.HTTPRouteFilters, httpFilter) + default: + extRefFilter, ok := resourceMap.extensionRefFilters[key] + if !ok { + r.log.Error( + errors.New("filter not found; bypassing rule"), + "Filter not found; bypassing rule", + "name", filter.ExtensionRef.Name, + "index", i) + continue + } + + resourceTree.ExtensionRefFilters = append(resourceTree.ExtensionRefFilters, extRefFilter) + } } } } diff --git a/internal/provider/kubernetes/test/utils.go b/internal/provider/kubernetes/test/utils.go index ae798b57d779..6fe50fa75bd7 100644 --- a/internal/provider/kubernetes/test/utils.go +++ b/internal/provider/kubernetes/test/utils.go @@ -107,8 +107,8 @@ func GetSecret(nsName types.NamespacedName) *corev1.Secret { } // GetHTTPRoute returns a sample HTTPRoute with a parent reference. -func GetHTTPRoute(nsName types.NamespacedName, parent string, serviceName types.NamespacedName, port int32) *gwapiv1.HTTPRoute { - return &gwapiv1.HTTPRoute{ +func GetHTTPRoute(nsName types.NamespacedName, parent string, serviceName types.NamespacedName, port int32, httpRouteFilterName string) *gwapiv1.HTTPRoute { + httpRoute := &gwapiv1.HTTPRoute{ ObjectMeta: metav1.ObjectMeta{ Namespace: nsName.Namespace, Name: nsName.Name, @@ -135,6 +135,21 @@ func GetHTTPRoute(nsName types.NamespacedName, parent string, serviceName types. }, }, } + + if httpRouteFilterName != "" { + httpRoute.Spec.Rules[0].Filters = []gwapiv1.HTTPRouteFilter{ + { + Type: gwapiv1.HTTPRouteFilterExtensionRef, + ExtensionRef: &gwapiv1.LocalObjectReference{ + Group: egv1a1.GroupName, + Kind: egv1a1.KindHTTPRouteFilter, + Name: gwapiv1.ObjectName(httpRouteFilterName), + }, + }, + } + } + + return httpRoute } // GetGRPCRoute returns a sample GRPCRoute with a parent reference. @@ -329,3 +344,24 @@ func GetEndpointSlice(nsName types.NamespacedName, svcName string) *discoveryv1. }, } } + +// GetHTTPRouteFilter returns a sample Service with labels and ports. +func GetHTTPRouteFilter(nsName types.NamespacedName) *egv1a1.HTTPRouteFilter { + return &egv1a1.HTTPRouteFilter{ + ObjectMeta: metav1.ObjectMeta{ + Name: nsName.Name, + Namespace: nsName.Namespace, + }, + Spec: egv1a1.HTTPRouteFilterSpec{ + URLRewrite: &egv1a1.HTTPURLRewriteFilter{ + Path: &egv1a1.HTTPPathModifier{ + Type: egv1a1.RegexHTTPPathModifier, + ReplaceRegexMatch: &egv1a1.ReplaceRegexMatch{ + Pattern: "foo", + Substitution: "bar", + }, + }, + }, + }, + } +} diff --git a/internal/xds/translator/route.go b/internal/xds/translator/route.go index 42f17ff94f18..a8ec4a291d5b 100644 --- a/internal/xds/translator/route.go +++ b/internal/xds/translator/route.go @@ -386,14 +386,15 @@ func buildXdsURLRewriteAction(destName string, urlRewrite *ir.URLRewrite, pathMa } if urlRewrite.Path != nil { - if urlRewrite.Path.FullReplace != nil { + switch { + case urlRewrite.Path.FullReplace != nil: routeAction.RegexRewrite = &matcherv3.RegexMatchAndSubstitute{ Pattern: &matcherv3.RegexMatcher{ Regex: "^/.*$", }, Substitution: *urlRewrite.Path.FullReplace, } - } else if urlRewrite.Path.PrefixMatchReplace != nil { + case urlRewrite.Path.PrefixMatchReplace != nil: // Circumvent the case of "//" when the replace string is "/" // An empty replace string does not seem to solve the issue so we are using // a regex match and replace instead @@ -406,6 +407,13 @@ func buildXdsURLRewriteAction(destName string, urlRewrite *ir.URLRewrite, pathMa // and the urlRewrite.Path.PrefixMatchReplace suffix with / the upstream will get unwanted / routeAction.PrefixRewrite = strings.TrimSuffix(*urlRewrite.Path.PrefixMatchReplace, "/") } + case urlRewrite.Path.RegexMatchReplace != nil: + routeAction.RegexRewrite = &matcherv3.RegexMatchAndSubstitute{ + Pattern: &matcherv3.RegexMatcher{ + Regex: urlRewrite.Path.RegexMatchReplace.Pattern, + }, + Substitution: urlRewrite.Path.RegexMatchReplace.Substitution, + } } } diff --git a/internal/xds/translator/testdata/in/xds-ir/http-route-rewrite-url-regex.yaml b/internal/xds/translator/testdata/in/xds-ir/http-route-rewrite-url-regex.yaml new file mode 100644 index 000000000000..0389201186eb --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/http-route-rewrite-url-regex.yaml @@ -0,0 +1,26 @@ +name: "http-route" +http: +- name: "first-listener" + address: "0.0.0.0" + port: 10080 + hostnames: + - "*" + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + routes: + - name: "rewrite-route" + pathMatch: + prefix: "/origin" + hostname: gateway.envoyproxy.io + destination: + name: "rewrite-route" + settings: + - endpoints: + - host: "1.2.3.4" + port: 50000 + urlRewrite: + path: + regexMatchReplace: + pattern: '^/service/([^/]+)(/.*)$' + substitution: '\2/instance/\1' diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-regex.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-regex.clusters.yaml new file mode 100644 index 000000000000..3a2b7308d8e1 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-regex.clusters.yaml @@ -0,0 +1,17 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: + localityWeightedLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_ONLY + edsClusterConfig: + edsConfig: + ads: {} + resourceApiVersion: V3 + serviceName: rewrite-route + lbPolicy: LEAST_REQUEST + name: rewrite-route + outlierDetection: {} + perConnectionBufferLimitBytes: 32768 + type: EDS diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-regex.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-regex.endpoints.yaml new file mode 100644 index 000000000000..ca1ef21c989e --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-regex.endpoints.yaml @@ -0,0 +1,12 @@ +- clusterName: rewrite-route + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: 1.2.3.4 + portValue: 50000 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: rewrite-route/backend/0 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-regex.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-regex.listeners.yaml new file mode 100644 index 000000000000..c3fb113017a9 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-regex.listeners.yaml @@ -0,0 +1,34 @@ +- address: + socketAddress: + address: 0.0.0.0 + portValue: 10080 + defaultFilterChain: + filters: + - name: envoy.filters.network.http_connection_manager + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + commonHttpProtocolOptions: + headersWithUnderscoresAction: REJECT_REQUEST + http2ProtocolOptions: + initialConnectionWindowSize: 1048576 + initialStreamWindowSize: 65536 + maxConcurrentStreams: 100 + httpFilters: + - name: envoy.filters.http.router + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + suppressEnvoyHeaders: true + mergeSlashes: true + normalizePath: true + pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: first-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: http-10080 + useRemoteAddress: true + name: first-listener + name: first-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-regex.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-regex.routes.yaml new file mode 100644 index 000000000000..20d4e99ef68c --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-url-regex.routes.yaml @@ -0,0 +1,18 @@ +- ignorePortInHostMatching: true + name: first-listener + virtualHosts: + - domains: + - gateway.envoyproxy.io + name: first-listener/gateway_envoyproxy_io + routes: + - match: + pathSeparatedPrefix: /origin + name: rewrite-route + route: + cluster: rewrite-route + regexRewrite: + pattern: + regex: ^/service/([^/]+)(/.*)$ + substitution: \2/instance/\1 + upgradeConfigs: + - upgradeType: websocket diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index d02a1686171c..b716d7ad3f0e 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -1905,7 +1905,7 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | | `type` | _[HTTPPathModifierType](#httppathmodifiertype)_ | true | | -| `replaceRegexMatch` | _[ReplaceRegexMatch](#replaceregexmatch)_ | true | ReplaceRegexMatch defines a path regex rewrite. The path portions matched by the regex pattern are replaced by the defined substitution.
https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-field-config-route-v3-routeaction-regex-rewrite
Some examples:
(1) replaceRegexMatch:
pattern: ^/service/([^/]+)(/.*)$
substitution: \2/instance/\1
Would transform /service/foo/v1/api into /v1/api/instance/foo.
(2) replaceRegexMatch:
pattern: one
substitution: two
Would transform /xxx/one/yyy/one/zzz into /xxx/two/yyy/two/zzz.
(3) replaceRegexMatch:
pattern: ^(.*?)one(.*)$
substitution: \1two\2
Would transform /xxx/one/yyy/one/zzz into /xxx/two/yyy/one/zzz.
(3) replaceRegexMatch:
pattern: (?i)/xxx/
substitution: /yyy/
Would transform path /aaa/XxX/bbb into /aaa/yyy/bbb (case-insensitive). | +| `replaceRegexMatch` | _[ReplaceRegexMatch](#replaceregexmatch)_ | false | ReplaceRegexMatch defines a path regex rewrite. The path portions matched by the regex pattern are replaced by the defined substitution.
https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-field-config-route-v3-routeaction-regex-rewrite
Some examples:
(1) replaceRegexMatch:
pattern: ^/service/([^/]+)(/.*)$
substitution: \2/instance/\1
Would transform /service/foo/v1/api into /v1/api/instance/foo.
(2) replaceRegexMatch:
pattern: one
substitution: two
Would transform /xxx/one/yyy/one/zzz into /xxx/two/yyy/two/zzz.
(3) replaceRegexMatch:
pattern: ^(.*?)one(.*)$
substitution: \1two\2
Would transform /xxx/one/yyy/one/zzz into /xxx/two/yyy/one/zzz.
(3) replaceRegexMatch:
pattern: (?i)/xxx/
substitution: /yyy/
Would transform path /aaa/XxX/bbb into /aaa/yyy/bbb (case-insensitive). | #### HTTPPathModifierType diff --git a/site/content/en/latest/tasks/traffic/http-urlrewrite.md b/site/content/en/latest/tasks/traffic/http-urlrewrite.md index 67915f93fcfe..a643d775a570 100644 --- a/site/content/en/latest/tasks/traffic/http-urlrewrite.md +++ b/site/content/en/latest/tasks/traffic/http-urlrewrite.md @@ -275,6 +275,160 @@ $ curl -L -vvv --header "Host: path.rewrite.example" "http://${GATEWAY_HOST}/get You can see that the `X-Envoy-Original-Path` is `/get/origin/path/extra`, but the actual path is `/force/replace/fullpath`. +## Rewrite URL Path with Regex + +In addition to core Gateway-API rewrite options, Envoy Gateway supports extended rewrite options through the [HTTPRouteFilter][] API. +The `HTTPRouteFilter` API can be configured to use [RE2][]-compatible regex matchers and substitutions to rewrite a portion of the url. +In the example below, requests sent to `http://${GATEWAY_HOST}/service/xxx/yyy` (where `xxx` is a single path portion and `yyy` is one or more path portions) +are rewritten to `http://${GATEWAY_HOST}/yyy/instance/xxx`. The entire path is matched and rewritten using capture groups. + +{{< tabpane text=true >}} +{{% tab header="Apply from stdin" %}} + +```shell +cat <}} + +The HTTPRoute status should indicate that it has been accepted and is bound to the example Gateway. + +```shell +kubectl get httproute/http-filter-url-rewrite -o yaml +``` + +Querying `http://${GATEWAY_HOST}/get/origin/path/extra` should rewrite the request to +`http://${GATEWAY_HOST}/force/replace/fullpath`. + +```console +$ curl -L -vvv --header "Host: path.regex.rewrite.example" "http://${GATEWAY_HOST}/get/origin/path/extra" +... +> GET /service/foo/v1/api HTTP/1.1 +> Host: path.regex.rewrite.example +> User-Agent: curl/8.7.1 +> Accept: */* +> +* Request completely sent off +< HTTP/1.1 200 OK +< content-type: application/json +< x-content-type-options: nosniff +< date: Mon, 16 Sep 2024 18:49:48 GMT +< content-length: 482 +< +{ + "path": "/v1/api/instance/foo", + "host": "path.regex.rewrite.example", + "method": "GET", + "proto": "HTTP/1.1", + "headers": { + "Accept": [ + "*/*" + ], + "User-Agent": [ + "curl/8.7.1" + ], + "X-Envoy-Internal": [ + "true" + ], + "X-Forwarded-For": [ + "10.244.0.37" + ], + "X-Forwarded-Proto": [ + "http" + ], + "X-Request-Id": [ + "24a5958f-1bfa-4694-a9c1-807d5139a18a" + ] + }, + "namespace": "default", + "ingress": "", + "service": "", + "pod": "backend-765694d47f-lzmpm" +... +``` + +You can see that the path is rewritten from `/service/foo/v1/api`, to `/v1/api/instance/foo`. + ## Rewrite Host Name You can configure to rewrite the hostname like below. In this example, any requests sent to @@ -402,3 +556,5 @@ $ curl -L -vvv --header "Host: path.rewrite.example" "http://${GATEWAY_HOST}/get You can see that the `X-Forwarded-Host` is `path.rewrite.example`, but the actual host is `envoygateway.io`. [HTTPURLRewriteFilter]: https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPURLRewriteFilter +[HTTPRouteFilter]: ../../../api/extension_types#httproutefilter +[RE2]: https://github.com/google/re2/wiki/Syntax \ No newline at end of file diff --git a/site/content/zh/latest/api/extension_types.md b/site/content/zh/latest/api/extension_types.md index d02a1686171c..b716d7ad3f0e 100644 --- a/site/content/zh/latest/api/extension_types.md +++ b/site/content/zh/latest/api/extension_types.md @@ -1905,7 +1905,7 @@ _Appears in:_ | Field | Type | Required | Description | | --- | --- | --- | --- | | `type` | _[HTTPPathModifierType](#httppathmodifiertype)_ | true | | -| `replaceRegexMatch` | _[ReplaceRegexMatch](#replaceregexmatch)_ | true | ReplaceRegexMatch defines a path regex rewrite. The path portions matched by the regex pattern are replaced by the defined substitution.
https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-field-config-route-v3-routeaction-regex-rewrite
Some examples:
(1) replaceRegexMatch:
pattern: ^/service/([^/]+)(/.*)$
substitution: \2/instance/\1
Would transform /service/foo/v1/api into /v1/api/instance/foo.
(2) replaceRegexMatch:
pattern: one
substitution: two
Would transform /xxx/one/yyy/one/zzz into /xxx/two/yyy/two/zzz.
(3) replaceRegexMatch:
pattern: ^(.*?)one(.*)$
substitution: \1two\2
Would transform /xxx/one/yyy/one/zzz into /xxx/two/yyy/one/zzz.
(3) replaceRegexMatch:
pattern: (?i)/xxx/
substitution: /yyy/
Would transform path /aaa/XxX/bbb into /aaa/yyy/bbb (case-insensitive). | +| `replaceRegexMatch` | _[ReplaceRegexMatch](#replaceregexmatch)_ | false | ReplaceRegexMatch defines a path regex rewrite. The path portions matched by the regex pattern are replaced by the defined substitution.
https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-field-config-route-v3-routeaction-regex-rewrite
Some examples:
(1) replaceRegexMatch:
pattern: ^/service/([^/]+)(/.*)$
substitution: \2/instance/\1
Would transform /service/foo/v1/api into /v1/api/instance/foo.
(2) replaceRegexMatch:
pattern: one
substitution: two
Would transform /xxx/one/yyy/one/zzz into /xxx/two/yyy/two/zzz.
(3) replaceRegexMatch:
pattern: ^(.*?)one(.*)$
substitution: \1two\2
Would transform /xxx/one/yyy/one/zzz into /xxx/two/yyy/one/zzz.
(3) replaceRegexMatch:
pattern: (?i)/xxx/
substitution: /yyy/
Would transform path /aaa/XxX/bbb into /aaa/yyy/bbb (case-insensitive). | #### HTTPPathModifierType diff --git a/test/cel-validation/httproutefilter_test.go b/test/cel-validation/httproutefilter_test.go new file mode 100644 index 000000000000..e9ebf380fb6d --- /dev/null +++ b/test/cel-validation/httproutefilter_test.go @@ -0,0 +1,120 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +//go:build celvalidation +// +build celvalidation + +package celvalidation + +import ( + "context" + "fmt" + "strings" + "testing" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" +) + +func TestHTTPRouteFilter(t *testing.T) { + ctx := context.Background() + baseHTTPRouteFilter := egv1a1.HTTPRouteFilter{ + ObjectMeta: metav1.ObjectMeta{ + Name: "hrf", + Namespace: metav1.NamespaceDefault, + }, + Spec: egv1a1.HTTPRouteFilterSpec{}, + } + + cases := []struct { + desc string + mutate func(httproutefilter *egv1a1.HTTPRouteFilter) + mutateStatus func(httproutefilter *egv1a1.HTTPRouteFilter) + wantErrors []string + }{ + { + desc: "Valid RegexHTTPPathModifier", + mutate: func(httproutefilter *egv1a1.HTTPRouteFilter) { + httproutefilter.Spec = egv1a1.HTTPRouteFilterSpec{ + URLRewrite: &egv1a1.HTTPURLRewriteFilter{ + Path: &egv1a1.HTTPPathModifier{ + Type: egv1a1.RegexHTTPPathModifier, + ReplaceRegexMatch: &egv1a1.ReplaceRegexMatch{ + Pattern: "foo", + Substitution: "bar", + }, + }, + }, + } + }, + wantErrors: []string{}, + }, + { + desc: "invalid RegexHTTPPathModifier missing settings", + mutate: func(httproutefilter *egv1a1.HTTPRouteFilter) { + httproutefilter.Spec = egv1a1.HTTPRouteFilterSpec{ + URLRewrite: &egv1a1.HTTPURLRewriteFilter{ + Path: &egv1a1.HTTPPathModifier{ + Type: egv1a1.RegexHTTPPathModifier, + }, + }, + } + }, + wantErrors: []string{"spec.urlRewrite.path: Invalid value: \"object\": If HTTPPathModifier type is ReplaceRegexMatch, replaceRegexMatch field needs to be set."}, + }, + { + desc: "invalid RegexHTTPPathModifier missing pattern and substitution", + mutate: func(httproutefilter *egv1a1.HTTPRouteFilter) { + httproutefilter.Spec = egv1a1.HTTPRouteFilterSpec{ + URLRewrite: &egv1a1.HTTPURLRewriteFilter{ + Path: &egv1a1.HTTPPathModifier{ + Type: egv1a1.RegexHTTPPathModifier, + ReplaceRegexMatch: &egv1a1.ReplaceRegexMatch{ + Pattern: "", + Substitution: "", + }, + }, + }, + } + }, + wantErrors: []string{ + "spec.urlRewrite.path.replaceRegexMatch.pattern: Invalid value: \"\": spec.urlRewrite.path.replaceRegexMatch.pattern in body should be at least 1 chars long", + }, + }, + } + + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + httpRouteFilter := baseHTTPRouteFilter.DeepCopy() + httpRouteFilter.Name = fmt.Sprintf("hrf-%v", time.Now().UnixNano()) + + if tc.mutate != nil { + tc.mutate(httpRouteFilter) + } + err := c.Create(ctx, httpRouteFilter) + + if tc.mutateStatus != nil { + tc.mutateStatus(httpRouteFilter) + err = c.Status().Update(ctx, httpRouteFilter) + } + + if (len(tc.wantErrors) != 0) != (err != nil) { + t.Fatalf("Unexpected response while creating HTTPRouteFilter; got err=\n%v\n;want error=%v", err, tc.wantErrors) + } + + var missingErrorStrings []string + for _, wantError := range tc.wantErrors { + if !strings.Contains(strings.ToLower(err.Error()), strings.ToLower(wantError)) { + missingErrorStrings = append(missingErrorStrings, wantError) + } + } + if len(missingErrorStrings) != 0 { + t.Errorf("Unexpected response while creating HTTPRouteFilter; got err=\n%v\n;missing strings within error=%q", err, missingErrorStrings) + } + }) + } +} diff --git a/test/e2e/testdata/httproute-rewrite-regex-path.yaml b/test/e2e/testdata/httproute-rewrite-regex-path.yaml new file mode 100644 index 000000000000..821550d73759 --- /dev/null +++ b/test/e2e/testdata/httproute-rewrite-regex-path.yaml @@ -0,0 +1,35 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: rewrite-regex-path + namespace: gateway-conformance-infra +spec: + parentRefs: + - name: same-namespace + rules: + - matches: + - path: + type: PathPrefix + value: / + filters: + - type: ExtensionRef + extensionRef: + group: gateway.envoyproxy.io + kind: HTTPRouteFilter + name: regex-path-rewrite + backendRefs: + - name: infra-backend-v1 + port: 8080 +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: HTTPRouteFilter +metadata: + name: regex-path-rewrite + namespace: gateway-conformance-infra +spec: + urlRewrite: + path: + type: ReplaceRegexMatch + replaceRegexMatch: + pattern: '^/service/([^/]+)(/.*)$' + substitution: '\2/instance/\1' diff --git a/test/e2e/tests/httproute_rewrite_regex_path.go b/test/e2e/tests/httproute_rewrite_regex_path.go new file mode 100644 index 000000000000..975d2ec88680 --- /dev/null +++ b/test/e2e/tests/httproute_rewrite_regex_path.go @@ -0,0 +1,59 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +//go:build e2e +// +build e2e + +package tests + +import ( + "testing" + + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/gateway-api/conformance/utils/http" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" +) + +func init() { + ConformanceTests = append(ConformanceTests, HTTPRouteRewriteRegexPath) +} + +var HTTPRouteRewriteRegexPath = suite.ConformanceTest{ + ShortName: "HTTPRouteRewriteRegexPath", + Description: "An HTTPRoute with path rewrite filter to replace a regex match", + Manifests: []string{"testdata/httproute-rewrite-regex-path.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + ns := "gateway-conformance-infra" + routeNN := types.NamespacedName{Name: "rewrite-regex-path", Namespace: ns} + gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} + gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) + kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) + + testCases := []http.ExpectedResponse{ + { + Request: http.Request{ + Path: "/service/foo/v1/api", + }, + ExpectedRequest: &http.ExpectedRequest{ + Request: http.Request{ + Path: "/v1/api/instance/foo", + }, + }, + Backend: "infra-backend-v1", + Namespace: ns, + }, + } + for i := range testCases { + // Declare tc here to avoid loop variable + // reuse issues across parallel tests. + tc := testCases[i] + t.Run(tc.GetTestCaseName(i), func(t *testing.T) { + t.Parallel() + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc) + }) + } + }, +} diff --git a/test/helm/gateway-helm/certjen-custom-scheduling.out.yaml b/test/helm/gateway-helm/certjen-custom-scheduling.out.yaml index 0bd873a34b9a..c280e54ca94d 100644 --- a/test/helm/gateway-helm/certjen-custom-scheduling.out.yaml +++ b/test/helm/gateway-helm/certjen-custom-scheduling.out.yaml @@ -127,6 +127,7 @@ rules: - securitypolicies - envoyextensionpolicies - backends + - httproutefilters verbs: - get - list diff --git a/test/helm/gateway-helm/control-plane-with-pdb.out.yaml b/test/helm/gateway-helm/control-plane-with-pdb.out.yaml index cd7ff1a53dcd..3db52f2bcbee 100644 --- a/test/helm/gateway-helm/control-plane-with-pdb.out.yaml +++ b/test/helm/gateway-helm/control-plane-with-pdb.out.yaml @@ -142,6 +142,7 @@ rules: - securitypolicies - envoyextensionpolicies - backends + - httproutefilters verbs: - get - list diff --git a/test/helm/gateway-helm/default-config.out.yaml b/test/helm/gateway-helm/default-config.out.yaml index 147c0f8ba707..0dd66b5c2099 100644 --- a/test/helm/gateway-helm/default-config.out.yaml +++ b/test/helm/gateway-helm/default-config.out.yaml @@ -127,6 +127,7 @@ rules: - securitypolicies - envoyextensionpolicies - backends + - httproutefilters verbs: - get - list diff --git a/test/helm/gateway-helm/deployment-custom-topology.out.yaml b/test/helm/gateway-helm/deployment-custom-topology.out.yaml index 7fdfef5e53e7..b9fc662515f6 100644 --- a/test/helm/gateway-helm/deployment-custom-topology.out.yaml +++ b/test/helm/gateway-helm/deployment-custom-topology.out.yaml @@ -127,6 +127,7 @@ rules: - securitypolicies - envoyextensionpolicies - backends + - httproutefilters verbs: - get - list diff --git a/test/helm/gateway-helm/deployment-images-config.out.yaml b/test/helm/gateway-helm/deployment-images-config.out.yaml index 5a2df408fe54..4da6c9a57f3c 100644 --- a/test/helm/gateway-helm/deployment-images-config.out.yaml +++ b/test/helm/gateway-helm/deployment-images-config.out.yaml @@ -127,6 +127,7 @@ rules: - securitypolicies - envoyextensionpolicies - backends + - httproutefilters verbs: - get - list diff --git a/test/helm/gateway-helm/envoy-gateway-config.out.yaml b/test/helm/gateway-helm/envoy-gateway-config.out.yaml index 233334d59721..056a0bde7d0b 100644 --- a/test/helm/gateway-helm/envoy-gateway-config.out.yaml +++ b/test/helm/gateway-helm/envoy-gateway-config.out.yaml @@ -129,6 +129,7 @@ rules: - securitypolicies - envoyextensionpolicies - backends + - httproutefilters verbs: - get - list diff --git a/test/helm/gateway-helm/global-images-config.out.yaml b/test/helm/gateway-helm/global-images-config.out.yaml index 95b98165d124..5eea20550703 100644 --- a/test/helm/gateway-helm/global-images-config.out.yaml +++ b/test/helm/gateway-helm/global-images-config.out.yaml @@ -131,6 +131,7 @@ rules: - securitypolicies - envoyextensionpolicies - backends + - httproutefilters verbs: - get - list