From 5ea30d6e1626b0d609e72e46f04097cdcc6de5a7 Mon Sep 17 00:00:00 2001 From: Paul Abel Date: Mon, 3 Feb 2025 14:37:31 +0000 Subject: [PATCH 1/4] create function to generate errorPageDetails struct --- internal/configs/virtualserver.go | 20 ++++---- internal/configs/virtualserver_test.go | 69 ++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 10 deletions(-) diff --git a/internal/configs/virtualserver.go b/internal/configs/virtualserver.go index fc17a4f45c..deb0b2b056 100644 --- a/internal/configs/virtualserver.go +++ b/internal/configs/virtualserver.go @@ -552,11 +552,7 @@ func (vsc *virtualServerConfigurator) GenerateVirtualServerConfig( // generates config for VirtualServer routes for _, r := range vsEx.VirtualServer.Spec.Routes { - errorPages := errorPageDetails{ - pages: r.ErrorPages, - index: len(errorPageLocations), - owner: vsEx.VirtualServer, - } + errorPages := generateErrorPageDetails(r.ErrorPages, errorPageLocations, vsEx.VirtualServer) errorPageLocations = append(errorPageLocations, generateErrorPageLocations(errorPages.index, errorPages.pages)...) // ignore routes that reference VirtualServerRoute @@ -700,11 +696,7 @@ func (vsc *virtualServerConfigurator) GenerateVirtualServerConfig( isVSR := true upstreamNamer := NewUpstreamNamerForVirtualServerRoute(vsEx.VirtualServer, vsr) for _, r := range vsr.Spec.Subroutes { - errorPages := errorPageDetails{ - pages: r.ErrorPages, - index: len(errorPageLocations), - owner: vsr, - } + errorPages := generateErrorPageDetails(r.ErrorPages, errorPageLocations, vsr) errorPageLocations = append(errorPageLocations, generateErrorPageLocations(errorPages.index, errorPages.pages)...) vsrNamespaceName := fmt.Sprintf("%v/%v", vsr.Namespace, vsr.Name) // use the VirtualServer error pages if the route does not define any @@ -3265,6 +3257,14 @@ func generateErrorPages(errPageIndex int, errorPages []conf_v1.ErrorPage) []vers return ePages } +func generateErrorPageDetails(errorPages []conf_v1.ErrorPage, errorPageLocations []version2.ErrorPageLocation, owner runtime.Object) errorPageDetails { + return errorPageDetails{ + pages: errorPages, + index: len(errorPageLocations), + owner: owner, + } +} + func generateErrorPageLocations(errPageIndex int, errorPages []conf_v1.ErrorPage) []version2.ErrorPageLocation { var errorPageLocations []version2.ErrorPageLocation for i, e := range errorPages { diff --git a/internal/configs/virtualserver_test.go b/internal/configs/virtualserver_test.go index 11c7700496..1319fb6cdd 100644 --- a/internal/configs/virtualserver_test.go +++ b/internal/configs/virtualserver_test.go @@ -20019,6 +20019,75 @@ func TestGenerateErrorPageLocations(t *testing.T) { } } +func TestGenerateErrorPageDetails(t *testing.T) { + t.Parallel() + tests := []struct { + errorPages []conf_v1.ErrorPage + errorLocations []version2.ErrorPageLocation + owner runtime.Object + expected errorPageDetails + }{ + {}, // empty + { + errorPages: []conf_v1.ErrorPage{ + { + Codes: []int{404, 405, 500, 502}, + Return: &conf_v1.ErrorPageReturn{ + ActionReturn: conf_v1.ActionReturn{ + Code: 200, + Headers: nil, + }, + }, + Redirect: nil, + }, + }, + errorLocations: []version2.ErrorPageLocation{ + { + Name: "@error_page_0_0", + DefaultType: "text/plain", + Return: &version2.Return{ + Text: "All Good", + }, + }, + }, + owner: &conf_v1.VirtualServer{ + ObjectMeta: meta_v1.ObjectMeta{ + Namespace: "namespace", + Name: "name", + }, + }, + expected: errorPageDetails{ + pages: []conf_v1.ErrorPage{ + { + Codes: []int{404, 405, 500, 502}, + Return: &conf_v1.ErrorPageReturn{ + ActionReturn: conf_v1.ActionReturn{ + Code: 200, + Headers: nil, + }, + }, + Redirect: nil, + }, + }, + index: 1, + owner: &conf_v1.VirtualServer{ + ObjectMeta: meta_v1.ObjectMeta{ + Namespace: "namespace", + Name: "name", + }, + }, + }, + }, + } + + for _, test := range tests { + result := generateErrorPageDetails(test.errorPages, test.errorLocations, test.owner) + if !reflect.DeepEqual(result, test.expected) { + t.Errorf("generateErrorPageDetails() returned %v but expected %v", result, test.expected) + } + } +} + func TestGenerateProxySSLName(t *testing.T) { t.Parallel() result := generateProxySSLName("coffee-v1", "default") From ea0aee667b5e0319268b98b81e60e5ce1ef0634e Mon Sep 17 00:00:00 2001 From: Paul Abel Date: Mon, 3 Feb 2025 15:40:45 +0000 Subject: [PATCH 2/4] rename backup endpoint variable --- internal/configs/virtualserver.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/internal/configs/virtualserver.go b/internal/configs/virtualserver.go index deb0b2b056..b180fda749 100644 --- a/internal/configs/virtualserver.go +++ b/internal/configs/virtualserver.go @@ -481,13 +481,12 @@ func (vsc *virtualServerConfigurator) GenerateVirtualServerConfig( upstreamName := virtualServerUpstreamNamer.GetNameForUpstream(u.Name) upstreamNamespace := vsEx.VirtualServer.Namespace endpoints := vsc.generateEndpointsForUpstream(vsEx.VirtualServer, upstreamNamespace, u, vsEx) - backupEndpoints := vsc.generateBackupEndpointsForUpstream(vsEx.VirtualServer, upstreamNamespace, u, vsEx) + backup := vsc.generateBackupEndpointsForUpstream(vsEx.VirtualServer, upstreamNamespace, u, vsEx) // isExternalNameSvc is always false for OSS _, isExternalNameSvc := vsEx.ExternalNameSvcs[GenerateExternalNameSvcKey(upstreamNamespace, u.Service)] - ups := vsc.generateUpstream(vsEx.VirtualServer, upstreamName, u, isExternalNameSvc, endpoints, backupEndpoints) + ups := vsc.generateUpstream(vsEx.VirtualServer, upstreamName, u, isExternalNameSvc, endpoints, backup) upstreams = append(upstreams, ups) - u.TLS.Enable = isTLSEnabled(u, vsc.spiffeCerts, vsEx.VirtualServer.Spec.InternalRoute) crUpstreams[upstreamName] = u From 4a9f3204e67ca30fcb78f1a8e715fa16a565cc42 Mon Sep 17 00:00:00 2001 From: Paul Abel Date: Tue, 4 Feb 2025 13:48:03 +0000 Subject: [PATCH 3/4] move similar generate upstreams to a function --- internal/configs/virtualserver.go | 117 +++++++++++++++++------------- 1 file changed, 66 insertions(+), 51 deletions(-) diff --git a/internal/configs/virtualserver.go b/internal/configs/virtualserver.go index b180fda749..d74542abfe 100644 --- a/internal/configs/virtualserver.go +++ b/internal/configs/virtualserver.go @@ -473,62 +473,37 @@ func (vsc *virtualServerConfigurator) GenerateVirtualServerConfig( // generate upstreams for VirtualServer for _, u := range vsEx.VirtualServer.Spec.Upstreams { - - if (sslConfig == nil || !vsc.cfgParams.HTTP2) && isGRPC(u.Type) { - vsc.addWarningf(vsEx.VirtualServer, "gRPC cannot be configured for upstream %s. gRPC requires enabled HTTP/2 and TLS termination.", u.Name) - } - - upstreamName := virtualServerUpstreamNamer.GetNameForUpstream(u.Name) - upstreamNamespace := vsEx.VirtualServer.Namespace - endpoints := vsc.generateEndpointsForUpstream(vsEx.VirtualServer, upstreamNamespace, u, vsEx) - backup := vsc.generateBackupEndpointsForUpstream(vsEx.VirtualServer, upstreamNamespace, u, vsEx) - - // isExternalNameSvc is always false for OSS - _, isExternalNameSvc := vsEx.ExternalNameSvcs[GenerateExternalNameSvcKey(upstreamNamespace, u.Service)] - ups := vsc.generateUpstream(vsEx.VirtualServer, upstreamName, u, isExternalNameSvc, endpoints, backup) - upstreams = append(upstreams, ups) - u.TLS.Enable = isTLSEnabled(u, vsc.spiffeCerts, vsEx.VirtualServer.Spec.InternalRoute) - crUpstreams[upstreamName] = u - - if hc := generateHealthCheck(u, upstreamName, vsc.cfgParams); hc != nil { - healthChecks = append(healthChecks, *hc) - if u.HealthCheck.StatusMatch != "" { - statusMatches = append( - statusMatches, - generateUpstreamStatusMatch(upstreamName, u.HealthCheck.StatusMatch), - ) - } - } + upstreams, healthChecks, statusMatches = generateUpstreams( + sslConfig, + vsc, + u, + vsEx.VirtualServer, + vsEx.VirtualServer.Namespace, + virtualServerUpstreamNamer, + vsEx, + upstreams, + crUpstreams, + healthChecks, + statusMatches, + ) } // generate upstreams for each VirtualServerRoute for _, vsr := range vsEx.VirtualServerRoutes { upstreamNamer := NewUpstreamNamerForVirtualServerRoute(vsEx.VirtualServer, vsr) for _, u := range vsr.Spec.Upstreams { - if (sslConfig == nil || !vsc.cfgParams.HTTP2) && isGRPC(u.Type) { - vsc.addWarningf(vsr, "gRPC cannot be configured for upstream %s. gRPC requires enabled HTTP/2 and TLS termination", u.Name) - } - - upstreamName := upstreamNamer.GetNameForUpstream(u.Name) - upstreamNamespace := vsr.Namespace - endpoints := vsc.generateEndpointsForUpstream(vsr, upstreamNamespace, u, vsEx) - backup := vsc.generateBackupEndpointsForUpstream(vsEx.VirtualServer, upstreamNamespace, u, vsEx) - - // isExternalNameSvc is always false for OSS - _, isExternalNameSvc := vsEx.ExternalNameSvcs[GenerateExternalNameSvcKey(upstreamNamespace, u.Service)] - ups := vsc.generateUpstream(vsr, upstreamName, u, isExternalNameSvc, endpoints, backup) - upstreams = append(upstreams, ups) - u.TLS.Enable = isTLSEnabled(u, vsc.spiffeCerts, vsEx.VirtualServer.Spec.InternalRoute) - crUpstreams[upstreamName] = u - - if hc := generateHealthCheck(u, upstreamName, vsc.cfgParams); hc != nil { - healthChecks = append(healthChecks, *hc) - if u.HealthCheck.StatusMatch != "" { - statusMatches = append( - statusMatches, - generateUpstreamStatusMatch(upstreamName, u.HealthCheck.StatusMatch), - ) - } - } + upstreams, healthChecks, statusMatches = generateUpstreams( + sslConfig, + vsc, + u, + vsr, + vsr.Namespace, + upstreamNamer, + vsEx, + upstreams, + crUpstreams, + healthChecks, + statusMatches, + ) } } @@ -921,6 +896,46 @@ func (vsc *virtualServerConfigurator) GenerateVirtualServerConfig( return vsCfg, vsc.warnings } +func generateUpstreams( + sslConfig *version2.SSL, + vsc *virtualServerConfigurator, + u conf_v1.Upstream, + owner runtime.Object, + ownerNamespace string, + upstreamNamer *upstreamNamer, + vsEx *VirtualServerEx, + upstreams []version2.Upstream, + crUpstreams map[string]conf_v1.Upstream, + healthChecks []version2.HealthCheck, + statusMatches []version2.StatusMatch, +) ([]version2.Upstream, []version2.HealthCheck, []version2.StatusMatch) { + if (sslConfig == nil || !vsc.cfgParams.HTTP2) && isGRPC(u.Type) { + vsc.addWarningf(owner, "gRPC cannot be configured for upstream %s. gRPC requires enabled HTTP/2 and TLS termination", u.Name) + } + + upstreamName := upstreamNamer.GetNameForUpstream(u.Name) + endpoints := vsc.generateEndpointsForUpstream(owner, ownerNamespace, u, vsEx) + backup := vsc.generateBackupEndpointsForUpstream(owner, ownerNamespace, u, vsEx) + + // isExternalNameSvc is always false for OSS + _, isExternalNameSvc := vsEx.ExternalNameSvcs[GenerateExternalNameSvcKey(ownerNamespace, u.Service)] + ups := vsc.generateUpstream(owner, upstreamName, u, isExternalNameSvc, endpoints, backup) + upstreams = append(upstreams, ups) + u.TLS.Enable = isTLSEnabled(u, vsc.spiffeCerts, vsEx.VirtualServer.Spec.InternalRoute) + crUpstreams[upstreamName] = u + + if hc := generateHealthCheck(u, upstreamName, vsc.cfgParams); hc != nil { + healthChecks = append(healthChecks, *hc) + if u.HealthCheck.StatusMatch != "" { + statusMatches = append( + statusMatches, + generateUpstreamStatusMatch(upstreamName, u.HealthCheck.StatusMatch), + ) + } + } + return upstreams, healthChecks, statusMatches +} + // rateLimit hold the configuration for the ratelimiting Policy type rateLimit struct { Reqs []version2.LimitReq From 91a850ba39495e40fd46c5ae74f8752f60479505 Mon Sep 17 00:00:00 2001 From: Paul Abel Date: Fri, 18 Jul 2025 12:36:29 +0100 Subject: [PATCH 4/4] fix owner for backup endpoints --- internal/configs/virtualserver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/configs/virtualserver.go b/internal/configs/virtualserver.go index d74542abfe..c285e92f24 100644 --- a/internal/configs/virtualserver.go +++ b/internal/configs/virtualserver.go @@ -915,7 +915,7 @@ func generateUpstreams( upstreamName := upstreamNamer.GetNameForUpstream(u.Name) endpoints := vsc.generateEndpointsForUpstream(owner, ownerNamespace, u, vsEx) - backup := vsc.generateBackupEndpointsForUpstream(owner, ownerNamespace, u, vsEx) + backup := vsc.generateBackupEndpointsForUpstream(vsEx.VirtualServer, ownerNamespace, u, vsEx) // isExternalNameSvc is always false for OSS _, isExternalNameSvc := vsEx.ExternalNameSvcs[GenerateExternalNameSvcKey(ownerNamespace, u.Service)]