From ad613e58cdc9cc381fc354063a0b9792cf20646e Mon Sep 17 00:00:00 2001 From: Romain Date: Mon, 12 Aug 2024 14:28:04 +0200 Subject: [PATCH] Allow configuring rule syntax with Kubernetes Ingress annotation --- docs/content/migration/v2-to-v3-details.md | 13 +++++++++++++ .../content/routing/providers/kubernetes-ingress.md | 10 +++++++++- pkg/provider/kubernetes/ingress/annotations.go | 1 + pkg/provider/kubernetes/ingress/annotations_test.go | 4 ++++ .../ingress/fixtures/Ingress-with-annotations.yml | 1 + pkg/provider/kubernetes/ingress/kubernetes.go | 1 + pkg/provider/kubernetes/ingress/kubernetes_test.go | 1 + 7 files changed, 30 insertions(+), 1 deletion(-) diff --git a/docs/content/migration/v2-to-v3-details.md b/docs/content/migration/v2-to-v3-details.md index e40ab39f3..abd8ae587 100644 --- a/docs/content/migration/v2-to-v3-details.md +++ b/docs/content/migration/v2-to-v3-details.md @@ -541,6 +541,19 @@ it is now unsupported and would prevent Traefik to start. All Pilot related configuration should be removed from the static configuration. +### Kubernetes Ingress Path Matching + +In v3, the Kubernetes Ingress default path matching does not support regexes anymore. + +#### Remediation + +Two levels of remediation are possible: + +- Interpret the default path matcher `PathPrefix` with v2 syntax. +This can done globally for all routers with the [static configuration](#configure-the-default-syntax-in-static-configuration) or on a per-router basis by using the [traefik.ingress.kubernetes.io/router.rulesyntax](../routing/providers/kubernetes-ingress.md#annotations) annotation. + +- Adapt the path regex to be compatible with the Go regex syntax and change the default path matcher to use the `PathRegexp` matcher with the [`traefik.ingress.kubernetes.io/router.pathmatcher`](../routing/providers/kubernetes-ingress.md#annotations) annotation. + ## Operations Changes ### Traefik RBAC Update diff --git a/docs/content/routing/providers/kubernetes-ingress.md b/docs/content/routing/providers/kubernetes-ingress.md index 80bd7becb..158543b46 100644 --- a/docs/content/routing/providers/kubernetes-ingress.md +++ b/docs/content/routing/providers/kubernetes-ingress.md @@ -229,10 +229,18 @@ which in turn will create the resulting routers, services, handlers, etc. traefik.ingress.kubernetes.io/router.priority: "42" ``` +??? info "`traefik.ingress.kubernetes.io/router.rulesyntax`" + + See [rule syntax](../routers/index.md#rulesyntax) for more information. + + ```yaml + traefik.ingress.kubernetes.io/router.rulesyntax: "v2" + ``` + ??? info "`traefik.ingress.kubernetes.io/router.pathmatcher`" Overrides the default router rule type used for a path. - Only path-related matcher name can be specified: `Path`, `PathPrefix`. + Only path-related matcher name should be specified: `Path`, `PathPrefix` or `PathRegexp`. Default `PathPrefix` diff --git a/pkg/provider/kubernetes/ingress/annotations.go b/pkg/provider/kubernetes/ingress/annotations.go index 00d5d6649..144dd2a46 100644 --- a/pkg/provider/kubernetes/ingress/annotations.go +++ b/pkg/provider/kubernetes/ingress/annotations.go @@ -26,6 +26,7 @@ type RouterIng struct { EntryPoints []string `json:"entryPoints,omitempty"` Middlewares []string `json:"middlewares,omitempty"` Priority int `json:"priority,omitempty"` + RuleSyntax string `json:"ruleSyntax,omitempty"` TLS *dynamic.RouterTLSConfig `json:"tls,omitempty" label:"allowEmpty"` } diff --git a/pkg/provider/kubernetes/ingress/annotations_test.go b/pkg/provider/kubernetes/ingress/annotations_test.go index 646261894..7746b2623 100644 --- a/pkg/provider/kubernetes/ingress/annotations_test.go +++ b/pkg/provider/kubernetes/ingress/annotations_test.go @@ -24,6 +24,7 @@ func Test_parseRouterConfig(t *testing.T) { "traefik.ingress.kubernetes.io/router.entrypoints": "foobar,foobar", "traefik.ingress.kubernetes.io/router.middlewares": "foobar,foobar", "traefik.ingress.kubernetes.io/router.priority": "42", + "traefik.ingress.kubernetes.io/router.rulesyntax": "foobar", "traefik.ingress.kubernetes.io/router.tls": "true", "traefik.ingress.kubernetes.io/router.tls.certresolver": "foobar", "traefik.ingress.kubernetes.io/router.tls.domains.0.main": "foobar", @@ -38,6 +39,7 @@ func Test_parseRouterConfig(t *testing.T) { EntryPoints: []string{"foobar", "foobar"}, Middlewares: []string{"foobar", "foobar"}, Priority: 42, + RuleSyntax: "foobar", TLS: &dynamic.RouterTLSConfig{ CertResolver: "foobar", Domains: []types.Domain{ @@ -180,6 +182,7 @@ func Test_convertAnnotations(t *testing.T) { "traefik.ingress.kubernetes.io/router.entrypoints": "foobar,foobar", "traefik.ingress.kubernetes.io/router.middlewares": "foobar,foobar", "traefik.ingress.kubernetes.io/router.priority": "42", + "traefik.ingress.kubernetes.io/router.rulesyntax": "foobar", "traefik.ingress.kubernetes.io/router.tls": "true", "traefik.ingress.kubernetes.io/router.tls.certresolver": "foobar", "traefik.ingress.kubernetes.io/router.tls.domains.0.main": "foobar", @@ -194,6 +197,7 @@ func Test_convertAnnotations(t *testing.T) { "traefik.router.entrypoints": "foobar,foobar", "traefik.router.middlewares": "foobar,foobar", "traefik.router.priority": "42", + "traefik.router.rulesyntax": "foobar", "traefik.router.tls": "true", "traefik.router.tls.certresolver": "foobar", "traefik.router.tls.domains[0].main": "foobar", diff --git a/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-annotations.yml b/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-annotations.yml index bf4679f30..3a57a6345 100644 --- a/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-annotations.yml +++ b/pkg/provider/kubernetes/ingress/fixtures/Ingress-with-annotations.yml @@ -10,6 +10,7 @@ metadata: traefik.ingress.kubernetes.io/router.entrypoints: ep1,ep2 traefik.ingress.kubernetes.io/router.middlewares: md1,md2 traefik.ingress.kubernetes.io/router.priority: "42" + traefik.ingress.kubernetes.io/router.rulesyntax: "v2" traefik.ingress.kubernetes.io/router.tls: "true" traefik.ingress.kubernetes.io/router.tls.certresolver: foobar traefik.ingress.kubernetes.io/router.tls.domains.0.main: domain.com diff --git a/pkg/provider/kubernetes/ingress/kubernetes.go b/pkg/provider/kubernetes/ingress/kubernetes.go index 490271b8c..982cc09e8 100644 --- a/pkg/provider/kubernetes/ingress/kubernetes.go +++ b/pkg/provider/kubernetes/ingress/kubernetes.go @@ -760,6 +760,7 @@ func loadRouter(rule netv1.IngressRule, pa netv1.HTTPIngressPath, rtConfig *Rout } if rtConfig != nil && rtConfig.Router != nil { + rt.RuleSyntax = rtConfig.Router.RuleSyntax rt.Priority = rtConfig.Router.Priority rt.EntryPoints = rtConfig.Router.EntryPoints rt.Middlewares = rtConfig.Router.Middlewares diff --git a/pkg/provider/kubernetes/ingress/kubernetes_test.go b/pkg/provider/kubernetes/ingress/kubernetes_test.go index 5a4e3dd2b..9b736a454 100644 --- a/pkg/provider/kubernetes/ingress/kubernetes_test.go +++ b/pkg/provider/kubernetes/ingress/kubernetes_test.go @@ -96,6 +96,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) { Service: "testing-service1-80", Middlewares: []string{"md1", "md2"}, Priority: 42, + RuleSyntax: "v2", TLS: &dynamic.RouterTLSConfig{ CertResolver: "foobar", Domains: []types.Domain{