diff --git a/integration/k8s_conformance_test.go b/integration/k8s_conformance_test.go index afae520fc..0c1baa28e 100644 --- a/integration/k8s_conformance_test.go +++ b/integration/k8s_conformance_test.go @@ -204,12 +204,12 @@ func (s *K8sConformanceSuite) TestK8sGatewayAPIConformance() { ksuite.SupportHTTPRouteSchemeRedirect, ksuite.SupportHTTPRouteHostRewrite, ksuite.SupportHTTPRoutePathRewrite, + ksuite.SupportHTTPRoutePathRedirect, ), ExemptFeatures: sets.New( ksuite.SupportHTTPRouteRequestTimeout, ksuite.SupportHTTPRouteBackendTimeout, ksuite.SupportHTTPRouteResponseHeaderModification, - ksuite.SupportHTTPRoutePathRedirect, ksuite.SupportHTTPRouteRequestMirror, ksuite.SupportHTTPRouteRequestMultipleMirrors, ), diff --git a/integration/testdata/rawdata-gateway.json b/integration/testdata/rawdata-gateway.json index d321d987f..d4dd467b0 100644 --- a/integration/testdata/rawdata-gateway.json +++ b/integration/testdata/rawdata-gateway.json @@ -30,27 +30,27 @@ "traefik" ] }, - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27@kubernetesgateway": { + "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06@kubernetesgateway": { "entryPoints": [ "web" ], - "service": "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr", - "rule": "Host(`foo.com`) \u0026\u0026 (Path(`/bar`))", + "service": "default-http-app-1-my-gateway-web-0-wrr", + "rule": "Host(`foo.com`) \u0026\u0026 Path(`/bar`)", "ruleSyntax": "v3", - "priority": 99997, + "priority": 100008, "status": "enabled", "using": [ "web" ] }, - "default-http-app-1-my-https-gateway-websecure-af4b9876d1fe36359e27@kubernetesgateway": { + "default-http-app-1-my-https-gateway-websecure-0-1c0cf64bde37d9d0df06@kubernetesgateway": { "entryPoints": [ "websecure" ], - "service": "default-http-app-1-my-https-gateway-websecure-af4b9876d1fe36359e27-wrr", - "rule": "Host(`foo.com`) \u0026\u0026 (Path(`/bar`))", + "service": "default-http-app-1-my-https-gateway-websecure-0-wrr", + "rule": "Host(`foo.com`) \u0026\u0026 Path(`/bar`)", "ruleSyntax": "v3", - "priority": 99997, + "priority": 100008, "tls": {}, "status": "enabled", "using": [ @@ -96,7 +96,7 @@ "dashboard@internal" ] }, - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr@kubernetesgateway": { + "default-http-app-1-my-gateway-web-0-wrr@kubernetesgateway": { "weighted": { "services": [ { @@ -107,10 +107,10 @@ }, "status": "enabled", "usedBy": [ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27@kubernetesgateway" + "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06@kubernetesgateway" ] }, - "default-http-app-1-my-https-gateway-websecure-af4b9876d1fe36359e27-wrr@kubernetesgateway": { + "default-http-app-1-my-https-gateway-websecure-0-wrr@kubernetesgateway": { "weighted": { "services": [ { @@ -121,7 +121,7 @@ }, "status": "enabled", "usedBy": [ - "default-http-app-1-my-https-gateway-websecure-af4b9876d1fe36359e27@kubernetesgateway" + "default-http-app-1-my-https-gateway-websecure-0-1c0cf64bde37d9d0df06@kubernetesgateway" ] }, "default-whoami-80@kubernetesgateway": { @@ -150,11 +150,11 @@ } }, "tcpRouters": { - "default-tcp-app-1-my-tcp-gateway-footcp-e3b0c44298fc1c149afb@kubernetesgateway": { + "default-tcp-app-1-my-tcp-gateway-footcp@kubernetesgateway": { "entryPoints": [ "footcp" ], - "service": "default-tcp-app-1-my-tcp-gateway-footcp-e3b0c44298fc1c149afb-wrr-0", + "service": "default-tcp-app-1-my-tcp-gateway-footcp-wrr-0", "rule": "HostSNI(`*`)", "ruleSyntax": "v3", "priority": -1, @@ -163,11 +163,11 @@ "footcp" ] }, - "default-tcp-app-1-my-tls-gateway-footlsterminate-e3b0c44298fc1c149afb@kubernetesgateway": { + "default-tcp-app-1-my-tls-gateway-footlsterminate@kubernetesgateway": { "entryPoints": [ "footlsterminate" ], - "service": "default-tcp-app-1-my-tls-gateway-footlsterminate-e3b0c44298fc1c149afb-wrr-0", + "service": "default-tcp-app-1-my-tls-gateway-footlsterminate-wrr-0", "rule": "HostSNI(`*`)", "ruleSyntax": "v3", "priority": -1, @@ -197,7 +197,7 @@ } }, "tcpServices": { - "default-tcp-app-1-my-tcp-gateway-footcp-e3b0c44298fc1c149afb-wrr-0@kubernetesgateway": { + "default-tcp-app-1-my-tcp-gateway-footcp-wrr-0@kubernetesgateway": { "weighted": { "services": [ { @@ -208,10 +208,10 @@ }, "status": "enabled", "usedBy": [ - "default-tcp-app-1-my-tcp-gateway-footcp-e3b0c44298fc1c149afb@kubernetesgateway" + "default-tcp-app-1-my-tcp-gateway-footcp@kubernetesgateway" ] }, - "default-tcp-app-1-my-tls-gateway-footlsterminate-e3b0c44298fc1c149afb-wrr-0@kubernetesgateway": { + "default-tcp-app-1-my-tls-gateway-footlsterminate-wrr-0@kubernetesgateway": { "weighted": { "services": [ { @@ -222,7 +222,7 @@ }, "status": "enabled", "usedBy": [ - "default-tcp-app-1-my-tls-gateway-footlsterminate-e3b0c44298fc1c149afb@kubernetesgateway" + "default-tcp-app-1-my-tls-gateway-footlsterminate@kubernetesgateway" ] }, "default-tls-app-1-my-tls-gateway-footlspassthrough-2279fe75c5156dc5eb26-wrr-0@kubernetesgateway": { diff --git a/pkg/config/dynamic/middlewares.go b/pkg/config/dynamic/middlewares.go index 4042ed3eb..79462e9df 100644 --- a/pkg/config/dynamic/middlewares.go +++ b/pkg/config/dynamic/middlewares.go @@ -696,7 +696,10 @@ type RequestHeaderModifier struct { // RequestRedirect holds the request redirect middleware configuration. type RequestRedirect struct { - Regex string `json:"regex,omitempty"` - Replacement string `json:"replacement,omitempty"` - Permanent bool `json:"permanent,omitempty"` + Scheme *string `json:"scheme,omitempty"` + Hostname *string `json:"hostname,omitempty"` + Port *string `json:"port,omitempty"` + Path *string `json:"path,omitempty"` + PathPrefix *string `json:"pathPrefix,omitempty"` + StatusCode int `json:"statusCode,omitempty"` } diff --git a/pkg/config/dynamic/zz_generated.deepcopy.go b/pkg/config/dynamic/zz_generated.deepcopy.go index fb496fe66..9b8d26217 100644 --- a/pkg/config/dynamic/zz_generated.deepcopy.go +++ b/pkg/config/dynamic/zz_generated.deepcopy.go @@ -867,7 +867,7 @@ func (in *Middleware) DeepCopyInto(out *Middleware) { if in.RequestRedirect != nil { in, out := &in.RequestRedirect, &out.RequestRedirect *out = new(RequestRedirect) - **out = **in + (*in).DeepCopyInto(*out) } return } @@ -1115,6 +1115,31 @@ func (in *RequestHeaderModifier) DeepCopy() *RequestHeaderModifier { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RequestRedirect) DeepCopyInto(out *RequestRedirect) { *out = *in + if in.Scheme != nil { + in, out := &in.Scheme, &out.Scheme + *out = new(string) + **out = **in + } + if in.Hostname != nil { + in, out := &in.Hostname, &out.Hostname + *out = new(string) + **out = **in + } + if in.Port != nil { + in, out := &in.Port, &out.Port + *out = new(string) + **out = **in + } + if in.Path != nil { + in, out := &in.Path, &out.Path + *out = new(string) + **out = **in + } + if in.PathPrefix != nil { + in, out := &in.PathPrefix, &out.PathPrefix + *out = new(string) + **out = **in + } return } diff --git a/pkg/middlewares/gatewayapi/redirect/request_redirect.go b/pkg/middlewares/gatewayapi/redirect/request_redirect.go index d1dd984ba..b0ec9d7fe 100644 --- a/pkg/middlewares/gatewayapi/redirect/request_redirect.go +++ b/pkg/middlewares/gatewayapi/redirect/request_redirect.go @@ -2,133 +2,101 @@ package redirect import ( "context" + "fmt" + "net" "net/http" - "net/url" - "regexp" + "path" "strings" "github.com/traefik/traefik/v3/pkg/config/dynamic" "github.com/traefik/traefik/v3/pkg/middlewares" - "github.com/vulcand/oxy/v2/utils" "go.opentelemetry.io/otel/trace" ) const ( - schemeHTTP = "http" - schemeHTTPS = "https" - typeName = "RequestRedirect" + typeName = "RequestRedirect" ) -var uriRegexp = regexp.MustCompile(`^(https?):\/\/(\[[\w:.]+\]|[\w\._-]+)?(:\d+)?(.*)$`) +type redirect struct { + name string + next http.Handler + scheme *string + hostname *string + port *string + path *string + pathPrefix *string + statusCode int +} // NewRequestRedirect creates a redirect middleware. func NewRequestRedirect(ctx context.Context, next http.Handler, conf dynamic.RequestRedirect, name string) (http.Handler, error) { logger := middlewares.GetLogger(ctx, name, typeName) logger.Debug().Msg("Creating middleware") - logger.Debug().Msgf("Setting up redirection from %s to %s", conf.Regex, conf.Replacement) - re, err := regexp.Compile(conf.Regex) - if err != nil { - return nil, err + statusCode := conf.StatusCode + if statusCode == 0 { + statusCode = http.StatusFound + } + if statusCode != http.StatusMovedPermanently && statusCode != http.StatusFound { + return nil, fmt.Errorf("unsupported status code: %d", statusCode) } - return &redirect{ - regex: re, - replacement: conf.Replacement, - permanent: conf.Permanent, - errHandler: utils.DefaultHandler, - next: next, - name: name, - rawURL: rawURL, + return redirect{ + name: name, + next: next, + scheme: conf.Scheme, + hostname: conf.Hostname, + port: conf.Port, + path: conf.Path, + pathPrefix: conf.PathPrefix, + statusCode: statusCode, }, nil } -type redirect struct { - next http.Handler - regex *regexp.Regexp - replacement string - permanent bool - errHandler utils.ErrorHandler - name string - rawURL func(*http.Request) string -} - -func rawURL(req *http.Request) string { - scheme := schemeHTTP - host := req.Host - port := "" - uri := req.RequestURI - - if match := uriRegexp.FindStringSubmatch(req.RequestURI); len(match) > 0 { - scheme = match[1] - - if len(match[2]) > 0 { - host = match[2] - } - - if len(match[3]) > 0 { - port = match[3] - } - - uri = match[4] - } - - if req.TLS != nil { - scheme = schemeHTTPS - } - - return strings.Join([]string{scheme, "://", host, port, uri}, "") -} - -func (r *redirect) GetTracingInformation() (string, string, trace.SpanKind) { +func (r redirect) GetTracingInformation() (string, string, trace.SpanKind) { return r.name, typeName, trace.SpanKindInternal } -func (r *redirect) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - oldURL := r.rawURL(req) +func (r redirect) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + redirectURL := *req.URL + redirectURL.Host = req.Host - // If the Regexp doesn't match, skip to the next handler. - if !r.regex.MatchString(oldURL) { - r.next.ServeHTTP(rw, req) - return + if r.scheme != nil { + redirectURL.Scheme = *r.scheme } - // Apply a rewrite regexp to the URL. - newURL := r.regex.ReplaceAllString(oldURL, r.replacement) - - // Parse the rewritten URL and replace request URL with it. - parsedURL, err := url.Parse(newURL) - if err != nil { - r.errHandler.ServeHTTP(rw, req, err) - return + host := redirectURL.Hostname() + if r.hostname != nil { + host = *r.hostname } - handler := &moveHandler{location: parsedURL, permanent: r.permanent} - handler.ServeHTTP(rw, req) -} - -type moveHandler struct { - location *url.URL - permanent bool -} - -func (m *moveHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - rw.Header().Set("Location", m.location.String()) - - status := http.StatusFound - if req.Method != http.MethodGet { - status = http.StatusTemporaryRedirect + port := redirectURL.Port() + if r.port != nil { + port = *r.port } - if m.permanent { - status = http.StatusMovedPermanently - if req.Method != http.MethodGet { - status = http.StatusPermanentRedirect + if port != "" { + host = net.JoinHostPort(host, port) + } + redirectURL.Host = host + + if r.path != nil && r.pathPrefix == nil { + redirectURL.Path = *r.path + } + + if r.path != nil && r.pathPrefix != nil { + redirectURL.Path = path.Join(*r.path, strings.TrimPrefix(req.URL.Path, *r.pathPrefix)) + + // add the trailing slash if needed, as path.Join removes trailing slashes. + if strings.HasSuffix(req.URL.Path, "/") && !strings.HasSuffix(redirectURL.Path, "/") { + redirectURL.Path += "/" } } - rw.WriteHeader(status) - _, err := rw.Write([]byte(http.StatusText(status))) - if err != nil { + + rw.Header().Set("Location", redirectURL.String()) + + rw.WriteHeader(r.statusCode) + if _, err := rw.Write([]byte(http.StatusText(r.statusCode))); err != nil { http.Error(rw, err.Error(), http.StatusInternalServerError) } } diff --git a/pkg/middlewares/gatewayapi/redirect/request_redirect_test.go b/pkg/middlewares/gatewayapi/redirect/request_redirect_test.go index 6fe9050a5..97d324ced 100644 --- a/pkg/middlewares/gatewayapi/redirect/request_redirect_test.go +++ b/pkg/middlewares/gatewayapi/redirect/request_redirect_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/traefik/traefik/v3/pkg/config/dynamic" + "k8s.io/utils/ptr" ) func TestRequestRedirectHandler(t *testing.T) { @@ -24,49 +25,107 @@ func TestRequestRedirectHandler(t *testing.T) { expectedStatus int errorExpected bool }{ + { + desc: "wrong status code", + config: dynamic.RequestRedirect{ + Path: ptr.To("/baz"), + StatusCode: http.StatusOK, + }, + url: "http://foo.com:80/foo/bar", + errorExpected: true, + }, + { + desc: "replace path", + config: dynamic.RequestRedirect{ + Path: ptr.To("/baz"), + }, + url: "http://foo.com:80/foo/bar", + expectedURL: "http://foo.com:80/baz", + expectedStatus: http.StatusFound, + }, + { + desc: "replace path without trailing slash", + config: dynamic.RequestRedirect{ + Path: ptr.To("/baz"), + }, + url: "http://foo.com:80/foo/bar/", + expectedURL: "http://foo.com:80/baz", + expectedStatus: http.StatusFound, + }, + { + desc: "replace path with trailing slash", + config: dynamic.RequestRedirect{ + Path: ptr.To("/baz/"), + }, + url: "http://foo.com:80/foo/bar", + expectedURL: "http://foo.com:80/baz/", + expectedStatus: http.StatusFound, + }, + { + desc: "only hostname", + config: dynamic.RequestRedirect{ + Hostname: ptr.To("bar.com"), + }, + url: "http://foo.com:8080/foo/", + expectedURL: "http://bar.com:8080/foo/", + expectedStatus: http.StatusFound, + }, + { + desc: "replace prefix path", + config: dynamic.RequestRedirect{ + Path: ptr.To("/baz"), + PathPrefix: ptr.To("/foo"), + }, + url: "http://foo.com:80/foo/bar", + expectedURL: "http://foo.com:80/baz/bar", + expectedStatus: http.StatusFound, + }, + { + desc: "replace prefix path with trailing slash", + config: dynamic.RequestRedirect{ + Path: ptr.To("/baz"), + PathPrefix: ptr.To("/foo"), + }, + url: "http://foo.com:80/foo/bar/", + expectedURL: "http://foo.com:80/baz/bar/", + expectedStatus: http.StatusFound, + }, + { + desc: "replace prefix path without slash prefix", + config: dynamic.RequestRedirect{ + Path: ptr.To("baz"), + PathPrefix: ptr.To("/foo"), + }, + url: "http://foo.com:80/foo/bar", + expectedURL: "http://foo.com:80/baz/bar", + expectedStatus: http.StatusFound, + }, + { + desc: "replace prefix path without slash prefix", + config: dynamic.RequestRedirect{ + Path: ptr.To("/baz"), + PathPrefix: ptr.To("/foo/"), + }, + url: "http://foo.com:80/foo/bar", + expectedURL: "http://foo.com:80/baz/bar", + expectedStatus: http.StatusFound, + }, { desc: "simple redirection", config: dynamic.RequestRedirect{ - Regex: `^(?:http?:\/\/)(foo)(\.com)(:\d+)(.*)$`, - Replacement: "https://${1}bar$2:443$4", + Scheme: ptr.To("https"), + Hostname: ptr.To("foobar.com"), + Port: ptr.To("443"), }, url: "http://foo.com:80", expectedURL: "https://foobar.com:443", expectedStatus: http.StatusFound, }, - { - desc: "URL doesn't match regex", - config: dynamic.RequestRedirect{ - Regex: `^(?:http?:\/\/)(foo)(\.com)(:\d+)(.*)$`, - Replacement: "https://${1}bar$2:443$4", - }, - url: "http://bar.com:80", - expectedStatus: http.StatusOK, - }, - { - desc: "invalid rewritten URL", - config: dynamic.RequestRedirect{ - Regex: `^(.*)$`, - Replacement: "http://192.168.0.%31/", - }, - url: "http://foo.com:80", - expectedStatus: http.StatusBadGateway, - }, - { - desc: "invalid regex", - config: dynamic.RequestRedirect{ - Regex: `^(.*`, - Replacement: "$1", - }, - url: "http://foo.com:80", - errorExpected: true, - }, { desc: "HTTP to HTTPS permanent", config: dynamic.RequestRedirect{ - Regex: `^http://`, - Replacement: "https://$1", - Permanent: true, + Scheme: ptr.To("https"), + StatusCode: http.StatusMovedPermanently, }, url: "http://foo", expectedURL: "https://foo", @@ -75,9 +134,8 @@ func TestRequestRedirectHandler(t *testing.T) { { desc: "HTTPS to HTTP permanent", config: dynamic.RequestRedirect{ - Regex: `https://foo`, - Replacement: "http://foo", - Permanent: true, + Scheme: ptr.To("http"), + StatusCode: http.StatusMovedPermanently, }, secured: true, url: "https://foo", @@ -87,8 +145,8 @@ func TestRequestRedirectHandler(t *testing.T) { { desc: "HTTP to HTTPS", config: dynamic.RequestRedirect{ - Regex: `http://foo:80`, - Replacement: "https://foo:443", + Scheme: ptr.To("https"), + Port: ptr.To("443"), }, url: "http://foo:80", expectedURL: "https://foo:443", @@ -97,8 +155,8 @@ func TestRequestRedirectHandler(t *testing.T) { { desc: "HTTP to HTTPS, with X-Forwarded-Proto", config: dynamic.RequestRedirect{ - Regex: `http://foo:80`, - Replacement: "https://foo:443", + Scheme: ptr.To("https"), + Port: ptr.To("443"), }, url: "http://foo:80", headers: map[string]string{ @@ -110,8 +168,8 @@ func TestRequestRedirectHandler(t *testing.T) { { desc: "HTTPS to HTTP", config: dynamic.RequestRedirect{ - Regex: `https://foo:443`, - Replacement: "http://foo:80", + Scheme: ptr.To("http"), + Port: ptr.To("80"), }, secured: true, url: "https://foo:443", @@ -121,36 +179,13 @@ func TestRequestRedirectHandler(t *testing.T) { { desc: "HTTP to HTTP", config: dynamic.RequestRedirect{ - Regex: `http://foo:80`, - Replacement: "http://foo:88", + Scheme: ptr.To("http"), + Port: ptr.To("88"), }, url: "http://foo:80", expectedURL: "http://foo:88", expectedStatus: http.StatusFound, }, - { - desc: "HTTP to HTTP POST", - config: dynamic.RequestRedirect{ - Regex: `^http://`, - Replacement: "https://$1", - }, - url: "http://foo", - method: http.MethodPost, - expectedURL: "https://foo", - expectedStatus: http.StatusTemporaryRedirect, - }, - { - desc: "HTTP to HTTP POST permanent", - config: dynamic.RequestRedirect{ - Regex: `^http://`, - Replacement: "https://$1", - Permanent: true, - }, - url: "http://foo", - method: http.MethodPost, - expectedURL: "https://foo", - expectedStatus: http.StatusPermanentRedirect, - }, } for _, test := range testCases { @@ -188,7 +223,7 @@ func TestRequestRedirectHandler(t *testing.T) { assert.Equal(t, test.expectedStatus, recorder.Code) switch test.expectedStatus { - case http.StatusMovedPermanently, http.StatusFound, http.StatusTemporaryRedirect, http.StatusPermanentRedirect: + case http.StatusMovedPermanently, http.StatusFound: location, err := recorder.Result().Location() require.NoError(t, err) diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https.yml index dda03362e..5e03018a3 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https.yml @@ -39,7 +39,11 @@ spec: hostnames: - "example.org" rules: - - filters: + - matches: + - path: + type: PathPrefix + value: / + filters: - type: RequestRedirect requestRedirect: scheme: https diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https_with_hostname_and_port.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https_with_hostname_and_port.yml index 971a0ae81..5ad86c1b8 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https_with_hostname_and_port.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_http_to_https_with_hostname_and_port.yml @@ -39,7 +39,11 @@ spec: hostnames: - "example.org" rules: - - filters: + - matches: + - path: + type: PathPrefix + value: / + filters: - type: RequestRedirect requestRedirect: hostname: example.com diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_request_header_modifier.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_request_header_modifier.yml index d5cc3d0b6..5b2d00cf9 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_request_header_modifier.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/filter_request_header_modifier.yml @@ -39,7 +39,11 @@ spec: hostnames: - "example.org" rules: - - backendRefs: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: - name: whoami port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_multiple_host.yml b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_multiple_host.yml index 1f35bc7bc..248144586 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/httproute/with_multiple_host.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/httproute/with_multiple_host.yml @@ -37,7 +37,11 @@ spec: - "foo.com" - "bar.com" rules: - - backendRefs: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: - name: whoami port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/simple.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/simple.yml index ac15a9934..0fd6ee36e 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/simple.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/simple.yml @@ -107,7 +107,11 @@ spec: kind: Gateway group: gateway.networking.k8s.io rules: - - backendRefs: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: - name: whoami port: 80 weight: 1 @@ -131,7 +135,11 @@ spec: kind: Gateway group: gateway.networking.k8s.io rules: - - backendRefs: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: - name: whoamitcp port: 9000 weight: 1 @@ -151,7 +159,11 @@ spec: kind: Gateway group: gateway.networking.k8s.io rules: - - backendRefs: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: - name: whoamitcp port: 9000 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_protocol.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_protocol.yml index 3c11ca130..72a7584be 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_protocol.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_protocol.yml @@ -33,7 +33,11 @@ metadata: namespace: default spec: rules: - - backendRefs: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: - name: whoami port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_route_kind.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_route_kind.yml index 1e54ea49c..b6507d251 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_route_kind.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_bad_listener_route_kind.yml @@ -33,7 +33,11 @@ metadata: namespace: default spec: rules: - - backendRefs: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: - name: whoami port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_core_group.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_core_group.yml index d9a0c0a00..dcef7966d 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_core_group.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_core_group.yml @@ -89,7 +89,11 @@ spec: kind: Gateway group: gateway.networking.k8s.io rules: - - backendRefs: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: - name: whoami port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_incompatible_protocol_and_route_kind.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_incompatible_protocol_and_route_kind.yml index 6f983f1ec..58b2f4e6c 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_incompatible_protocol_and_route_kind.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_incompatible_protocol_and_route_kind.yml @@ -33,7 +33,11 @@ metadata: namespace: default spec: rules: - - backendRefs: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: - name: whoami port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_multiple_listeners_using_same_hostname_port_protocol.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_multiple_listeners_using_same_hostname_port_protocol.yml index b57edc456..272e363d7 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_multiple_listeners_using_same_hostname_port_protocol.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_multiple_listeners_using_same_hostname_port_protocol.yml @@ -119,7 +119,11 @@ metadata: namespace: default spec: rules: - - backendRefs: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: - name: whoami port: 80 weight: 1 @@ -134,7 +138,11 @@ metadata: namespace: default spec: rules: - - backendRefs: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: - name: whoami port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_all.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_all.yml index a05cf0c73..c2b525044 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_all.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_all.yml @@ -107,7 +107,11 @@ spec: kind: Gateway group: gateway.networking.k8s.io rules: - - backendRefs: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: - name: whoami port: 80 weight: 1 @@ -177,7 +181,11 @@ spec: kind: Gateway group: gateway.networking.k8s.io rules: - - backendRefs: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: - name: whoami-bar port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_same.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_same.yml index 78ce26173..8d470e749 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_same.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_same.yml @@ -107,7 +107,11 @@ spec: kind: Gateway group: gateway.networking.k8s.io rules: - - backendRefs: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: - name: whoami port: 80 weight: 1 @@ -177,7 +181,11 @@ spec: kind: Gateway group: gateway.networking.k8s.io rules: - - backendRefs: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: - name: whoami-bar port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_selector.yml b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_selector.yml index 1178ad391..a46e3dab6 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_selector.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/mixed/with_namespace_selector.yml @@ -130,7 +130,11 @@ spec: kind: Gateway group: gateway.networking.k8s.io rules: - - backendRefs: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: - name: whoami port: 80 weight: 1 @@ -200,7 +204,11 @@ spec: kind: Gateway group: gateway.networking.k8s.io rules: - - backendRefs: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: - name: whoami-bar port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/referencegrant/for_service.yml b/pkg/provider/kubernetes/gateway/fixtures/referencegrant/for_service.yml index 0975c9442..19b1cf14c 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/referencegrant/for_service.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/referencegrant/for_service.yml @@ -53,7 +53,11 @@ spec: kind: Gateway group: gateway.networking.k8s.io rules: - - backendRefs: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: - name: whoami-bar port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/referencegrant/for_service_missing.yml b/pkg/provider/kubernetes/gateway/fixtures/referencegrant/for_service_missing.yml index f68163547..fe238b5d5 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/referencegrant/for_service_missing.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/referencegrant/for_service_missing.yml @@ -38,7 +38,11 @@ spec: kind: Gateway group: gateway.networking.k8s.io rules: - - backendRefs: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: - name: whoami-bar port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/referencegrant/for_service_not_matching_from.yml b/pkg/provider/kubernetes/gateway/fixtures/referencegrant/for_service_not_matching_from.yml index 422fca0a5..5f29ee339 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/referencegrant/for_service_not_matching_from.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/referencegrant/for_service_not_matching_from.yml @@ -53,7 +53,11 @@ spec: kind: Gateway group: gateway.networking.k8s.io rules: - - backendRefs: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: - name: whoami-bar port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/referencegrant/for_service_not_matching_to.yml b/pkg/provider/kubernetes/gateway/fixtures/referencegrant/for_service_not_matching_to.yml index b5cff815e..903d9038a 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/referencegrant/for_service_not_matching_to.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/referencegrant/for_service_not_matching_to.yml @@ -54,7 +54,11 @@ spec: kind: Gateway group: gateway.networking.k8s.io rules: - - backendRefs: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: - name: whoami-bar port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_one_wildcard.yml b/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_one_wildcard.yml index 33b2cad7e..36fbb14f6 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_one_wildcard.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_one_wildcard.yml @@ -37,7 +37,11 @@ spec: - "foo.com" - "*.bar.com" rules: - - backendRefs: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: - name: whoami port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_wildcard.yml b/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_wildcard.yml index f069e9b3b..2ce58c6f0 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_wildcard.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/with_two_hosts_wildcard.yml @@ -37,7 +37,11 @@ spec: - "foo.com" - "*.foo.com" rules: - - backendRefs: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: - name: whoami port: 80 weight: 1 diff --git a/pkg/provider/kubernetes/gateway/httproute.go b/pkg/provider/kubernetes/gateway/httproute.go index bc5d67160..3f378002e 100644 --- a/pkg/provider/kubernetes/gateway/httproute.go +++ b/pkg/provider/kubernetes/gateway/httproute.go @@ -20,8 +20,8 @@ import ( gatev1 "sigs.k8s.io/gateway-api/apis/v1" ) -func (p *Provider) loadHTTPRoutes(ctx context.Context, client Client, gatewayListeners []gatewayListener, conf *dynamic.Configuration) { - routes, err := client.ListHTTPRoutes() +func (p *Provider) loadHTTPRoutes(ctx context.Context, gatewayListeners []gatewayListener, conf *dynamic.Configuration) { + routes, err := p.client.ListHTTPRoutes() if err != nil { log.Ctx(ctx).Error().Err(err).Msg("Unable to list HTTPRoutes") return @@ -74,7 +74,7 @@ func (p *Provider) loadHTTPRoutes(ctx context.Context, client Client, gatewayLis } } - routeConf, resolveRefCondition := p.loadHTTPRoute(logger.WithContext(ctx), client, listener, route, hostnames) + routeConf, resolveRefCondition := p.loadHTTPRoute(logger.WithContext(ctx), listener, route, hostnames) if accepted && listener.Attached { mergeHTTPConfiguration(routeConf, conf) } @@ -90,7 +90,7 @@ func (p *Provider) loadHTTPRoutes(ctx context.Context, client Client, gatewayLis Parents: parentStatuses, }, } - if err := client.UpdateHTTPRouteStatus(ctx, ktypes.NamespacedName{Namespace: route.Namespace, Name: route.Name}, status); err != nil { + if err := p.client.UpdateHTTPRouteStatus(ctx, ktypes.NamespacedName{Namespace: route.Namespace, Name: route.Name}, status); err != nil { logger.Error(). Err(err). Msg("Unable to update HTTPRoute status") @@ -98,8 +98,8 @@ func (p *Provider) loadHTTPRoutes(ctx context.Context, client Client, gatewayLis } } -func (p *Provider) loadHTTPRoute(ctx context.Context, client Client, listener gatewayListener, route *gatev1.HTTPRoute, hostnames []gatev1.Hostname) (*dynamic.Configuration, metav1.Condition) { - routeConf := &dynamic.Configuration{ +func (p *Provider) loadHTTPRoute(ctx context.Context, listener gatewayListener, route *gatev1.HTTPRoute, hostnames []gatev1.Hostname) (*dynamic.Configuration, metav1.Condition) { + conf := &dynamic.Configuration{ HTTP: &dynamic.HTTPConfiguration{ Routers: make(map[string]*dynamic.Router), Middlewares: make(map[string]*dynamic.Middleware), @@ -108,7 +108,7 @@ func (p *Provider) loadHTTPRoute(ctx context.Context, client Client, listener ga }, } - routeCondition := metav1.Condition{ + condition := metav1.Condition{ Type: string(gatev1.RouteConditionResolvedRefs), Status: metav1.ConditionTrue, ObservedGeneration: route.Generation, @@ -116,95 +116,101 @@ func (p *Provider) loadHTTPRoute(ctx context.Context, client Client, listener ga Reason: string(gatev1.RouteConditionResolvedRefs), } - for _, routeRule := range route.Spec.Rules { - rule, priority := buildRouterRule(hostnames, routeRule.Matches) - router := dynamic.Router{ - RuleSyntax: "v3", - Rule: rule, - Priority: priority, - EntryPoints: []string{listener.EPName}, - } - if listener.Protocol == gatev1.HTTPSProtocolType { - router.TLS = &dynamic.RouterTLSConfig{} - } - - // Adding the gateway desc and the entryPoint desc prevents overlapping of routers build from the same routes. - routerName := route.Name + "-" + listener.GWName + "-" + listener.EPName - routerKey := makeRouterKey(router.Rule, makeID(route.Namespace, routerName)) - - var wrr dynamic.WeightedRoundRobin - wrrName := provider.Normalize(routerKey + "-wrr") - - middlewares, err := p.loadMiddlewares(route.Namespace, routerKey, routeRule.Filters) - if err != nil { - log.Ctx(ctx).Error(). - Err(err). - Msg("Unable to load HTTPRoute filters") - - wrr.Services = append(wrr.Services, dynamic.WRRService{ + errWrr := dynamic.WeightedRoundRobin{ + Services: []dynamic.WRRService{ + { Name: "invalid-httproute-filter", Status: ptr.To(500), Weight: ptr.To(1), - }) - - routeConf.HTTP.Services[wrrName] = &dynamic.Service{Weighted: &wrr} - router.Service = wrrName - } else { - for name, middleware := range middlewares { - // If the middleware config is nil in the return of the loadMiddlewares function, - // it means that we just need a reference to that middleware. - if middleware != nil { - routeConf.HTTP.Middlewares[name] = middleware - } - - router.Middlewares = append(router.Middlewares, name) - } - - // Traefik internal service can be used only if there is only one BackendRef service reference. - if len(routeRule.BackendRefs) == 1 && isInternalService(routeRule.BackendRefs[0].BackendRef) { - router.Service = string(routeRule.BackendRefs[0].Name) - } else { - for _, backendRef := range routeRule.BackendRefs { - name, svc, errCondition := p.loadHTTPService(client, route, backendRef) - weight := ptr.To(int(ptr.Deref(backendRef.Weight, 1))) - if errCondition != nil { - routeCondition = *errCondition - wrr.Services = append(wrr.Services, dynamic.WRRService{ - Name: name, - Status: ptr.To(500), - Weight: weight, - }) - continue - } - - if svc != nil { - routeConf.HTTP.Services[name] = svc - } - - wrr.Services = append(wrr.Services, dynamic.WRRService{ - Name: name, - Weight: weight, - }) - } - - routeConf.HTTP.Services[wrrName] = &dynamic.Service{Weighted: &wrr} - router.Service = wrrName - } - } - - rt := &router - p.applyRouterTransform(ctx, rt, route) - - routerKey = provider.Normalize(routerKey) - routeConf.HTTP.Routers[routerKey] = rt + }, + }, } - return routeConf, routeCondition + for ri, routeRule := range route.Spec.Rules { + // Adding the gateway desc and the entryPoint desc prevents overlapping of routers build from the same routes. + routeKey := provider.Normalize(fmt.Sprintf("%s-%s-%s-%s-%d", route.Namespace, route.Name, listener.GWName, listener.EPName, ri)) + + for _, match := range routeRule.Matches { + rule, priority := buildMatchRule(hostnames, match) + router := dynamic.Router{ + RuleSyntax: "v3", + Rule: rule, + Priority: priority + len(route.Spec.Rules) - ri, + EntryPoints: []string{listener.EPName}, + } + if listener.Protocol == gatev1.HTTPSProtocolType { + router.TLS = &dynamic.RouterTLSConfig{} + } + + var err error + routerName := makeRouterName(rule, routeKey) + router.Middlewares, err = p.loadMiddlewares(conf, route.Namespace, routerName, routeRule.Filters, match.Path) + switch { + case err != nil: + log.Ctx(ctx).Error().Err(err).Msg("Unable to load HTTPRoute filters") + + errWrrName := routerName + "-err-wrr" + conf.HTTP.Services[errWrrName] = &dynamic.Service{Weighted: &errWrr} + router.Service = errWrrName + + case len(routeRule.BackendRefs) == 1 && isInternalService(routeRule.BackendRefs[0].BackendRef): + router.Service = string(routeRule.BackendRefs[0].Name) + + default: + var serviceCondition *metav1.Condition + router.Service, serviceCondition = p.loadService(conf, routeKey, routeRule, route) + if serviceCondition != nil { + condition = *serviceCondition + } + } + + p.applyRouterTransform(ctx, &router, route) + + conf.HTTP.Routers[routerName] = &router + } + } + + return conf, condition +} + +func (p *Provider) loadService(conf *dynamic.Configuration, routeKey string, routeRule gatev1.HTTPRouteRule, route *gatev1.HTTPRoute) (string, *metav1.Condition) { + name := routeKey + "-wrr" + if _, ok := conf.HTTP.Services[name]; ok { + return name, nil + } + + var wrr dynamic.WeightedRoundRobin + var condition *metav1.Condition + for _, backendRef := range routeRule.BackendRefs { + svcName, svc, errCondition := p.loadHTTPService(route, backendRef) + weight := ptr.To(int(ptr.Deref(backendRef.Weight, 1))) + if errCondition != nil { + condition = errCondition + wrr.Services = append(wrr.Services, dynamic.WRRService{ + Name: svcName, + Status: ptr.To(500), + Weight: weight, + }) + continue + } + + if svc != nil { + conf.HTTP.Services[svcName] = svc + } + + wrr.Services = append(wrr.Services, dynamic.WRRService{ + Name: svcName, + Weight: weight, + }) + } + + conf.HTTP.Services[name] = &dynamic.Service{Weighted: &wrr} + return name, condition } // loadHTTPService returns a dynamic.Service config corresponding to the given gatev1.HTTPBackendRef. // Note that the returned dynamic.Service config can be nil (for cross-provider, internal services, and backendFunc). -func (p *Provider) loadHTTPService(client Client, route *gatev1.HTTPRoute, backendRef gatev1.HTTPBackendRef) (string, *dynamic.Service, *metav1.Condition) { +func (p *Provider) loadHTTPService(route *gatev1.HTTPRoute, backendRef gatev1.HTTPBackendRef) (string, *dynamic.Service, *metav1.Condition) { kind := ptr.Deref(backendRef.Kind, "Service") group := groupCore @@ -217,9 +223,9 @@ func (p *Provider) loadHTTPService(client Client, route *gatev1.HTTPRoute, backe namespace = string(*backendRef.Namespace) } - serviceName := provider.Normalize(makeID(namespace, string(backendRef.Name))) + serviceName := provider.Normalize(namespace + "-" + string(backendRef.Name)) - if err := isReferenceGranted(client, groupGateway, kindHTTPRoute, route.Namespace, group, string(kind), string(backendRef.Name), namespace); err != nil { + if err := p.isReferenceGranted(groupGateway, kindHTTPRoute, route.Namespace, group, string(kind), string(backendRef.Name), namespace); err != nil { return serviceName, nil, &metav1.Condition{ Type: string(gatev1.RouteConditionResolvedRefs), Status: metav1.ConditionFalse, @@ -261,7 +267,7 @@ func (p *Provider) loadHTTPService(client Client, route *gatev1.HTTPRoute, backe portStr := strconv.FormatInt(int64(port), 10) serviceName = provider.Normalize(serviceName + "-" + portStr) - lb, err := loadHTTPServers(client, namespace, backendRef) + lb, err := p.loadHTTPServers(namespace, backendRef) if err != nil { return serviceName, nil, &metav1.Condition{ Type: string(gatev1.RouteConditionResolvedRefs), @@ -294,18 +300,17 @@ func (p *Provider) loadHTTPBackendRef(namespace string, backendRef gatev1.HTTPBa return backendFunc(string(backendRef.Name), namespace) } -func (p *Provider) loadMiddlewares(namespace, prefix string, filters []gatev1.HTTPRouteFilter) (map[string]*dynamic.Middleware, error) { +func (p *Provider) loadMiddlewares(conf *dynamic.Configuration, namespace, routerName string, filters []gatev1.HTTPRouteFilter, pathMatch *gatev1.HTTPPathMatch) ([]string, error) { middlewares := make(map[string]*dynamic.Middleware) - for i, filter := range filters { switch filter.Type { case gatev1.HTTPRouteFilterRequestRedirect: - middlewareName := provider.Normalize(fmt.Sprintf("%s-%s-%d", prefix, strings.ToLower(string(filter.Type)), i)) - middlewares[middlewareName] = createRedirectMiddleware(filter.RequestRedirect) + name := fmt.Sprintf("%s-%s-%d", routerName, strings.ToLower(string(filter.Type)), i) + middlewares[name] = createRequestRedirect(filter.RequestRedirect, pathMatch) case gatev1.HTTPRouteFilterRequestHeaderModifier: - middlewareName := provider.Normalize(fmt.Sprintf("%s-%s-%d", prefix, strings.ToLower(string(filter.Type)), i)) - middlewares[middlewareName] = createRequestHeaderModifier(filter.RequestHeaderModifier) + name := fmt.Sprintf("%s-%s-%d", routerName, strings.ToLower(string(filter.Type)), i) + middlewares[name] = createRequestHeaderModifier(filter.RequestHeaderModifier) case gatev1.HTTPRouteFilterExtensionRef: name, middleware, err := p.loadHTTPRouteFilterExtensionRef(namespace, filter.ExtensionRef) @@ -324,7 +329,16 @@ func (p *Provider) loadMiddlewares(namespace, prefix string, filters []gatev1.HT } } - return middlewares, nil + var middlewareNames []string + for name, middleware := range middlewares { + if middleware != nil { + conf.HTTP.Middlewares[name] = middleware + } + + middlewareNames = append(middlewareNames, name) + } + + return middlewareNames, nil } func (p *Provider) loadHTTPRouteFilterExtensionRef(namespace string, extensionRef *gatev1.LocalObjectReference) (string, *dynamic.Middleware, error) { @@ -343,9 +357,8 @@ func (p *Provider) loadHTTPRouteFilterExtensionRef(namespace string, extensionRe return filterFunc(string(extensionRef.Name), namespace) } -// TODO support cross namespace through ReferencePolicy. -func loadHTTPServers(client Client, namespace string, backendRef gatev1.HTTPBackendRef) (*dynamic.ServersLoadBalancer, error) { - service, exists, err := client.GetService(namespace, string(backendRef.Name)) +func (p *Provider) loadHTTPServers(namespace string, backendRef gatev1.HTTPBackendRef) (*dynamic.ServersLoadBalancer, error) { + service, exists, err := p.client.GetService(namespace, string(backendRef.Name)) if err != nil { return nil, fmt.Errorf("getting service: %w", err) } @@ -367,7 +380,7 @@ func loadHTTPServers(client Client, namespace string, backendRef gatev1.HTTPBack return nil, errors.New("service port not found") } - endpoints, endpointsExists, err := client.GetEndpoints(namespace, string(backendRef.Name)) + endpoints, endpointsExists, err := p.client.GetEndpoints(namespace, string(backendRef.Name)) if err != nil { return nil, fmt.Errorf("getting endpoints: %w", err) } @@ -440,7 +453,7 @@ func buildHostRule(hostnames []gatev1.Hostname) (string, int) { } } -// buildRouterRule builds the route rule and computes its priority. +// buildMatchRule builds the route rule and computes its priority. // The current priority computing is rather naive but aims to fulfill Conformance tests suite requirement. // The priority is computed to match the following precedence order: // @@ -451,60 +464,34 @@ func buildHostRule(hostnames []gatev1.Hostname) (string, int) { // * Largest number of query param matches. (not implemented) // // In case of multiple matches for a route, the maximum priority among all matches is retain. -func buildRouterRule(hostnames []gatev1.Hostname, routeMatches []gatev1.HTTPRouteMatch) (string, int) { - var matchesRules []string - var maxPriority int +func buildMatchRule(hostnames []gatev1.Hostname, match gatev1.HTTPRouteMatch) (string, int) { + path := ptr.Deref(match.Path, gatev1.HTTPPathMatch{ + Type: ptr.To(gatev1.PathMatchPathPrefix), + Value: ptr.To("/"), + }) - for _, match := range routeMatches { - path := ptr.Deref(match.Path, gatev1.HTTPPathMatch{ - Type: ptr.To(gatev1.PathMatchPathPrefix), - Value: ptr.To("/"), - }) + var priority int + var matchRules []string - var priority int - var matchRules []string + pathRule, pathPriority := buildPathRule(path) + matchRules = append(matchRules, pathRule) + priority += pathPriority - pathRule, pathPriority := buildPathRule(path) - matchRules = append(matchRules, pathRule) - priority += pathPriority + headerRules, headersPriority := buildHeaderRules(match.Headers) + matchRules = append(matchRules, headerRules...) + priority += headersPriority - headerRules, headersPriority := buildHeaderRules(match.Headers) - matchRules = append(matchRules, headerRules...) - priority += headersPriority - - matchesRules = append(matchesRules, strings.Join(matchRules, " && ")) - - if priority > maxPriority { - maxPriority = priority - } - } + matchRulesStr := strings.Join(matchRules, " && ") hostRule, hostPriority := buildHostRule(hostnames) - matchesRulesStr := strings.Join(matchesRules, " || ") - - if hostRule == "" && matchesRulesStr == "" { - return "PathPrefix(`/`)", 1 - } - - if hostRule != "" && matchesRulesStr == "" { - return hostRule, hostPriority - } - - // Enforce that, at the same priority, - // the route with fewer matches (more specific) matches first. - maxPriority -= len(matchesRules) * 10 - if maxPriority < 1 { - maxPriority = 1 - } - if hostRule == "" { - return matchesRulesStr, maxPriority + return matchRulesStr, priority } // A route with a host should match over the same route with no host. - maxPriority += hostPriority - return hostRule + " && " + "(" + matchesRulesStr + ")", maxPriority + priority += hostPriority + return hostRule + " && " + matchRulesStr, priority } func buildPathRule(pathMatch gatev1.HTTPPathMatch) (string, int) { @@ -573,29 +560,41 @@ func createRequestHeaderModifier(filter *gatev1.HTTPHeaderFilter) *dynamic.Middl } } -func createRedirectMiddleware(filter *gatev1.HTTPRequestRedirectFilter) *dynamic.Middleware { - filterScheme := ptr.Deref(filter.Scheme, "${scheme}") +func createRequestRedirect(filter *gatev1.HTTPRequestRedirectFilter, pathMatch *gatev1.HTTPPathMatch) *dynamic.Middleware { + var hostname *string + if filter.Hostname != nil { + hostname = ptr.To(string(*filter.Hostname)) + } - port := "${port}" + var port *string + filterScheme := ptr.Deref(filter.Scheme, "") if filterScheme == "http" || filterScheme == "https" { - port = "" + port = ptr.To("") } if filter.Port != nil { - port = fmt.Sprintf(":%d", *filter.Port) + port = ptr.To(fmt.Sprintf("%d", *filter.Port)) } - statusCode := ptr.Deref(filter.StatusCode, http.StatusFound) - - hostname := "${hostname}" - if filter.Hostname != nil && *filter.Hostname != "" { - hostname = string(*filter.Hostname) + var path *string + var pathPrefix *string + if filter.Path != nil { + switch filter.Path.Type { + case gatev1.FullPathHTTPPathModifier: + path = filter.Path.ReplaceFullPath + case gatev1.PrefixMatchHTTPPathModifier: + path = filter.Path.ReplacePrefixMatch + pathPrefix = pathMatch.Value + } } return &dynamic.Middleware{ RequestRedirect: &dynamic.RequestRedirect{ - Regex: `^(?P[a-z]+):\/\/(?P.+@)?(?P\[[\w:\.]+\]|[\w\._-]+)(?P:\d+)?\/(?P.*)`, - Replacement: fmt.Sprintf("%s://${userinfo}%s%s/${path}", filterScheme, hostname, port), - Permanent: statusCode == http.StatusMovedPermanently, + Scheme: filter.Scheme, + Hostname: hostname, + Port: port, + Path: path, + PathPrefix: pathPrefix, + StatusCode: ptr.Deref(filter.StatusCode, http.StatusFound), }, } } diff --git a/pkg/provider/kubernetes/gateway/httproute_test.go b/pkg/provider/kubernetes/gateway/httproute_test.go index 9e9833e40..bd74a04d0 100644 --- a/pkg/provider/kubernetes/gateway/httproute_test.go +++ b/pkg/provider/kubernetes/gateway/httproute_test.go @@ -69,10 +69,10 @@ func Test_buildHostRule(t *testing.T) { } } -func Test_buildRouterRule(t *testing.T) { +func Test_buildMatchRule(t *testing.T) { testCases := []struct { desc string - routeMatches []gatev1.HTTPRouteMatch + routeMatch gatev1.HTTPRouteMatch hostnames []gatev1.Hostname expectedRule string expectedPriority int @@ -84,187 +84,112 @@ func Test_buildRouterRule(t *testing.T) { expectedPriority: 1, }, { - desc: "One Host rule without matches", + desc: "One Host rule without match", hostnames: []gatev1.Hostname{"foo.com"}, - expectedRule: "Host(`foo.com`)", - expectedPriority: 7, + expectedRule: "Host(`foo.com`) && PathPrefix(`/`)", + expectedPriority: 8, }, { desc: "One HTTPRouteMatch with nil HTTPHeaderMatch", - routeMatches: []gatev1.HTTPRouteMatch{ - { - Path: ptr.To(gatev1.HTTPPathMatch{ - Type: ptr.To(gatev1.PathMatchPathPrefix), - Value: ptr.To("/"), - }), - Headers: nil, - }, + routeMatch: gatev1.HTTPRouteMatch{ + Path: ptr.To(gatev1.HTTPPathMatch{ + Type: ptr.To(gatev1.PathMatchPathPrefix), + Value: ptr.To("/"), + }), + Headers: nil, }, expectedRule: "PathPrefix(`/`)", expectedPriority: 1, }, { desc: "One HTTPRouteMatch with nil HTTPHeaderMatch Type", - routeMatches: []gatev1.HTTPRouteMatch{ - { - Path: ptr.To(gatev1.HTTPPathMatch{ - Type: ptr.To(gatev1.PathMatchPathPrefix), - Value: ptr.To("/"), - }), - Headers: []gatev1.HTTPHeaderMatch{ - {Name: "foo", Value: "bar"}, - }, + routeMatch: gatev1.HTTPRouteMatch{ + Path: ptr.To(gatev1.HTTPPathMatch{ + Type: ptr.To(gatev1.PathMatchPathPrefix), + Value: ptr.To("/"), + }), + Headers: []gatev1.HTTPHeaderMatch{ + {Name: "foo", Value: "bar"}, }, }, expectedRule: "PathPrefix(`/`) && Header(`foo`,`bar`)", - expectedPriority: 91, + expectedPriority: 101, }, { - desc: "One HTTPRouteMatch with nil HTTPPathMatch", - routeMatches: []gatev1.HTTPRouteMatch{ - {Path: nil}, - }, + desc: "One HTTPRouteMatch with nil HTTPPathMatch", + routeMatch: gatev1.HTTPRouteMatch{Path: nil}, expectedRule: "PathPrefix(`/`)", expectedPriority: 1, }, { desc: "One HTTPRouteMatch with nil HTTPPathMatch Type", - routeMatches: []gatev1.HTTPRouteMatch{ - { - Path: &gatev1.HTTPPathMatch{ - Type: nil, - Value: ptr.To("/foo/"), - }, + routeMatch: gatev1.HTTPRouteMatch{ + Path: &gatev1.HTTPPathMatch{ + Type: nil, + Value: ptr.To("/foo/"), }, }, expectedRule: "(Path(`/foo`) || PathPrefix(`/foo/`))", - expectedPriority: 10490, + expectedPriority: 10500, }, { desc: "One HTTPRouteMatch with nil HTTPPathMatch Values", - routeMatches: []gatev1.HTTPRouteMatch{ - { - Path: &gatev1.HTTPPathMatch{ - Type: ptr.To(gatev1.PathMatchExact), - Value: nil, - }, + routeMatch: gatev1.HTTPRouteMatch{ + Path: &gatev1.HTTPPathMatch{ + Type: ptr.To(gatev1.PathMatchExact), + Value: nil, }, }, expectedRule: "Path(`/`)", - expectedPriority: 99990, + expectedPriority: 100000, }, { - desc: "One Path in matches", - routeMatches: []gatev1.HTTPRouteMatch{ - { - Path: &gatev1.HTTPPathMatch{ - Type: ptr.To(gatev1.PathMatchExact), - Value: ptr.To("/foo/"), - }, + desc: "One Path", + routeMatch: gatev1.HTTPRouteMatch{ + Path: &gatev1.HTTPPathMatch{ + Type: ptr.To(gatev1.PathMatchExact), + Value: ptr.To("/foo/"), }, }, expectedRule: "Path(`/foo/`)", - expectedPriority: 99990, + expectedPriority: 100000, }, { - desc: "One Path in matches and another empty", - routeMatches: []gatev1.HTTPRouteMatch{ - { - Path: &gatev1.HTTPPathMatch{ - Type: ptr.To(gatev1.PathMatchExact), - Value: ptr.To("/foo/"), - }, + desc: "Path && Header", + routeMatch: gatev1.HTTPRouteMatch{ + Path: &gatev1.HTTPPathMatch{ + Type: ptr.To(gatev1.PathMatchExact), + Value: ptr.To("/foo/"), }, - {}, - }, - expectedRule: "Path(`/foo/`) || PathPrefix(`/`)", - expectedPriority: 99980, - }, - { - desc: "Path OR Header rules", - routeMatches: []gatev1.HTTPRouteMatch{ - { - Path: &gatev1.HTTPPathMatch{ - Type: ptr.To(gatev1.PathMatchExact), - Value: ptr.To("/foo/"), - }, - }, - { - Headers: []gatev1.HTTPHeaderMatch{ - { - Type: ptr.To(gatev1.HeaderMatchExact), - Name: "my-header", - Value: "foo", - }, - }, - }, - }, - expectedRule: "Path(`/foo/`) || PathPrefix(`/`) && Header(`my-header`,`foo`)", - expectedPriority: 99980, - }, - { - desc: "Path && Header rules", - routeMatches: []gatev1.HTTPRouteMatch{ - { - Path: &gatev1.HTTPPathMatch{ - Type: ptr.To(gatev1.PathMatchExact), - Value: ptr.To("/foo/"), - }, - Headers: []gatev1.HTTPHeaderMatch{ - { - Type: ptr.To(gatev1.HeaderMatchExact), - Name: "my-header", - Value: "foo", - }, + Headers: []gatev1.HTTPHeaderMatch{ + { + Type: ptr.To(gatev1.HeaderMatchExact), + Name: "my-header", + Value: "foo", }, }, }, expectedRule: "Path(`/foo/`) && Header(`my-header`,`foo`)", - expectedPriority: 100090, + expectedPriority: 100100, }, { - desc: "Host && Path && Header rules", + desc: "Host && Path && Header", hostnames: []gatev1.Hostname{"foo.com"}, - routeMatches: []gatev1.HTTPRouteMatch{ - { - Path: &gatev1.HTTPPathMatch{ - Type: ptr.To(gatev1.PathMatchExact), - Value: ptr.To("/foo/"), - }, - Headers: []gatev1.HTTPHeaderMatch{ - { - Type: ptr.To(gatev1.HeaderMatchExact), - Name: "my-header", - Value: "foo", - }, + routeMatch: gatev1.HTTPRouteMatch{ + Path: &gatev1.HTTPPathMatch{ + Type: ptr.To(gatev1.PathMatchExact), + Value: ptr.To("/foo/"), + }, + Headers: []gatev1.HTTPHeaderMatch{ + { + Type: ptr.To(gatev1.HeaderMatchExact), + Name: "my-header", + Value: "foo", }, }, }, - expectedRule: "Host(`foo.com`) && (Path(`/foo/`) && Header(`my-header`,`foo`))", - expectedPriority: 100097, - }, - { - desc: "Host && (Path || Header) rules", - hostnames: []gatev1.Hostname{"foo.com"}, - routeMatches: []gatev1.HTTPRouteMatch{ - { - Path: &gatev1.HTTPPathMatch{ - Type: ptr.To(gatev1.PathMatchExact), - Value: ptr.To("/foo/"), - }, - }, - { - Headers: []gatev1.HTTPHeaderMatch{ - { - Type: ptr.To(gatev1.HeaderMatchExact), - Name: "my-header", - Value: "foo", - }, - }, - }, - }, - expectedRule: "Host(`foo.com`) && (Path(`/foo/`) || PathPrefix(`/`) && Header(`my-header`,`foo`))", - expectedPriority: 99987, + expectedRule: "Host(`foo.com`) && Path(`/foo/`) && Header(`my-header`,`foo`)", + expectedPriority: 100107, }, } @@ -272,7 +197,7 @@ func Test_buildRouterRule(t *testing.T) { t.Run(test.desc, func(t *testing.T) { t.Parallel() - rule, priority := buildRouterRule(test.hostnames, test.routeMatches) + rule, priority := buildMatchRule(test.hostnames, test.routeMatch) assert.Equal(t, test.expectedRule, rule) assert.Equal(t, test.expectedPriority, priority) }) diff --git a/pkg/provider/kubernetes/gateway/kubernetes.go b/pkg/provider/kubernetes/gateway/kubernetes.go index 55ee9a999..6af304e0c 100644 --- a/pkg/provider/kubernetes/gateway/kubernetes.go +++ b/pkg/provider/kubernetes/gateway/kubernetes.go @@ -68,6 +68,7 @@ type Provider struct { lastConfiguration safe.Safe routerTransform k8s.RouterTransform + client *clientWrapper } // Entrypoint defines the available entry points. @@ -194,6 +195,14 @@ func (p *Provider) newK8sClient(ctx context.Context) (*clientWrapper, error) { // Init the provider. func (p *Provider) Init() error { + logger := log.With().Str(logs.ProviderName, providerName).Logger() + + var err error + p.client, err = p.newK8sClient(logger.WithContext(context.Background())) + if err != nil { + return fmt.Errorf("creating k8s client: %w", err) + } + return nil } @@ -202,14 +211,9 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. logger := log.With().Str(logs.ProviderName, providerName).Logger() ctxLog := logger.WithContext(context.Background()) - k8sClient, err := p.newK8sClient(ctxLog) - if err != nil { - return err - } - pool.GoCtx(func(ctxPool context.Context) { operation := func() error { - eventsChan, err := k8sClient.WatchAll(p.Namespaces, ctxPool.Done()) + eventsChan, err := p.client.WatchAll(p.Namespaces, ctxPool.Done()) if err != nil { logger.Error().Err(err).Msg("Error watching kubernetes events") timer := time.NewTimer(1 * time.Second) @@ -235,7 +239,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. // Note that event is the *first* event that came in during this throttling interval -- if we're hitting our throttle, we may have dropped events. // This is fine, because we don't treat different event types differently. // But if we do in the future, we'll need to track more information about the dropped events. - conf := p.loadConfigurationFromGateways(ctxLog, k8sClient) + conf := p.loadConfigurationFromGateways(ctxLog) confHash, err := hashstructure.Hash(conf, nil) switch { @@ -272,7 +276,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe. } // TODO Handle errors and update resources statuses (gatewayClass, gateway). -func (p *Provider) loadConfigurationFromGateways(ctx context.Context, client Client) *dynamic.Configuration { +func (p *Provider) loadConfigurationFromGateways(ctx context.Context) *dynamic.Configuration { conf := &dynamic.Configuration{ HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -293,13 +297,13 @@ func (p *Provider) loadConfigurationFromGateways(ctx context.Context, client Cli TLS: &dynamic.TLSConfiguration{}, } - addresses, err := p.gatewayAddresses(client) + addresses, err := p.gatewayAddresses() if err != nil { log.Ctx(ctx).Error().Err(err).Msg("Unable to get Gateway status addresses") return nil } - gatewayClasses, err := client.ListGatewayClasses() + gatewayClasses, err := p.client.ListGatewayClasses() if err != nil { log.Ctx(ctx).Error().Err(err).Msg("Unable to list GatewayClasses") return nil @@ -313,7 +317,7 @@ func (p *Provider) loadConfigurationFromGateways(ctx context.Context, client Cli gatewayClassNames[gatewayClass.Name] = struct{}{} - err := client.UpdateGatewayClassStatus(gatewayClass, metav1.Condition{ + err := p.client.UpdateGatewayClassStatus(gatewayClass, metav1.Condition{ Type: string(gatev1.GatewayClassConditionStatusAccepted), Status: metav1.ConditionTrue, ObservedGeneration: gatewayClass.Generation, @@ -330,7 +334,7 @@ func (p *Provider) loadConfigurationFromGateways(ctx context.Context, client Cli } } - gateways := client.ListGateways() + gateways := p.client.ListGateways() var gatewayListeners []gatewayListener for _, gateway := range gateways { @@ -343,14 +347,14 @@ func (p *Provider) loadConfigurationFromGateways(ctx context.Context, client Cli continue } - gatewayListeners = append(gatewayListeners, p.loadGatewayListeners(logger.WithContext(ctx), client, gateway, conf)...) + gatewayListeners = append(gatewayListeners, p.loadGatewayListeners(logger.WithContext(ctx), gateway, conf)...) } - p.loadHTTPRoutes(ctx, client, gatewayListeners, conf) + p.loadHTTPRoutes(ctx, gatewayListeners, conf) if p.ExperimentalChannel { - p.loadTCPRoutes(ctx, client, gatewayListeners, conf) - p.loadTLSRoutes(ctx, client, gatewayListeners, conf) + p.loadTCPRoutes(ctx, gatewayListeners, conf) + p.loadTLSRoutes(ctx, gatewayListeners, conf) } for _, gateway := range gateways { @@ -367,7 +371,7 @@ func (p *Provider) loadConfigurationFromGateways(ctx context.Context, client Cli } gatewayStatus, errG := p.makeGatewayStatus(gateway, listeners, addresses) - if err = client.UpdateGatewayStatus(gateway, gatewayStatus); err != nil { + if err = p.client.UpdateGatewayStatus(gateway, gatewayStatus); err != nil { logger.Error(). Err(err). Msg("Unable to update Gateway status") @@ -382,7 +386,7 @@ func (p *Provider) loadConfigurationFromGateways(ctx context.Context, client Cli return conf } -func (p *Provider) loadGatewayListeners(ctx context.Context, client Client, gateway *gatev1.Gateway, conf *dynamic.Configuration) []gatewayListener { +func (p *Provider) loadGatewayListeners(ctx context.Context, gateway *gatev1.Gateway, conf *dynamic.Configuration) []gatewayListener { tlsConfigs := make(map[string]*tls.CertAndStores) allocatedListeners := make(map[string]struct{}) gatewayListeners := make([]gatewayListener, len(gateway.Spec.Listeners)) @@ -420,7 +424,7 @@ func (p *Provider) loadGatewayListeners(ctx context.Context, client Client, gate gatewayListeners[i].EPName = ep allowedRoutes := ptr.Deref(listener.AllowedRoutes, gatev1.AllowedRoutes{Namespaces: &gatev1.RouteNamespaces{From: ptr.To(gatev1.NamespacesFromSame)}}) - gatewayListeners[i].AllowedNamespaces, err = allowedNamespaces(client, gateway.Namespace, allowedRoutes.Namespaces) + gatewayListeners[i].AllowedNamespaces, err = p.allowedNamespaces(gateway.Namespace, allowedRoutes.Namespaces) if err != nil { // update "ResolvedRefs" status true with "InvalidRoutesRef" reason gatewayListeners[i].Status.Conditions = append(gatewayListeners[i].Status.Conditions, metav1.Condition{ @@ -565,7 +569,7 @@ func (p *Provider) loadGatewayListeners(ctx context.Context, client Client, gate certificateNamespace = string(*certificateRef.Namespace) } - if err := isReferenceGranted(client, groupGateway, kindGateway, gateway.Namespace, groupCore, "Secret", string(certificateRef.Name), certificateNamespace); err != nil { + if err := p.isReferenceGranted(groupGateway, kindGateway, gateway.Namespace, groupCore, "Secret", string(certificateRef.Name), certificateNamespace); err != nil { gatewayListeners[i].Status.Conditions = append(gatewayListeners[i].Status.Conditions, metav1.Condition{ Type: string(gatev1.ListenerConditionResolvedRefs), Status: metav1.ConditionFalse, @@ -580,7 +584,7 @@ func (p *Provider) loadGatewayListeners(ctx context.Context, client Client, gate configKey := certificateNamespace + "/" + string(certificateRef.Name) if _, tlsExists := tlsConfigs[configKey]; !tlsExists { - tlsConf, err := getTLS(client, certificateRef.Name, certificateNamespace) + tlsConf, err := p.getTLS(certificateRef.Name, certificateNamespace) if err != nil { // update "ResolvedRefs" status false with "InvalidCertificateRef" reason // update "Programmed" status false with "Invalid" reason @@ -703,7 +707,7 @@ func (p *Provider) makeGatewayStatus(gateway *gatev1.Gateway, listeners []gatewa return gatewayStatus, nil } -func (p *Provider) gatewayAddresses(client Client) ([]gatev1.GatewayStatusAddress, error) { +func (p *Provider) gatewayAddresses() ([]gatev1.GatewayStatusAddress, error) { if p.StatusAddress == nil { return nil, nil } @@ -724,7 +728,7 @@ func (p *Provider) gatewayAddresses(client Client) ([]gatev1.GatewayStatusAddres svcRef := p.StatusAddress.Service if svcRef.Name != "" && svcRef.Namespace != "" { - svc, exists, err := client.GetService(svcRef.Namespace, svcRef.Name) + svc, exists, err := p.client.GetService(svcRef.Namespace, svcRef.Name) if err != nil { return nil, fmt.Errorf("unable to get service: %w", err) } @@ -772,6 +776,71 @@ func (p *Provider) entryPointName(port gatev1.PortNumber, protocol gatev1.Protoc return "", fmt.Errorf("no matching entryPoint for port %d and protocol %q", port, protocol) } +func (p *Provider) isReferenceGranted(fromGroup, fromKind, fromNamespace, toGroup, toKind, toName, toNamespace string) error { + if toNamespace == fromNamespace { + return nil + } + + refGrants, err := p.client.ListReferenceGrants(toNamespace) + if err != nil { + return fmt.Errorf("listing ReferenceGrant: %w", err) + } + + refGrants = filterReferenceGrantsFrom(refGrants, fromGroup, fromKind, fromNamespace) + refGrants = filterReferenceGrantsTo(refGrants, toGroup, toKind, toName) + if len(refGrants) == 0 { + return errors.New("missing ReferenceGrant") + } + + return nil +} + +func (p *Provider) getTLS(secretName gatev1.ObjectName, namespace string) (*tls.CertAndStores, error) { + secret, exists, err := p.client.GetSecret(namespace, string(secretName)) + if err != nil { + return nil, fmt.Errorf("failed to fetch secret %s/%s: %w", namespace, secretName, err) + } + if !exists { + return nil, fmt.Errorf("secret %s/%s does not exist", namespace, secretName) + } + + cert, key, err := getCertificateBlocks(secret, namespace, string(secretName)) + if err != nil { + return nil, err + } + + return &tls.CertAndStores{ + Certificate: tls.Certificate{ + CertFile: types.FileOrContent(cert), + KeyFile: types.FileOrContent(key), + }, + }, nil +} + +func (p *Provider) allowedNamespaces(gatewayNamespace string, routeNamespaces *gatev1.RouteNamespaces) ([]string, error) { + if routeNamespaces == nil || routeNamespaces.From == nil { + return []string{gatewayNamespace}, nil + } + + switch *routeNamespaces.From { + case gatev1.NamespacesFromAll: + return []string{metav1.NamespaceAll}, nil + + case gatev1.NamespacesFromSame: + return []string{gatewayNamespace}, nil + + case gatev1.NamespacesFromSelector: + selector, err := metav1.LabelSelectorAsSelector(routeNamespaces.Selector) + if err != nil { + return nil, fmt.Errorf("malformed selector: %w", err) + } + + return p.client.ListNamespaces(selector) + } + + return nil, fmt.Errorf("unsupported RouteSelectType: %q", *routeNamespaces.From) +} + func supportedRouteKinds(protocol gatev1.ProtocolType, experimentalChannel bool) ([]gatev1.RouteGroupKind, []metav1.Condition) { group := gatev1.Group(gatev1.GroupName) @@ -856,30 +925,6 @@ func allowedRouteKinds(gateway *gatev1.Gateway, listener gatev1.Listener, suppor return routeKinds, conditions } -func allowedNamespaces(client Client, gatewayNamespace string, routeNamespaces *gatev1.RouteNamespaces) ([]string, error) { - if routeNamespaces == nil || routeNamespaces.From == nil { - return []string{gatewayNamespace}, nil - } - - switch *routeNamespaces.From { - case gatev1.NamespacesFromAll: - return []string{metav1.NamespaceAll}, nil - - case gatev1.NamespacesFromSame: - return []string{gatewayNamespace}, nil - - case gatev1.NamespacesFromSelector: - selector, err := metav1.LabelSelectorAsSelector(routeNamespaces.Selector) - if err != nil { - return nil, fmt.Errorf("malformed selector: %w", err) - } - - return client.ListNamespaces(selector) - } - - return nil, fmt.Errorf("unsupported RouteSelectType: %q", *routeNamespaces.From) -} - func findMatchingHostnames(listenerHostname *gatev1.Hostname, routeHostnames []gatev1.Hostname) ([]gatev1.Hostname, bool) { if listenerHostname == nil { return routeHostnames, true @@ -971,7 +1016,7 @@ func matchListener(listener gatewayListener, routeNamespace string, parentRef ga return true } -func makeRouterKey(rule, name string) string { +func makeRouterName(rule, name string) string { h := sha256.New() // As explained in https://pkg.go.dev/hash#Hash, @@ -981,36 +1026,6 @@ func makeRouterKey(rule, name string) string { return fmt.Sprintf("%s-%.10x", name, h.Sum(nil)) } -func makeID(namespace, name string) string { - if namespace == "" { - return name - } - - return namespace + "-" + name -} - -func getTLS(client Client, secretName gatev1.ObjectName, namespace string) (*tls.CertAndStores, error) { - secret, exists, err := client.GetSecret(namespace, string(secretName)) - if err != nil { - return nil, fmt.Errorf("failed to fetch secret %s/%s: %w", namespace, secretName, err) - } - if !exists { - return nil, fmt.Errorf("secret %s/%s does not exist", namespace, secretName) - } - - cert, key, err := getCertificateBlocks(secret, namespace, string(secretName)) - if err != nil { - return nil, err - } - - return &tls.CertAndStores{ - Certificate: tls.Certificate{ - CertFile: types.FileOrContent(cert), - KeyFile: types.FileOrContent(key), - }, - }, nil -} - func getTLSConfig(tlsConfigs map[string]*tls.CertAndStores) []*tls.CertAndStores { var secretNames []string for secretName := range tlsConfigs { @@ -1114,25 +1129,6 @@ func makeListenerKey(l gatev1.Listener) string { return fmt.Sprintf("%s|%s|%d", l.Protocol, hostname, l.Port) } -func isReferenceGranted(client Client, fromGroup, fromKind, fromNamespace, toGroup, toKind, toName, toNamespace string) error { - if toNamespace == fromNamespace { - return nil - } - - refGrants, err := client.ListReferenceGrants(toNamespace) - if err != nil { - return fmt.Errorf("listing ReferenceGrant: %w", err) - } - - refGrants = filterReferenceGrantsFrom(refGrants, fromGroup, fromKind, fromNamespace) - refGrants = filterReferenceGrantsTo(refGrants, toGroup, toKind, toName) - if len(refGrants) == 0 { - return errors.New("missing ReferenceGrant") - } - - return nil -} - func filterReferenceGrantsFrom(referenceGrants []*gatev1beta1.ReferenceGrant, group, kind, namespace string) []*gatev1beta1.ReferenceGrant { var matchingReferenceGrants []*gatev1beta1.ReferenceGrant for _, referenceGrant := range referenceGrants { diff --git a/pkg/provider/kubernetes/gateway/kubernetes_test.go b/pkg/provider/kubernetes/gateway/kubernetes_test.go index 94bb5fe6b..b404931d8 100644 --- a/pkg/provider/kubernetes/gateway/kubernetes_test.go +++ b/pkg/provider/kubernetes/gateway/kubernetes_test.go @@ -3,6 +3,7 @@ package gateway import ( "context" "errors" + "net/http" "os" "path/filepath" "testing" @@ -198,17 +199,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27": { + "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr", - Rule: "Host(`foo.com`) && (Path(`/bar`))", - Priority: 99997, + Service: "default-http-app-1-my-gateway-web-0-wrr", + Rule: "Host(`foo.com`) && Path(`/bar`)", + Priority: 100008, RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr": { + "default-http-app-1-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -567,17 +568,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27": { + "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr", - Rule: "Host(`foo.com`) && (Path(`/bar`))", - Priority: 99997, + Service: "default-http-app-1-my-gateway-web-0-wrr", + Rule: "Host(`foo.com`) && Path(`/bar`)", + Priority: 100008, RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr": { + "default-http-app-1-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -628,11 +629,11 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27": { + "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, Service: "api@internal", - Rule: "Host(`foo.com`) && (Path(`/bar`))", - Priority: 99997, + Rule: "Host(`foo.com`) && Path(`/bar`)", + Priority: 100008, RuleSyntax: "v3", }, }, @@ -662,18 +663,18 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-websecure-af4b9876d1fe36359e27": { + "default-http-app-1-my-gateway-websecure-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"websecure"}, - Service: "default-http-app-1-my-gateway-websecure-af4b9876d1fe36359e27-wrr", - Rule: "Host(`foo.com`) && (Path(`/bar`))", - Priority: 99997, + Service: "default-http-app-1-my-gateway-websecure-0-wrr", + Rule: "Host(`foo.com`) && Path(`/bar`)", + Priority: 100008, RuleSyntax: "v3", TLS: &dynamic.RouterTLSConfig{}, }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-websecure-af4b9876d1fe36359e27-wrr": { + "default-http-app-1-my-gateway-websecure-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -733,17 +734,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-da59521d735cff97495a": { + "default-http-app-1-my-gateway-web-0-66e726cd8903b49727ae": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-da59521d735cff97495a-wrr", - Rule: "(Host(`foo.com`) || Host(`bar.com`))", - Priority: 7, + Service: "default-http-app-1-my-gateway-web-0-wrr", + Rule: "(Host(`foo.com`) || Host(`bar.com`)) && PathPrefix(`/`)", + Priority: 9, RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-da59521d735cff97495a-wrr": { + "default-http-app-1-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -794,17 +795,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-2550b6c946893e8b737a": { + "default-http-app-1-my-gateway-web-0-baa117c0219e3878749f": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-2550b6c946893e8b737a-wrr", - Rule: "(Host(`foo.com`) || HostRegexp(`^[a-z0-9-\\.]+\\.bar\\.com$`))", - Priority: 9, + Service: "default-http-app-1-my-gateway-web-0-wrr", + Rule: "(Host(`foo.com`) || HostRegexp(`^[a-z0-9-\\.]+\\.bar\\.com$`)) && PathPrefix(`/`)", + Priority: 11, RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-2550b6c946893e8b737a-wrr": { + "default-http-app-1-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -855,17 +856,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-0cd7265d0030f02bee3d": { + "default-http-app-1-my-gateway-web-0-45eba2eaf40ac792e036": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-0cd7265d0030f02bee3d-wrr", - Rule: "(Host(`foo.com`) || HostRegexp(`^[a-z0-9-\\.]+\\.foo\\.com$`))", - Priority: 9, + Service: "default-http-app-1-my-gateway-web-0-wrr", + Rule: "(Host(`foo.com`) || HostRegexp(`^[a-z0-9-\\.]+\\.foo\\.com$`)) && PathPrefix(`/`)", + Priority: 11, RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-0cd7265d0030f02bee3d-wrr": { + "default-http-app-1-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -916,24 +917,24 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27": { + "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Rule: "Host(`foo.com`) && (Path(`/bar`))", - Priority: 99997, + Rule: "Host(`foo.com`) && Path(`/bar`)", + Priority: 100009, RuleSyntax: "v3", - Service: "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr", + Service: "default-http-app-1-my-gateway-web-0-wrr", }, - "default-http-app-1-my-gateway-web-f37ede0f5aa6cc3e3a16": { + "default-http-app-1-my-gateway-web-1-d737b4933fa88e68ab8a": { EntryPoints: []string{"web"}, - Rule: "Host(`foo.com`) && (Path(`/bir`))", - Priority: 99997, + Rule: "Host(`foo.com`) && Path(`/bir`)", + Priority: 100008, RuleSyntax: "v3", - Service: "default-http-app-1-my-gateway-web-f37ede0f5aa6cc3e3a16-wrr", + Service: "default-http-app-1-my-gateway-web-1-wrr", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr": { + "default-http-app-1-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -943,7 +944,7 @@ func TestLoadHTTPRoutes(t *testing.T) { }, }, }, - "default-http-app-1-my-gateway-web-f37ede0f5aa6cc3e3a16-wrr": { + "default-http-app-1-my-gateway-web-1-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -1010,17 +1011,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27": { + "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Rule: "Host(`foo.com`) && (Path(`/bar`))", - Priority: 99997, + Rule: "Host(`foo.com`) && Path(`/bar`)", + Priority: 100008, RuleSyntax: "v3", - Service: "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr", + Service: "default-http-app-1-my-gateway-web-0-wrr", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr": { + "default-http-app-1-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -1096,25 +1097,25 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-http-web-af4b9876d1fe36359e27": { + "default-http-app-1-my-gateway-http-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-http-web-af4b9876d1fe36359e27-wrr", - Rule: "Host(`foo.com`) && (Path(`/bar`))", - Priority: 99997, + Service: "default-http-app-1-my-gateway-http-web-0-wrr", + Rule: "Host(`foo.com`) && Path(`/bar`)", + Priority: 100008, RuleSyntax: "v3", }, - "default-http-app-1-my-gateway-https-websecure-af4b9876d1fe36359e27": { + "default-http-app-1-my-gateway-https-websecure-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"websecure"}, - Service: "default-http-app-1-my-gateway-https-websecure-af4b9876d1fe36359e27-wrr", - Rule: "Host(`foo.com`) && (Path(`/bar`))", - Priority: 99997, + Service: "default-http-app-1-my-gateway-https-websecure-0-wrr", + Rule: "Host(`foo.com`) && Path(`/bar`)", + Priority: 100008, RuleSyntax: "v3", TLS: &dynamic.RouterTLSConfig{}, }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-http-web-af4b9876d1fe36359e27-wrr": { + "default-http-app-1-my-gateway-http-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -1124,7 +1125,7 @@ func TestLoadHTTPRoutes(t *testing.T) { }, }, }, - "default-http-app-1-my-gateway-https-websecure-af4b9876d1fe36359e27-wrr": { + "default-http-app-1-my-gateway-https-websecure-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -1189,25 +1190,25 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27": { + "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr", - Rule: "Host(`foo.com`) && (Path(`/bar`))", - Priority: 99997, + Service: "default-http-app-1-my-gateway-web-0-wrr", + Rule: "Host(`foo.com`) && Path(`/bar`)", + Priority: 100008, RuleSyntax: "v3", }, - "default-http-app-1-my-gateway-websecure-af4b9876d1fe36359e27": { + "default-http-app-1-my-gateway-websecure-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"websecure"}, - Service: "default-http-app-1-my-gateway-websecure-af4b9876d1fe36359e27-wrr", - Rule: "Host(`foo.com`) && (Path(`/bar`))", - Priority: 99997, + Service: "default-http-app-1-my-gateway-websecure-0-wrr", + Rule: "Host(`foo.com`) && Path(`/bar`)", + Priority: 100008, RuleSyntax: "v3", TLS: &dynamic.RouterTLSConfig{}, }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr": { + "default-http-app-1-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -1217,7 +1218,7 @@ func TestLoadHTTPRoutes(t *testing.T) { }, }, }, - "default-http-app-1-my-gateway-websecure-af4b9876d1fe36359e27-wrr": { + "default-http-app-1-my-gateway-websecure-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -1277,31 +1278,31 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-1f099b05db72cebb53a5": { + "default-http-app-1-my-gateway-web-0-6cf37fa71907768d925c": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-1f099b05db72cebb53a5-wrr", - Rule: "Host(`foo.com`) && (Path(`/bar`) && Header(`my-header`,`bar`))", - Priority: 100097, + Rule: "Host(`foo.com`) && (Path(`/bar`) || PathPrefix(`/bar/`)) && Header(`my-header`,`foo`) && Header(`my-header2`,`bar`)", + Priority: 10610, RuleSyntax: "v3", + Service: "default-http-app-1-my-gateway-web-0-wrr", }, - "default-http-app-1-my-gateway-web-4863cbd61ecd5b4b0739": { + "default-http-app-1-my-gateway-web-2-d23f7039bc8036fb918c": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-4863cbd61ecd5b4b0739-wrr", - Rule: "Host(`foo.com`) && (PathRegexp(`^/buzz/[0-9]+$`))", - Priority: 2397, + Rule: "Host(`foo.com`) && PathRegexp(`^/buzz/[0-9]+$`)", + Priority: 2408, RuleSyntax: "v3", + Service: "default-http-app-1-my-gateway-web-2-wrr", }, - "default-http-app-1-my-gateway-web-374af7817bd7c32eba26": { + "default-http-app-1-my-gateway-web-1-aaba0f24fd26e1ca2276": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-374af7817bd7c32eba26-wrr", - Rule: "Host(`foo.com`) && ((Path(`/bar`) || PathPrefix(`/bar/`)) && Header(`my-header`,`foo`) && Header(`my-header2`,`bar`))", - Priority: 10597, + Rule: "Host(`foo.com`) && Path(`/bar`) && Header(`my-header`,`bar`)", + Priority: 100109, RuleSyntax: "v3", + Service: "default-http-app-1-my-gateway-web-1-wrr", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-1f099b05db72cebb53a5-wrr": { + "default-http-app-1-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -1311,7 +1312,7 @@ func TestLoadHTTPRoutes(t *testing.T) { }, }, }, - "default-http-app-1-my-gateway-web-4863cbd61ecd5b4b0739-wrr": { + "default-http-app-1-my-gateway-web-2-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -1321,7 +1322,7 @@ func TestLoadHTTPRoutes(t *testing.T) { }, }, }, - "default-http-app-1-my-gateway-web-374af7817bd7c32eba26-wrr": { + "default-http-app-1-my-gateway-web-1-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -1372,17 +1373,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-default-my-gateway-web-a0df3dbe37431caa4485": { + "default-http-app-default-my-gateway-web-0-efde1997778109a1f6eb": { EntryPoints: []string{"web"}, - Service: "default-http-app-default-my-gateway-web-a0df3dbe37431caa4485-wrr", - Rule: "Host(`foo.com`) && (Path(`/foo`))", - Priority: 99997, + Service: "default-http-app-default-my-gateway-web-0-wrr", + Rule: "Host(`foo.com`) && Path(`/foo`)", + Priority: 100008, RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-default-my-gateway-web-a0df3dbe37431caa4485-wrr": { + "default-http-app-default-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -1433,24 +1434,24 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-default-my-gateway-web-a0df3dbe37431caa4485": { + "default-http-app-default-my-gateway-web-0-efde1997778109a1f6eb": { EntryPoints: []string{"web"}, - Service: "default-http-app-default-my-gateway-web-a0df3dbe37431caa4485-wrr", - Rule: "Host(`foo.com`) && (Path(`/foo`))", - Priority: 99997, + Service: "default-http-app-default-my-gateway-web-0-wrr", + Rule: "Host(`foo.com`) && Path(`/foo`)", + Priority: 100008, RuleSyntax: "v3", }, - "bar-http-app-bar-my-gateway-web-c7f946bee1e5b1751d6a": { + "bar-http-app-bar-my-gateway-web-0-66f5c78d03d948e36597": { EntryPoints: []string{"web"}, - Service: "bar-http-app-bar-my-gateway-web-c7f946bee1e5b1751d6a-wrr", - Rule: "Host(`bar.com`) && (Path(`/bar`))", - Priority: 99997, + Service: "bar-http-app-bar-my-gateway-web-0-wrr", + Rule: "Host(`bar.com`) && Path(`/bar`)", + Priority: 100008, RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-default-my-gateway-web-a0df3dbe37431caa4485-wrr": { + "default-http-app-default-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -1460,7 +1461,7 @@ func TestLoadHTTPRoutes(t *testing.T) { }, }, }, - "bar-http-app-bar-my-gateway-web-c7f946bee1e5b1751d6a-wrr": { + "bar-http-app-bar-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -1527,17 +1528,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "bar-http-app-bar-my-gateway-web-c7f946bee1e5b1751d6a": { + "bar-http-app-bar-my-gateway-web-0-66f5c78d03d948e36597": { EntryPoints: []string{"web"}, - Service: "bar-http-app-bar-my-gateway-web-c7f946bee1e5b1751d6a-wrr", - Rule: "Host(`bar.com`) && (Path(`/bar`))", - Priority: 99997, + Service: "bar-http-app-bar-my-gateway-web-0-wrr", + Rule: "Host(`bar.com`) && Path(`/bar`)", + Priority: 100008, RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "bar-http-app-bar-my-gateway-web-c7f946bee1e5b1751d6a-wrr": { + "bar-http-app-bar-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -1588,17 +1589,17 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-fa136e10345bd0e7248d": { + "default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-fa136e10345bd0e7248d-wrr", - Rule: "Host(`example.org`)", - Priority: 11, + Service: "default-http-app-1-my-gateway-web-0-wrr", + Rule: "Host(`example.org`) && PathPrefix(`/`)", + Priority: 13, RuleSyntax: "v3", - Middlewares: []string{"default-http-app-1-my-gateway-web-fa136e10345bd0e7248d-requestheadermodifier-0"}, + Middlewares: []string{"default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4-requestheadermodifier-0"}, }, }, Middlewares: map[string]*dynamic.Middleware{ - "default-http-app-1-my-gateway-web-fa136e10345bd0e7248d-requestheadermodifier-0": { + "default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4-requestheadermodifier-0": { RequestHeaderModifier: &dynamic.RequestHeaderModifier{ Set: map[string]string{"X-Foo": "Bar"}, Add: map[string]string{"X-Bar": "Foo"}, @@ -1607,7 +1608,7 @@ func TestLoadHTTPRoutes(t *testing.T) { }, }, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-fa136e10345bd0e7248d-wrr": { + "default-http-app-1-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -1658,26 +1659,26 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-fa136e10345bd0e7248d": { + "default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-fa136e10345bd0e7248d-wrr", - Rule: "Host(`example.org`)", - Priority: 11, + Service: "default-http-app-1-my-gateway-web-0-wrr", + Rule: "Host(`example.org`) && PathPrefix(`/`)", + Priority: 13, RuleSyntax: "v3", - Middlewares: []string{"default-http-app-1-my-gateway-web-fa136e10345bd0e7248d-requestredirect-0"}, + Middlewares: []string{"default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4-requestredirect-0"}, }, }, Middlewares: map[string]*dynamic.Middleware{ - "default-http-app-1-my-gateway-web-fa136e10345bd0e7248d-requestredirect-0": { + "default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4-requestredirect-0": { RequestRedirect: &dynamic.RequestRedirect{ - Regex: "^(?P[a-z]+):\\/\\/(?P.+@)?(?P\\[[\\w:\\.]+\\]|[\\w\\._-]+)(?P:\\d+)?\\/(?P.*)", - Replacement: "https://${userinfo}${hostname}/${path}", - Permanent: true, + Scheme: ptr.To("https"), + Port: ptr.To(""), + StatusCode: http.StatusMovedPermanently, }, }, }, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-fa136e10345bd0e7248d-wrr": { + "default-http-app-1-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{}, }, }, @@ -1705,25 +1706,26 @@ func TestLoadHTTPRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-fa136e10345bd0e7248d": { + "default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-fa136e10345bd0e7248d-wrr", - Rule: "Host(`example.org`)", - Priority: 11, + Service: "default-http-app-1-my-gateway-web-0-wrr", + Rule: "Host(`example.org`) && PathPrefix(`/`)", + Priority: 13, RuleSyntax: "v3", - Middlewares: []string{"default-http-app-1-my-gateway-web-fa136e10345bd0e7248d-requestredirect-0"}, + Middlewares: []string{"default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4-requestredirect-0"}, }, }, Middlewares: map[string]*dynamic.Middleware{ - "default-http-app-1-my-gateway-web-fa136e10345bd0e7248d-requestredirect-0": { + "default-http-app-1-my-gateway-web-0-364ce6ec04c3d49b19c4-requestredirect-0": { RequestRedirect: &dynamic.RequestRedirect{ - Regex: "^(?P[a-z]+):\\/\\/(?P.+@)?(?P\\[[\\w:\\.]+\\]|[\\w\\._-]+)(?P:\\d+)?\\/(?P.*)", - Replacement: "${scheme}://${userinfo}example.com:443/${path}", + Hostname: ptr.To("example.com"), + Port: ptr.To("443"), + StatusCode: http.StatusFound, }, }, }, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-fa136e10345bd0e7248d-wrr": { + "default-http-app-1-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{}, }, }, @@ -1742,11 +1744,6 @@ func TestLoadHTTPRoutes(t *testing.T) { return } - p := Provider{ - EntryPoints: test.entryPoints, - ExperimentalChannel: test.experimentalChannel, - } - k8sObjects, gwObjects := readResources(t, test.paths) kubeClient := kubefake.NewSimpleClientset(k8sObjects...) @@ -1762,7 +1759,13 @@ func TestLoadHTTPRoutes(t *testing.T) { <-eventCh } - conf := p.loadConfigurationFromGateways(context.Background(), client) + p := Provider{ + EntryPoints: test.entryPoints, + ExperimentalChannel: test.experimentalChannel, + client: client, + } + + conf := p.loadConfigurationFromGateways(context.Background()) assert.Equal(t, test.expected, conf) }) } @@ -1800,17 +1803,17 @@ func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27": { + "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr", - Rule: "Host(`foo.com`) && (Path(`/bar`))", - Priority: 99997, + Service: "default-http-app-1-my-gateway-web-0-wrr", + Rule: "Host(`foo.com`) && Path(`/bar`)", + Priority: 100008, RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr": { + "default-http-app-1-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -1850,17 +1853,17 @@ func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27": { + "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr", - Rule: "Host(`foo.com`) && (Path(`/bar`))", - Priority: 99997, + Service: "default-http-app-1-my-gateway-web-0-wrr", + Rule: "Host(`foo.com`) && Path(`/bar`)", + Priority: 100008, RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr": { + "default-http-app-1-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -1902,17 +1905,17 @@ func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27": { + "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr", - Rule: "Host(`foo.com`) && (Path(`/bar`))", - Priority: 99997, + Service: "default-http-app-1-my-gateway-web-0-wrr", + Rule: "Host(`foo.com`) && Path(`/bar`)", + Priority: 100008, RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr": { + "default-http-app-1-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -1953,17 +1956,17 @@ func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27": { + "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr", - Rule: "Host(`foo.com`) && (Path(`/bar`))", - Priority: 99997, + Service: "default-http-app-1-my-gateway-web-0-wrr", + Rule: "Host(`foo.com`) && Path(`/bar`)", + Priority: 100008, RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr": { + "default-http-app-1-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -2005,17 +2008,17 @@ func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27": { + "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr", - Rule: "Host(`foo.com`) && (Path(`/bar`))", - Priority: 99997, + Service: "default-http-app-1-my-gateway-web-0-wrr", + Rule: "Host(`foo.com`) && Path(`/bar`)", + Priority: 100008, RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr": { + "default-http-app-1-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -2061,8 +2064,6 @@ func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) { return } - p := Provider{EntryPoints: test.entryPoints} - k8sObjects, gwObjects := readResources(t, test.paths) kubeClient := kubefake.NewSimpleClientset(k8sObjects...) @@ -2078,12 +2079,17 @@ func TestLoadHTTPRoutes_backendExtensionRef(t *testing.T) { <-eventCh } + p := Provider{ + EntryPoints: test.entryPoints, + client: client, + } + for group, kindFuncs := range test.groupKindBackendFuncs { for kind, backendFunc := range kindFuncs { p.RegisterBackendFuncs(group, kind, backendFunc) } } - conf := p.loadConfigurationFromGateways(context.Background(), client) + conf := p.loadConfigurationFromGateways(context.Background()) assert.Equal(t, test.expected, conf) }) } @@ -2119,18 +2125,18 @@ func TestLoadHTTPRoutes_filterExtensionRef(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27": { + "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr", - Rule: "Host(`foo.com`) && (Path(`/bar`))", - Priority: 99997, + Service: "default-http-app-1-my-gateway-web-0-wrr", + Rule: "Host(`foo.com`) && Path(`/bar`)", + Priority: 100008, RuleSyntax: "v3", Middlewares: []string{"default-my-middleware"}, }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr": { + "default-http-app-1-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -2185,11 +2191,11 @@ func TestLoadHTTPRoutes_filterExtensionRef(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27": { + "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr", - Rule: "Host(`foo.com`) && (Path(`/bar`))", - Priority: 99997, + Service: "default-http-app-1-my-gateway-web-0-wrr", + Rule: "Host(`foo.com`) && Path(`/bar`)", + Priority: 100008, RuleSyntax: "v3", Middlewares: []string{"default-my-middleware"}, }, @@ -2198,7 +2204,7 @@ func TestLoadHTTPRoutes_filterExtensionRef(t *testing.T) { "default-my-middleware": {Headers: &dynamic.Headers{CustomRequestHeaders: map[string]string{"Test-Header": "Test"}}}, }, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr": { + "default-http-app-1-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -2248,17 +2254,17 @@ func TestLoadHTTPRoutes_filterExtensionRef(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27": { + "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr", - Rule: "Host(`foo.com`) && (Path(`/bar`))", - Priority: 99997, + Service: "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-err-wrr", + Rule: "Host(`foo.com`) && Path(`/bar`)", + Priority: 100008, RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr": { + "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-err-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -2298,17 +2304,17 @@ func TestLoadHTTPRoutes_filterExtensionRef(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27": { + "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr", - Rule: "Host(`foo.com`) && (Path(`/bar`))", - Priority: 99997, + Service: "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-err-wrr", + Rule: "Host(`foo.com`) && Path(`/bar`)", + Priority: 100008, RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-af4b9876d1fe36359e27-wrr": { + "default-http-app-1-my-gateway-web-0-1c0cf64bde37d9d0df06-err-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -2335,8 +2341,6 @@ func TestLoadHTTPRoutes_filterExtensionRef(t *testing.T) { return } - p := Provider{EntryPoints: test.entryPoints} - k8sObjects, gwObjects := readResources(t, []string{"services.yml", "httproute/filter_extension_ref.yml"}) kubeClient := kubefake.NewSimpleClientset(k8sObjects...) @@ -2352,12 +2356,17 @@ func TestLoadHTTPRoutes_filterExtensionRef(t *testing.T) { <-eventCh } + p := Provider{ + EntryPoints: test.entryPoints, + client: client, + } + for group, kindFuncs := range test.groupKindFilterFuncs { for kind, filterFunc := range kindFuncs { p.RegisterFilterFuncs(group, kind, filterFunc) } } - conf := p.loadConfigurationFromGateways(context.Background(), client) + conf := p.loadConfigurationFromGateways(context.Background()) assert.Equal(t, test.expected, conf) }) } @@ -2562,16 +2571,16 @@ func TestLoadTCPRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-1-my-tcp-gateway-tcp-e3b0c44298fc1c149afb": { + "default-tcp-app-1-my-tcp-gateway-tcp": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-1-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", + Service: "default-tcp-app-1-my-tcp-gateway-tcp-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { + "default-tcp-app-1-my-tcp-gateway-tcp-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -2620,22 +2629,22 @@ func TestLoadTCPRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-1-my-tcp-gateway-tcp-1-e3b0c44298fc1c149afb": { + "default-tcp-app-1-my-tcp-gateway-tcp-1": { EntryPoints: []string{"tcp-1"}, - Service: "default-tcp-app-1-my-tcp-gateway-tcp-1-e3b0c44298fc1c149afb-wrr-0", + Service: "default-tcp-app-1-my-tcp-gateway-tcp-1-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, - "default-tcp-app-2-my-tcp-gateway-tcp-2-e3b0c44298fc1c149afb": { + "default-tcp-app-2-my-tcp-gateway-tcp-2": { EntryPoints: []string{"tcp-2"}, - Service: "default-tcp-app-2-my-tcp-gateway-tcp-2-e3b0c44298fc1c149afb-wrr-0", + Service: "default-tcp-app-2-my-tcp-gateway-tcp-2-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-tcp-gateway-tcp-1-e3b0c44298fc1c149afb-wrr-0": { + "default-tcp-app-1-my-tcp-gateway-tcp-1-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -2645,7 +2654,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, - "default-tcp-app-2-my-tcp-gateway-tcp-2-e3b0c44298fc1c149afb-wrr-0": { + "default-tcp-app-2-my-tcp-gateway-tcp-2-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -2706,30 +2715,30 @@ func TestLoadTCPRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-my-tcp-gateway-tcp-1-e3b0c44298fc1c149afb": { + "default-tcp-app-my-tcp-gateway-tcp-1": { EntryPoints: []string{"tcp-1"}, - Service: "default-tcp-app-my-tcp-gateway-tcp-1-e3b0c44298fc1c149afb-wrr", + Service: "default-tcp-app-my-tcp-gateway-tcp-1-wrr", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-my-tcp-gateway-tcp-1-e3b0c44298fc1c149afb-wrr": { + "default-tcp-app-my-tcp-gateway-tcp-1-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { - Name: "default-tcp-app-my-tcp-gateway-tcp-1-e3b0c44298fc1c149afb-wrr-0", + Name: "default-tcp-app-my-tcp-gateway-tcp-1-wrr-0", Weight: ptr.To(1), }, { - Name: "default-tcp-app-my-tcp-gateway-tcp-1-e3b0c44298fc1c149afb-wrr-1", + Name: "default-tcp-app-my-tcp-gateway-tcp-1-wrr-1", Weight: ptr.To(1), }, }, }, }, - "default-tcp-app-my-tcp-gateway-tcp-1-e3b0c44298fc1c149afb-wrr-0": { + "default-tcp-app-my-tcp-gateway-tcp-1-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -2739,7 +2748,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, - "default-tcp-app-my-tcp-gateway-tcp-1-e3b0c44298fc1c149afb-wrr-1": { + "default-tcp-app-my-tcp-gateway-tcp-1-wrr-1": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -2798,16 +2807,16 @@ func TestLoadTCPRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-1-my-gateway-tcp-e3b0c44298fc1c149afb": { + "default-tcp-app-1-my-gateway-tcp": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-1-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", + Service: "default-tcp-app-1-my-gateway-tcp-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { + "default-tcp-app-1-my-gateway-tcp-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -2858,9 +2867,9 @@ func TestLoadTCPRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-1-my-gateway-tls-e3b0c44298fc1c149afb": { + "default-tcp-app-1-my-gateway-tls": { EntryPoints: []string{"tls"}, - Service: "default-tcp-app-1-my-gateway-tls-e3b0c44298fc1c149afb-wrr-0", + Service: "default-tcp-app-1-my-gateway-tls-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{}, @@ -2868,7 +2877,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-gateway-tls-e3b0c44298fc1c149afb-wrr-0": { + "default-tcp-app-1-my-gateway-tls-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{{ Name: "default-whoamitcp-9000", @@ -2922,16 +2931,16 @@ func TestLoadTCPRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-default-my-tcp-gateway-tcp-e3b0c44298fc1c149afb": { + "default-tcp-app-default-my-tcp-gateway-tcp": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-default-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", + Service: "default-tcp-app-default-my-tcp-gateway-tcp-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-default-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { + "default-tcp-app-default-my-tcp-gateway-tcp-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -2978,22 +2987,22 @@ func TestLoadTCPRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-default-my-tcp-gateway-tcp-e3b0c44298fc1c149afb": { + "default-tcp-app-default-my-tcp-gateway-tcp": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-default-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", + Service: "default-tcp-app-default-my-tcp-gateway-tcp-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, - "bar-tcp-app-bar-my-tcp-gateway-tcp-e3b0c44298fc1c149afb": { + "bar-tcp-app-bar-my-tcp-gateway-tcp": { EntryPoints: []string{"tcp"}, - Service: "bar-tcp-app-bar-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", + Service: "bar-tcp-app-bar-my-tcp-gateway-tcp-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-default-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { + "default-tcp-app-default-my-tcp-gateway-tcp-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3003,7 +3012,7 @@ func TestLoadTCPRoutes(t *testing.T) { }, }, }, - "bar-tcp-app-bar-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { + "bar-tcp-app-bar-my-tcp-gateway-tcp-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3062,16 +3071,16 @@ func TestLoadTCPRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "bar-tcp-app-bar-my-tcp-gateway-tcp-e3b0c44298fc1c149afb": { + "bar-tcp-app-bar-my-tcp-gateway-tcp": { EntryPoints: []string{"tcp"}, - Service: "bar-tcp-app-bar-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", + Service: "bar-tcp-app-bar-my-tcp-gateway-tcp-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "bar-tcp-app-bar-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { + "bar-tcp-app-bar-my-tcp-gateway-tcp-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3115,11 +3124,6 @@ func TestLoadTCPRoutes(t *testing.T) { return } - p := Provider{ - EntryPoints: test.entryPoints, - ExperimentalChannel: true, - } - k8sObjects, gwObjects := readResources(t, test.paths) kubeClient := kubefake.NewSimpleClientset(k8sObjects...) @@ -3136,7 +3140,13 @@ func TestLoadTCPRoutes(t *testing.T) { <-eventCh } - conf := p.loadConfigurationFromGateways(context.Background(), client) + p := Provider{ + EntryPoints: test.entryPoints, + ExperimentalChannel: true, + client: client, + } + + conf := p.loadConfigurationFromGateways(context.Background()) assert.Equal(t, test.expected, conf) }) } @@ -3358,9 +3368,9 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-1-my-tls-gateway-tcp-e3b0c44298fc1c149afb": { + "default-tcp-app-1-my-tls-gateway-tcp": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-1-my-tls-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", + Service: "default-tcp-app-1-my-tls-gateway-tcp-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{}, @@ -3368,7 +3378,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-tls-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { + "default-tcp-app-1-my-tls-gateway-tcp-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3424,9 +3434,9 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-1-my-tls-gateway-tcp-e3b0c44298fc1c149afb": { + "default-tcp-app-1-my-tls-gateway-tcp": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-1-my-tls-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", + Service: "default-tcp-app-1-my-tls-gateway-tcp-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{ @@ -3436,7 +3446,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-tls-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { + "default-tcp-app-1-my-tls-gateway-tcp-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3543,9 +3553,9 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-1-my-tls-gateway-tls-e3b0c44298fc1c149afb": { + "default-tcp-app-1-my-tls-gateway-tls": { EntryPoints: []string{"tls"}, - Service: "default-tcp-app-1-my-tls-gateway-tls-e3b0c44298fc1c149afb-wrr-0", + Service: "default-tcp-app-1-my-tls-gateway-tls-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{}, @@ -3562,7 +3572,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-tls-gateway-tls-e3b0c44298fc1c149afb-wrr-0": { + "default-tcp-app-1-my-tls-gateway-tls-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -3640,9 +3650,9 @@ func TestLoadTLSRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-1-my-gateway-tls-e3b0c44298fc1c149afb": { + "default-tcp-app-1-my-gateway-tls": { EntryPoints: []string{"tls"}, - Service: "default-tcp-app-1-my-gateway-tls-e3b0c44298fc1c149afb-wrr-0", + Service: "default-tcp-app-1-my-gateway-tls-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{}, @@ -3650,7 +3660,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-gateway-tls-e3b0c44298fc1c149afb-wrr-0": { + "default-tcp-app-1-my-gateway-tls-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -4246,11 +4256,6 @@ func TestLoadTLSRoutes(t *testing.T) { return } - p := Provider{ - EntryPoints: test.entryPoints, - ExperimentalChannel: true, - } - k8sObjects, gwObjects := readResources(t, test.paths) kubeClient := kubefake.NewSimpleClientset(k8sObjects...) @@ -4267,7 +4272,13 @@ func TestLoadTLSRoutes(t *testing.T) { <-eventCh } - conf := p.loadConfigurationFromGateways(context.Background(), client) + p := Provider{ + EntryPoints: test.entryPoints, + ExperimentalChannel: true, + client: client, + } + + conf := p.loadConfigurationFromGateways(context.Background()) assert.Equal(t, test.expected, conf) }) } @@ -4400,15 +4411,15 @@ func TestLoadMixedRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-1-my-gateway-tcp-e3b0c44298fc1c149afb": { + "default-tcp-app-1-my-gateway-tcp": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-1-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", + Service: "default-tcp-app-1-my-gateway-tcp-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, - "default-tcp-app-1-my-gateway-tls-1-e3b0c44298fc1c149afb": { + "default-tcp-app-1-my-gateway-tls-1": { EntryPoints: []string{"tls-1"}, - Service: "default-tcp-app-1-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr-0", + Service: "default-tcp-app-1-my-gateway-tls-1-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{}, @@ -4425,7 +4436,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { + "default-tcp-app-1-my-gateway-tcp-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -4435,7 +4446,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "default-tcp-app-1-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr-0": { + "default-tcp-app-1-my-gateway-tls-1-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -4472,25 +4483,25 @@ func TestLoadMixedRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-web-a431b128267aabc954fd": { + "default-http-app-1-my-gateway-web-0-a431b128267aabc954fd": { EntryPoints: []string{"web"}, - Service: "default-http-app-1-my-gateway-web-a431b128267aabc954fd-wrr", + Service: "default-http-app-1-my-gateway-web-0-wrr", Rule: "PathPrefix(`/`)", - Priority: 1, + Priority: 2, RuleSyntax: "v3", }, - "default-http-app-1-my-gateway-websecure-a431b128267aabc954fd": { + "default-http-app-1-my-gateway-websecure-0-a431b128267aabc954fd": { EntryPoints: []string{"websecure"}, - Service: "default-http-app-1-my-gateway-websecure-a431b128267aabc954fd-wrr", + Service: "default-http-app-1-my-gateway-websecure-0-wrr", Rule: "PathPrefix(`/`)", - Priority: 1, + Priority: 2, RuleSyntax: "v3", TLS: &dynamic.RouterTLSConfig{}, }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-web-a431b128267aabc954fd-wrr": { + "default-http-app-1-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -4500,7 +4511,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "default-http-app-1-my-gateway-websecure-a431b128267aabc954fd-wrr": { + "default-http-app-1-my-gateway-websecure-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -4587,15 +4598,15 @@ func TestLoadMixedRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-default-my-gateway-tcp-e3b0c44298fc1c149afb": { + "default-tcp-app-default-my-gateway-tcp": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-default-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", + Service: "default-tcp-app-default-my-gateway-tcp-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, - "default-tcp-app-default-my-gateway-tls-1-e3b0c44298fc1c149afb": { + "default-tcp-app-default-my-gateway-tls-1": { EntryPoints: []string{"tls-1"}, - Service: "default-tcp-app-default-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr-0", + Service: "default-tcp-app-default-my-gateway-tls-1-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{}, @@ -4612,7 +4623,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-default-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { + "default-tcp-app-default-my-gateway-tcp-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -4622,7 +4633,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "default-tcp-app-default-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr-0": { + "default-tcp-app-default-my-gateway-tls-1-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -4659,25 +4670,25 @@ func TestLoadMixedRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-default-my-gateway-web-a431b128267aabc954fd": { + "default-http-app-default-my-gateway-web-0-a431b128267aabc954fd": { EntryPoints: []string{"web"}, - Service: "default-http-app-default-my-gateway-web-a431b128267aabc954fd-wrr", + Service: "default-http-app-default-my-gateway-web-0-wrr", Rule: "PathPrefix(`/`)", - Priority: 1, + Priority: 2, RuleSyntax: "v3", }, - "default-http-app-default-my-gateway-websecure-a431b128267aabc954fd": { + "default-http-app-default-my-gateway-websecure-0-a431b128267aabc954fd": { EntryPoints: []string{"websecure"}, - Service: "default-http-app-default-my-gateway-websecure-a431b128267aabc954fd-wrr", + Service: "default-http-app-default-my-gateway-websecure-0-wrr", Rule: "PathPrefix(`/`)", - Priority: 1, + Priority: 2, RuleSyntax: "v3", TLS: &dynamic.RouterTLSConfig{}, }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-default-my-gateway-web-a431b128267aabc954fd-wrr": { + "default-http-app-default-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -4687,7 +4698,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "default-http-app-default-my-gateway-websecure-a431b128267aabc954fd-wrr": { + "default-http-app-default-my-gateway-websecure-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -4746,15 +4757,15 @@ func TestLoadMixedRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-default-my-gateway-tcp-e3b0c44298fc1c149afb": { + "default-tcp-app-default-my-gateway-tcp": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-default-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", + Service: "default-tcp-app-default-my-gateway-tcp-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, - "default-tcp-app-default-my-gateway-tls-1-e3b0c44298fc1c149afb": { + "default-tcp-app-default-my-gateway-tls-1": { EntryPoints: []string{"tls-1"}, - Service: "default-tcp-app-default-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr-0", + Service: "default-tcp-app-default-my-gateway-tls-1-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{}, @@ -4768,15 +4779,15 @@ func TestLoadMixedRoutes(t *testing.T) { Passthrough: true, }, }, - "bar-tcp-app-bar-my-gateway-tcp-e3b0c44298fc1c149afb": { + "bar-tcp-app-bar-my-gateway-tcp": { EntryPoints: []string{"tcp"}, - Service: "bar-tcp-app-bar-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", + Service: "bar-tcp-app-bar-my-gateway-tcp-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, - "bar-tcp-app-bar-my-gateway-tls-1-e3b0c44298fc1c149afb": { + "bar-tcp-app-bar-my-gateway-tls-1": { EntryPoints: []string{"tls-1"}, - Service: "bar-tcp-app-bar-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr-0", + Service: "bar-tcp-app-bar-my-gateway-tls-1-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{}, @@ -4784,7 +4795,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-default-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { + "default-tcp-app-default-my-gateway-tcp-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -4794,7 +4805,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "default-tcp-app-default-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr-0": { + "default-tcp-app-default-my-gateway-tls-1-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -4838,7 +4849,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "bar-tcp-app-bar-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { + "bar-tcp-app-bar-my-gateway-tcp-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -4848,7 +4859,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "bar-tcp-app-bar-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr-0": { + "bar-tcp-app-bar-my-gateway-tls-1-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -4863,40 +4874,40 @@ func TestLoadMixedRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-default-my-gateway-web-a431b128267aabc954fd": { + "default-http-app-default-my-gateway-web-0-a431b128267aabc954fd": { EntryPoints: []string{"web"}, - Service: "default-http-app-default-my-gateway-web-a431b128267aabc954fd-wrr", + Service: "default-http-app-default-my-gateway-web-0-wrr", Rule: "PathPrefix(`/`)", - Priority: 1, + Priority: 2, RuleSyntax: "v3", }, - "default-http-app-default-my-gateway-websecure-a431b128267aabc954fd": { + "default-http-app-default-my-gateway-websecure-0-a431b128267aabc954fd": { EntryPoints: []string{"websecure"}, - Service: "default-http-app-default-my-gateway-websecure-a431b128267aabc954fd-wrr", + Service: "default-http-app-default-my-gateway-websecure-0-wrr", Rule: "PathPrefix(`/`)", - Priority: 1, + Priority: 2, RuleSyntax: "v3", TLS: &dynamic.RouterTLSConfig{}, }, - "bar-http-app-bar-my-gateway-web-a431b128267aabc954fd": { + "bar-http-app-bar-my-gateway-web-0-a431b128267aabc954fd": { EntryPoints: []string{"web"}, - Service: "bar-http-app-bar-my-gateway-web-a431b128267aabc954fd-wrr", + Service: "bar-http-app-bar-my-gateway-web-0-wrr", Rule: "PathPrefix(`/`)", - Priority: 1, + Priority: 2, RuleSyntax: "v3", }, - "bar-http-app-bar-my-gateway-websecure-a431b128267aabc954fd": { + "bar-http-app-bar-my-gateway-websecure-0-a431b128267aabc954fd": { EntryPoints: []string{"websecure"}, - Service: "bar-http-app-bar-my-gateway-websecure-a431b128267aabc954fd-wrr", + Service: "bar-http-app-bar-my-gateway-websecure-0-wrr", Rule: "PathPrefix(`/`)", - Priority: 1, + Priority: 2, RuleSyntax: "v3", TLS: &dynamic.RouterTLSConfig{}, }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-default-my-gateway-web-a431b128267aabc954fd-wrr": { + "default-http-app-default-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -4906,7 +4917,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "default-http-app-default-my-gateway-websecure-a431b128267aabc954fd-wrr": { + "default-http-app-default-my-gateway-websecure-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -4948,7 +4959,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "bar-http-app-bar-my-gateway-web-a431b128267aabc954fd-wrr": { + "bar-http-app-bar-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -4958,7 +4969,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "bar-http-app-bar-my-gateway-websecure-a431b128267aabc954fd-wrr": { + "bar-http-app-bar-my-gateway-websecure-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -5001,15 +5012,15 @@ func TestLoadMixedRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "bar-tcp-app-bar-my-gateway-tcp-e3b0c44298fc1c149afb": { + "bar-tcp-app-bar-my-gateway-tcp": { EntryPoints: []string{"tcp"}, - Service: "bar-tcp-app-bar-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", + Service: "bar-tcp-app-bar-my-gateway-tcp-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, - "bar-tcp-app-bar-my-gateway-tls-1-e3b0c44298fc1c149afb": { + "bar-tcp-app-bar-my-gateway-tls-1": { EntryPoints: []string{"tls-1"}, - Service: "bar-tcp-app-bar-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr-0", + Service: "bar-tcp-app-bar-my-gateway-tls-1-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{}, @@ -5038,7 +5049,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "bar-tcp-app-bar-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { + "bar-tcp-app-bar-my-gateway-tcp-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -5048,7 +5059,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "bar-tcp-app-bar-my-gateway-tls-1-e3b0c44298fc1c149afb-wrr-0": { + "bar-tcp-app-bar-my-gateway-tls-1-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -5073,18 +5084,18 @@ func TestLoadMixedRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "bar-http-app-bar-my-gateway-web-a431b128267aabc954fd": { + "bar-http-app-bar-my-gateway-web-0-a431b128267aabc954fd": { EntryPoints: []string{"web"}, - Service: "bar-http-app-bar-my-gateway-web-a431b128267aabc954fd-wrr", + Service: "bar-http-app-bar-my-gateway-web-0-wrr", Rule: "PathPrefix(`/`)", - Priority: 1, + Priority: 2, RuleSyntax: "v3", }, - "bar-http-app-bar-my-gateway-websecure-a431b128267aabc954fd": { + "bar-http-app-bar-my-gateway-websecure-0-a431b128267aabc954fd": { EntryPoints: []string{"websecure"}, - Service: "bar-http-app-bar-my-gateway-websecure-a431b128267aabc954fd-wrr", + Service: "bar-http-app-bar-my-gateway-websecure-0-wrr", Rule: "PathPrefix(`/`)", - Priority: 1, + Priority: 2, RuleSyntax: "v3", TLS: &dynamic.RouterTLSConfig{}, }, @@ -5107,7 +5118,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "bar-http-app-bar-my-gateway-web-a431b128267aabc954fd-wrr": { + "bar-http-app-bar-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -5117,7 +5128,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "bar-http-app-bar-my-gateway-websecure-a431b128267aabc954fd-wrr": { + "bar-http-app-bar-my-gateway-websecure-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -5159,15 +5170,15 @@ func TestLoadMixedRoutes(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-default-my-gateway-tcp-e3b0c44298fc1c149afb": { + "default-tcp-app-default-my-gateway-tcp": { EntryPoints: []string{"tcp"}, - Service: "default-tcp-app-default-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0", + Service: "default-tcp-app-default-my-gateway-tcp-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", }, - "default-tcp-app-default-my-gateway-tls-e3b0c44298fc1c149afb": { + "default-tcp-app-default-my-gateway-tls": { EntryPoints: []string{"tls"}, - Service: "default-tcp-app-default-my-gateway-tls-e3b0c44298fc1c149afb-wrr-0", + Service: "default-tcp-app-default-my-gateway-tls-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{}, @@ -5175,7 +5186,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-default-my-gateway-tcp-e3b0c44298fc1c149afb-wrr-0": { + "default-tcp-app-default-my-gateway-tcp-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -5185,7 +5196,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "default-tcp-app-default-my-gateway-tls-e3b0c44298fc1c149afb-wrr-0": { + "default-tcp-app-default-my-gateway-tls-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{ { @@ -5212,25 +5223,25 @@ func TestLoadMixedRoutes(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-default-my-gateway-web-a431b128267aabc954fd": { + "default-http-app-default-my-gateway-web-0-a431b128267aabc954fd": { EntryPoints: []string{"web"}, - Service: "default-http-app-default-my-gateway-web-a431b128267aabc954fd-wrr", + Service: "default-http-app-default-my-gateway-web-0-wrr", Rule: "PathPrefix(`/`)", - Priority: 1, + Priority: 2, RuleSyntax: "v3", }, - "default-http-app-default-my-gateway-websecure-a431b128267aabc954fd": { + "default-http-app-default-my-gateway-websecure-0-a431b128267aabc954fd": { EntryPoints: []string{"websecure"}, - Service: "default-http-app-default-my-gateway-websecure-a431b128267aabc954fd-wrr", + Service: "default-http-app-default-my-gateway-websecure-0-wrr", Rule: "PathPrefix(`/`)", - Priority: 1, + Priority: 2, RuleSyntax: "v3", TLS: &dynamic.RouterTLSConfig{}, }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-default-my-gateway-web-a431b128267aabc954fd-wrr": { + "default-http-app-default-my-gateway-web-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -5240,7 +5251,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, - "default-http-app-default-my-gateway-websecure-a431b128267aabc954fd-wrr": { + "default-http-app-default-my-gateway-websecure-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -5291,11 +5302,6 @@ func TestLoadMixedRoutes(t *testing.T) { return } - p := Provider{ - EntryPoints: test.entryPoints, - ExperimentalChannel: test.experimentalChannel, - } - k8sObjects, gwObjects := readResources(t, test.paths) kubeClient := kubefake.NewSimpleClientset(k8sObjects...) @@ -5312,7 +5318,13 @@ func TestLoadMixedRoutes(t *testing.T) { <-eventCh } - conf := p.loadConfigurationFromGateways(context.Background(), client) + p := Provider{ + EntryPoints: test.entryPoints, + ExperimentalChannel: test.experimentalChannel, + client: client, + } + + conf := p.loadConfigurationFromGateways(context.Background()) assert.Equal(t, test.expected, conf) }) } @@ -5441,9 +5453,9 @@ func TestLoadRoutesWithReferenceGrants(t *testing.T) { }, TCP: &dynamic.TCPConfiguration{ Routers: map[string]*dynamic.TCPRouter{ - "default-tcp-app-1-my-gateway-tls-e3b0c44298fc1c149afb": { + "default-tcp-app-1-my-gateway-tls": { EntryPoints: []string{"tls"}, - Service: "default-tcp-app-1-my-gateway-tls-e3b0c44298fc1c149afb-wrr-0", + Service: "default-tcp-app-1-my-gateway-tls-wrr-0", Rule: "HostSNI(`*`)", RuleSyntax: "v3", TLS: &dynamic.RouterTCPTLSConfig{}, @@ -5451,7 +5463,7 @@ func TestLoadRoutesWithReferenceGrants(t *testing.T) { }, Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ - "default-tcp-app-1-my-gateway-tls-e3b0c44298fc1c149afb-wrr-0": { + "default-tcp-app-1-my-gateway-tls-wrr-0": { Weighted: &dynamic.TCPWeightedRoundRobin{ Services: []dynamic.TCPWRRService{{ Name: "default-whoamitcp-9000", @@ -5589,17 +5601,17 @@ func TestLoadRoutesWithReferenceGrants(t *testing.T) { }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ - "default-http-app-1-my-gateway-http-f381ad97110137b4d42c": { + "default-http-app-1-my-gateway-http-0-d40286ed9f4652ca2108": { EntryPoints: []string{"http"}, - Rule: "Host(`foo.example.com`)", - Service: "default-http-app-1-my-gateway-http-f381ad97110137b4d42c-wrr", + Rule: "Host(`foo.example.com`) && PathPrefix(`/`)", + Service: "default-http-app-1-my-gateway-http-0-wrr", RuleSyntax: "v3", - Priority: 15, + Priority: 17, }, }, Middlewares: map[string]*dynamic.Middleware{}, Services: map[string]*dynamic.Service{ - "default-http-app-1-my-gateway-http-f381ad97110137b4d42c-wrr": { + "default-http-app-1-my-gateway-http-0-wrr": { Weighted: &dynamic.WeightedRoundRobin{ Services: []dynamic.WRRService{ { @@ -5626,11 +5638,6 @@ func TestLoadRoutesWithReferenceGrants(t *testing.T) { return } - p := Provider{ - EntryPoints: test.entryPoints, - ExperimentalChannel: test.experimentalChannel, - } - k8sObjects, gwObjects := readResources(t, test.paths) kubeClient := kubefake.NewSimpleClientset(k8sObjects...) @@ -5647,7 +5654,13 @@ func TestLoadRoutesWithReferenceGrants(t *testing.T) { <-eventCh } - conf := p.loadConfigurationFromGateways(context.Background(), client) + p := Provider{ + EntryPoints: test.entryPoints, + ExperimentalChannel: test.experimentalChannel, + client: client, + } + + conf := p.loadConfigurationFromGateways(context.Background()) assert.Equal(t, test.expected, conf) }) } @@ -6486,8 +6499,6 @@ func Test_gatewayAddresses(t *testing.T) { t.Run(test.desc, func(t *testing.T) { t.Parallel() - p := Provider{StatusAddress: test.statusAddress} - k8sObjects, gwObjects := readResources(t, test.paths) kubeClient := kubefake.NewSimpleClientset(k8sObjects...) @@ -6503,7 +6514,12 @@ func Test_gatewayAddresses(t *testing.T) { <-eventCh } - got, err := p.gatewayAddresses(client) + p := Provider{ + StatusAddress: test.statusAddress, + client: client, + } + + got, err := p.gatewayAddresses() test.wantErr(t, err) assert.Equal(t, test.want, got) diff --git a/pkg/provider/kubernetes/gateway/tcproute.go b/pkg/provider/kubernetes/gateway/tcproute.go index e0bafe99c..cdbb155ff 100644 --- a/pkg/provider/kubernetes/gateway/tcproute.go +++ b/pkg/provider/kubernetes/gateway/tcproute.go @@ -18,9 +18,9 @@ import ( gatev1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" ) -func (p *Provider) loadTCPRoutes(ctx context.Context, client Client, gatewayListeners []gatewayListener, conf *dynamic.Configuration) { +func (p *Provider) loadTCPRoutes(ctx context.Context, gatewayListeners []gatewayListener, conf *dynamic.Configuration) { logger := log.Ctx(ctx) - routes, err := client.ListTCPRoutes() + routes, err := p.client.ListTCPRoutes() if err != nil { logger.Error().Err(err).Msgf("Unable to list TCPRoutes") return @@ -64,7 +64,7 @@ func (p *Provider) loadTCPRoutes(ctx context.Context, client Client, gatewayList } } - routeConf, resolveRefCondition := p.loadTCPRoute(client, listener, route) + routeConf, resolveRefCondition := p.loadTCPRoute(listener, route) if accepted && listener.Attached { mergeTCPConfiguration(routeConf, conf) } @@ -79,7 +79,7 @@ func (p *Provider) loadTCPRoutes(ctx context.Context, client Client, gatewayList Parents: parentStatuses, }, } - if err := client.UpdateTCPRouteStatus(ctx, ktypes.NamespacedName{Namespace: route.Namespace, Name: route.Name}, routeStatus); err != nil { + if err := p.client.UpdateTCPRouteStatus(ctx, ktypes.NamespacedName{Namespace: route.Namespace, Name: route.Name}, routeStatus); err != nil { logger.Error(). Err(err). Msg("Unable to update TCPRoute status") @@ -87,8 +87,8 @@ func (p *Provider) loadTCPRoutes(ctx context.Context, client Client, gatewayList } } -func (p *Provider) loadTCPRoute(client Client, listener gatewayListener, route *gatev1alpha2.TCPRoute) (*dynamic.Configuration, metav1.Condition) { - routeConf := &dynamic.Configuration{ +func (p *Provider) loadTCPRoute(listener gatewayListener, route *gatev1alpha2.TCPRoute) (*dynamic.Configuration, metav1.Condition) { + conf := &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ Routers: make(map[string]*dynamic.TCPRouter), Middlewares: make(map[string]*dynamic.TCPMiddleware), @@ -97,7 +97,7 @@ func (p *Provider) loadTCPRoute(client Client, listener gatewayListener, route * }, } - routeCondition := metav1.Condition{ + condition := metav1.Condition{ Type: string(gatev1.RouteConditionResolvedRefs), Status: metav1.ConditionTrue, ObservedGeneration: route.Generation, @@ -119,8 +119,7 @@ func (p *Provider) loadTCPRoute(client Client, listener gatewayListener, route * } // Adding the gateway desc and the entryPoint desc prevents overlapping of routers build from the same routes. - routerName := route.Name + "-" + listener.GWName + "-" + listener.EPName - routerKey := provider.Normalize(makeRouterKey("", makeID(route.Namespace, routerName))) + routerName := provider.Normalize(route.Namespace + "-" + route.Name + "-" + listener.GWName + "-" + listener.EPName) var ruleServiceNames []string for i, rule := range route.Spec.Rules { @@ -130,9 +129,9 @@ func (p *Provider) loadTCPRoute(client Client, listener gatewayListener, route * continue } - wrrService, subServices, err := loadTCPServices(client, route.Namespace, rule.BackendRefs) + wrrService, subServices, err := p.loadTCPServices(route.Namespace, rule.BackendRefs) if err != nil { - return routeConf, metav1.Condition{ + return conf, metav1.Condition{ Type: string(gatev1.RouteConditionResolvedRefs), Status: metav1.ConditionFalse, ObservedGeneration: route.Generation, @@ -143,22 +142,22 @@ func (p *Provider) loadTCPRoute(client Client, listener gatewayListener, route * } for svcName, svc := range subServices { - routeConf.TCP.Services[svcName] = svc + conf.TCP.Services[svcName] = svc } - serviceName := fmt.Sprintf("%s-wrr-%d", routerKey, i) - routeConf.TCP.Services[serviceName] = wrrService + serviceName := fmt.Sprintf("%s-wrr-%d", routerName, i) + conf.TCP.Services[serviceName] = wrrService ruleServiceNames = append(ruleServiceNames, serviceName) } if len(ruleServiceNames) == 1 { router.Service = ruleServiceNames[0] - routeConf.TCP.Routers[routerKey] = &router - return routeConf, routeCondition + conf.TCP.Routers[routerName] = &router + return conf, condition } - routeServiceKey := routerKey + "-wrr" + routeServiceKey := routerName + "-wrr" routeService := &dynamic.TCPService{Weighted: &dynamic.TCPWeightedRoundRobin{}} for _, name := range ruleServiceNames { @@ -168,16 +167,16 @@ func (p *Provider) loadTCPRoute(client Client, listener gatewayListener, route * routeService.Weighted.Services = append(routeService.Weighted.Services, service) } - routeConf.TCP.Services[routeServiceKey] = routeService + conf.TCP.Services[routeServiceKey] = routeService router.Service = routeServiceKey - routeConf.TCP.Routers[routerKey] = &router + conf.TCP.Routers[routerName] = &router - return routeConf, routeCondition + return conf, condition } // loadTCPServices is generating a WRR service, even when there is only one target. -func loadTCPServices(client Client, namespace string, backendRefs []gatev1.BackendRef) (*dynamic.TCPService, map[string]*dynamic.TCPService, error) { +func (p *Provider) loadTCPServices(namespace string, backendRefs []gatev1.BackendRef) (*dynamic.TCPService, map[string]*dynamic.TCPService, error) { services := map[string]*dynamic.TCPService{} wrrSvc := &dynamic.TCPService{ @@ -211,7 +210,7 @@ func loadTCPServices(client Client, namespace string, backendRefs []gatev1.Backe LoadBalancer: &dynamic.TCPServersLoadBalancer{}, } - service, exists, err := client.GetService(namespace, string(backendRef.Name)) + service, exists, err := p.client.GetService(namespace, string(backendRef.Name)) if err != nil { return nil, nil, err } @@ -247,7 +246,7 @@ func loadTCPServices(client Client, namespace string, backendRefs []gatev1.Backe return nil, nil, errors.New("service port not found") } - endpoints, endpointsExists, endpointsErr := client.GetEndpoints(namespace, string(backendRef.Name)) + endpoints, endpointsExists, endpointsErr := p.client.GetEndpoints(namespace, string(backendRef.Name)) if endpointsErr != nil { return nil, nil, endpointsErr } @@ -282,7 +281,7 @@ func loadTCPServices(client Client, namespace string, backendRefs []gatev1.Backe } } - serviceName := provider.Normalize(makeID(service.Namespace, service.Name) + "-" + portStr) + serviceName := provider.Normalize(service.Namespace + "-" + service.Name + "-" + portStr) services[serviceName] = &svc wrrSvc.Weighted.Services = append(wrrSvc.Weighted.Services, dynamic.TCPWRRService{Name: serviceName, Weight: &weight}) diff --git a/pkg/provider/kubernetes/gateway/tlsroute.go b/pkg/provider/kubernetes/gateway/tlsroute.go index 62183b82d..131fb1d92 100644 --- a/pkg/provider/kubernetes/gateway/tlsroute.go +++ b/pkg/provider/kubernetes/gateway/tlsroute.go @@ -15,9 +15,9 @@ import ( gatev1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" ) -func (p *Provider) loadTLSRoutes(ctx context.Context, client Client, gatewayListeners []gatewayListener, conf *dynamic.Configuration) { +func (p *Provider) loadTLSRoutes(ctx context.Context, gatewayListeners []gatewayListener, conf *dynamic.Configuration) { logger := log.Ctx(ctx) - routes, err := client.ListTLSRoutes() + routes, err := p.client.ListTLSRoutes() if err != nil { logger.Error().Err(err).Msgf("Unable to list TLSRoute") return @@ -66,7 +66,7 @@ func (p *Provider) loadTLSRoutes(ctx context.Context, client Client, gatewayList } } - routeConf, resolveRefCondition := p.loadTLSRoute(client, listener, route, hostnames) + routeConf, resolveRefCondition := p.loadTLSRoute(listener, route, hostnames) if accepted && listener.Attached { mergeTCPConfiguration(routeConf, conf) } @@ -81,7 +81,7 @@ func (p *Provider) loadTLSRoutes(ctx context.Context, client Client, gatewayList Parents: parentStatuses, }, } - if err := client.UpdateTLSRouteStatus(ctx, ktypes.NamespacedName{Namespace: route.Namespace, Name: route.Name}, routeStatus); err != nil { + if err := p.client.UpdateTLSRouteStatus(ctx, ktypes.NamespacedName{Namespace: route.Namespace, Name: route.Name}, routeStatus); err != nil { logger.Error(). Err(err). Msg("Unable to update TLSRoute status") @@ -89,8 +89,8 @@ func (p *Provider) loadTLSRoutes(ctx context.Context, client Client, gatewayList } } -func (p *Provider) loadTLSRoute(client Client, listener gatewayListener, route *gatev1alpha2.TLSRoute, hostnames []gatev1.Hostname) (*dynamic.Configuration, metav1.Condition) { - routeConf := &dynamic.Configuration{ +func (p *Provider) loadTLSRoute(listener gatewayListener, route *gatev1alpha2.TLSRoute, hostnames []gatev1.Hostname) (*dynamic.Configuration, metav1.Condition) { + conf := &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ Routers: make(map[string]*dynamic.TCPRouter), Middlewares: make(map[string]*dynamic.TCPMiddleware), @@ -99,7 +99,7 @@ func (p *Provider) loadTLSRoute(client Client, listener gatewayListener, route * }, } - routeCondition := metav1.Condition{ + condition := metav1.Condition{ Type: string(gatev1.RouteConditionResolvedRefs), Status: metav1.ConditionTrue, ObservedGeneration: route.Generation, @@ -117,8 +117,8 @@ func (p *Provider) loadTLSRoute(client Client, listener gatewayListener, route * } // Adding the gateway desc and the entryPoint desc prevents overlapping of routers build from the same routes. - routerName := route.Name + "-" + listener.GWName + "-" + listener.EPName - routerKey := provider.Normalize(makeRouterKey(router.Rule, makeID(route.Namespace, routerName))) + routeKey := provider.Normalize(route.Namespace + "-" + route.Name + "-" + listener.GWName + "-" + listener.EPName) + routerName := makeRouterName(router.Rule, routeKey) var ruleServiceNames []string for i, routeRule := range route.Spec.Rules { @@ -128,10 +128,10 @@ func (p *Provider) loadTLSRoute(client Client, listener gatewayListener, route * continue } - wrrService, subServices, err := loadTCPServices(client, route.Namespace, routeRule.BackendRefs) + wrrService, subServices, err := p.loadTCPServices(route.Namespace, routeRule.BackendRefs) if err != nil { // update "ResolvedRefs" status true with "InvalidBackendRefs" reason - routeCondition = metav1.Condition{ + condition = metav1.Condition{ Type: string(gatev1.RouteConditionResolvedRefs), Status: metav1.ConditionFalse, ObservedGeneration: route.Generation, @@ -143,23 +143,23 @@ func (p *Provider) loadTLSRoute(client Client, listener gatewayListener, route * } for svcName, svc := range subServices { - routeConf.TCP.Services[svcName] = svc + conf.TCP.Services[svcName] = svc } - serviceName := fmt.Sprintf("%s-wrr-%d", routerKey, i) - routeConf.TCP.Services[serviceName] = wrrService + serviceName := fmt.Sprintf("%s-wrr-%d", routerName, i) + conf.TCP.Services[serviceName] = wrrService ruleServiceNames = append(ruleServiceNames, serviceName) } if len(ruleServiceNames) == 1 { router.Service = ruleServiceNames[0] - routeConf.TCP.Routers[routerKey] = &router + conf.TCP.Routers[routerName] = &router - return routeConf, routeCondition + return conf, condition } - routeServiceKey := routerKey + "-wrr" + routeServiceKey := routerName + "-wrr" routeService := &dynamic.TCPService{Weighted: &dynamic.TCPWeightedRoundRobin{}} for _, name := range ruleServiceNames { @@ -169,12 +169,12 @@ func (p *Provider) loadTLSRoute(client Client, listener gatewayListener, route * routeService.Weighted.Services = append(routeService.Weighted.Services, service) } - routeConf.TCP.Services[routeServiceKey] = routeService + conf.TCP.Services[routeServiceKey] = routeService router.Service = routeServiceKey - routeConf.TCP.Routers[routerKey] = &router + conf.TCP.Routers[routerName] = &router - return routeConf, routeCondition + return conf, condition } func hostSNIRule(hostnames []gatev1.Hostname) string {