diff --git a/docs-web/configuration/global-configuration/configmap-resource.md b/docs-web/configuration/global-configuration/configmap-resource.md index cda394b8af..ca19005e97 100644 --- a/docs-web/configuration/global-configuration/configmap-resource.md +++ b/docs-web/configuration/global-configuration/configmap-resource.md @@ -205,7 +205,7 @@ See the doc about [VirtualServer and VirtualServerRoute resources](/nginx-ingres * - ``log-format`` - Sets the custom `log format `_ for HTTP and HTTPS traffic. For convenience, it is possible to define the log format across multiple lines (each line separated by ``\n``). In that case, the Ingress Controller will replace every ``\n`` character with a space character. All ``'`` characters must be escaped. - See the `template file `_ for the access log. - - + - `Custom Log Format `_. * - ``log-format-escaping`` - Sets the characters escaping for the variables of the log format. Supported values: ``json`` (JSON escaping), ``default`` (the default escaping) ``none`` (disables escaping). - ``default`` diff --git a/examples/custom-log-format/README.md b/examples/custom-log-format/README.md new file mode 100644 index 0000000000..dc2cfee4c9 --- /dev/null +++ b/examples/custom-log-format/README.md @@ -0,0 +1,22 @@ +# Custom NGINX log format + +This example lets you set the log-format for NGINX using the configmap reosurce + +```yaml +kind: ConfigMap +apiVersion: v1 +metadata: + name: nginx-config +data: + log-format: | + compression '$remote_addr - $remote_user [$time_local] ' + '"$request" $status $bytes_sent ' + '"$http_referer" "$http_user_agent" "$gzip_ratio"' +``` + +In addition to the built-in NGINX variables, you can also use the variables that the Ingress Controller configures: + +- $resource_type - The type of k8s resource. +- $resource_name - The name of the k8s resource +- $resource_namespace - The namespace the resource exists in. +- $service - The service that exposes the resource. diff --git a/internal/configs/ingress.go b/internal/configs/ingress.go index ad6c5105ab..e6a5ab6006 100644 --- a/internal/configs/ingress.go +++ b/internal/configs/ingress.go @@ -200,7 +200,7 @@ func generateNginxCfg(ingEx *IngressEx, pems map[string]string, apResources map[ ssl := isSSLEnabled(sslServices[path.Backend.ServiceName], cfgParams, staticParams) proxySSLName := generateProxySSLName(path.Backend.ServiceName, ingEx.Ingress.Namespace) loc := createLocation(pathOrDefault(path.Path), upstreams[upsName], &cfgParams, wsServices[path.Backend.ServiceName], rewrites[path.Backend.ServiceName], - ssl, grpcServices[path.Backend.ServiceName], proxySSLName, path.PathType) + ssl, grpcServices[path.Backend.ServiceName], proxySSLName, path.PathType, path.Backend.ServiceName) if isMinion && ingEx.JWTKey.Name != "" { loc.JWTAuth = &version1.JWTAuth{ Key: jwtKeyFileName, @@ -230,7 +230,7 @@ func generateNginxCfg(ingEx *IngressEx, pems map[string]string, apResources map[ pathtype := networking.PathTypePrefix loc := createLocation(pathOrDefault("/"), upstreams[upsName], &cfgParams, wsServices[ingEx.Ingress.Spec.Backend.ServiceName], rewrites[ingEx.Ingress.Spec.Backend.ServiceName], - ssl, grpcServices[ingEx.Ingress.Spec.Backend.ServiceName], proxySSLName, &pathtype) + ssl, grpcServices[ingEx.Ingress.Spec.Backend.ServiceName], proxySSLName, &pathtype, ingEx.Ingress.Spec.Backend.ServiceName) locations = append(locations, loc) if cfgParams.HealthCheckEnabled { @@ -280,7 +280,7 @@ func generateIngressPath(path string, pathType *networking.PathType) string { return path } -func createLocation(path string, upstream version1.Upstream, cfg *ConfigParams, websocket bool, rewrite string, ssl bool, grpc bool, proxySSLName string, pathType *networking.PathType) version1.Location { +func createLocation(path string, upstream version1.Upstream, cfg *ConfigParams, websocket bool, rewrite string, ssl bool, grpc bool, proxySSLName string, pathType *networking.PathType, serviceName string) version1.Location { loc := version1.Location{ Path: generateIngressPath(path, pathType), Upstream: upstream, @@ -298,6 +298,7 @@ func createLocation(path string, upstream version1.Upstream, cfg *ConfigParams, ProxyMaxTempFileSize: cfg.ProxyMaxTempFileSize, ProxySSLName: proxySSLName, LocationSnippets: cfg.LocationSnippets, + ServiceName: serviceName, } return loc diff --git a/internal/configs/ingress_test.go b/internal/configs/ingress_test.go index a4613665e3..81d76b11c5 100644 --- a/internal/configs/ingress_test.go +++ b/internal/configs/ingress_test.go @@ -206,6 +206,7 @@ func createExpectedConfigForCafeIngressEx() version1.IngressNginxConfig { Locations: []version1.Location{ { Path: "/coffee", + ServiceName: "coffee-svc", Upstream: coffeeUpstream, ProxyConnectTimeout: "60s", ProxyReadTimeout: "60s", @@ -216,6 +217,7 @@ func createExpectedConfigForCafeIngressEx() version1.IngressNginxConfig { }, { Path: "/tea", + ServiceName: "tea-svc", Upstream: teaUpstream, ProxyConnectTimeout: "60s", ProxyReadTimeout: "60s", @@ -610,6 +612,7 @@ func createExpectedConfigForMergeableCafeIngress() version1.IngressNginxConfig { Locations: []version1.Location{ { Path: "/coffee", + ServiceName: "coffee-svc", Upstream: coffeeUpstream, ProxyConnectTimeout: "60s", ProxyReadTimeout: "60s", @@ -628,6 +631,7 @@ func createExpectedConfigForMergeableCafeIngress() version1.IngressNginxConfig { }, { Path: "/tea", + ServiceName: "tea-svc", Upstream: teaUpstream, ProxyConnectTimeout: "60s", ProxyReadTimeout: "60s", @@ -710,6 +714,7 @@ func createExpectedConfigForCrossNamespaceMergeableCafeIngress() version1.Ingres Locations: []version1.Location{ { Path: "/coffee", + ServiceName: "coffee-svc", Upstream: coffeeUpstream, ProxyConnectTimeout: "60s", ProxyReadTimeout: "60s", @@ -728,6 +733,7 @@ func createExpectedConfigForCrossNamespaceMergeableCafeIngress() version1.Ingres }, { Path: "/tea", + ServiceName: "tea-svc", Upstream: teaUpstream, ProxyConnectTimeout: "60s", ProxyReadTimeout: "60s", diff --git a/internal/configs/transportserver.go b/internal/configs/transportserver.go index 8cca246c7e..78ac25a507 100644 --- a/internal/configs/transportserver.go +++ b/internal/configs/transportserver.go @@ -49,6 +49,8 @@ func generateTransportServerConfig(transportServerEx *TransportServerEx, listene ProxyRequests: proxyRequests, ProxyResponses: proxyResponses, ProxyPass: upstreamNamer.GetNameForUpstream(transportServerEx.TransportServer.Spec.Action.Pass), + Name: transportServerEx.TransportServer.Name, + Namespace: transportServerEx.TransportServer.Namespace, }, Upstreams: upstreams, } diff --git a/internal/configs/transportserver_test.go b/internal/configs/transportserver_test.go index 1112f158e9..a0e14f1b31 100644 --- a/internal/configs/transportserver_test.go +++ b/internal/configs/transportserver_test.go @@ -110,6 +110,8 @@ func TestGenerateTransportServerConfigForTCP(t *testing.T) { UDP: false, StatusZone: "tcp-listener", ProxyPass: "ts_default_tcp-server_tcp-app", + Name: "tcp-server", + Namespace: "default", }, } @@ -178,6 +180,8 @@ func TestGenerateTransportServerConfigForUDP(t *testing.T) { ProxyRequests: &udpRequests, ProxyResponses: &udpResponses, ProxyPass: "ts_default_udp-server_udp-app", + Name: "udp-server", + Namespace: "default", }, } diff --git a/internal/configs/version1/config.go b/internal/configs/version1/config.go index a925f8d083..ac9f160385 100644 --- a/internal/configs/version1/config.go +++ b/internal/configs/version1/config.go @@ -136,6 +136,7 @@ type Location struct { ProxyMaxTempFileSize string ProxySSLName string JWTAuth *JWTAuth + ServiceName string MinionIngress *Ingress } diff --git a/internal/configs/version1/nginx-plus.ingress.tmpl b/internal/configs/version1/nginx-plus.ingress.tmpl index 9bd8f125d8..6cb76db497 100644 --- a/internal/configs/version1/nginx-plus.ingress.tmpl +++ b/internal/configs/version1/nginx-plus.ingress.tmpl @@ -60,6 +60,10 @@ server { status_zone {{$server.StatusZone}}; + set $resource_type "ingress"; + set $resource_name "{{$.Ingress.Name}}"; + set $resource_namespace "{{$.Ingress.Namespace}}"; + {{- if $server.AppProtectEnable}} app_protect_enable {{$server.AppProtectEnable}}; {{if $server.AppProtectPolicy}}app_protect_policy_file {{$server.AppProtectPolicy}};{{end}} @@ -143,8 +147,11 @@ server { {{range $location := $server.Locations}} location {{$location.Path}} { + set $service "{{$location.ServiceName}}"; {{with $location.MinionIngress}} # location for minion {{$location.MinionIngress.Namespace}}/{{$location.MinionIngress.Name}} + set $resource_name "{{$location.MinionIngress.Name}}"; + set $resource_namespace "{{$location.MinionIngress.Namespace}}"; {{end}} {{if $location.GRPC}} {{if not $server.GRPCOnly}} diff --git a/internal/configs/version1/nginx-plus.tmpl b/internal/configs/version1/nginx-plus.tmpl index 8b0b73f2c5..f12908a384 100644 --- a/internal/configs/version1/nginx-plus.tmpl +++ b/internal/configs/version1/nginx-plus.tmpl @@ -44,7 +44,11 @@ http { {{- else -}} log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; + '"$http_user_agent" "$http_x_forwarded_for" ' + 'resource_type="$resource_type" ' + 'resource_name="$resource_name" ' + 'resource_namespace="$resource_namespace" ' + 'service="$service"'; {{- end}} {{if .AccessLogOff}} @@ -106,6 +110,10 @@ http { server { # required to support the Websocket protocol in VirtualServer/VirtualServerRoutes set $default_connection_header ""; + set $resource_type ""; + set $resource_name ""; + set $resource_namespace ""; + set $service ""; listen 80 default_server{{if .ProxyProtocol}} proxy_protocol{{end}}; diff --git a/internal/configs/version1/nginx.ingress.tmpl b/internal/configs/version1/nginx.ingress.tmpl index 226102714c..8f3162ca9a 100644 --- a/internal/configs/version1/nginx.ingress.tmpl +++ b/internal/configs/version1/nginx.ingress.tmpl @@ -1,5 +1,4 @@ # configuration for {{.Ingress.Namespace}}/{{.Ingress.Name}} - {{range $upstream := .Upstreams}} upstream {{$upstream.Name}} { {{if ne $upstream.UpstreamZoneSize "0"}}zone {{$upstream.Name}} {{$upstream.UpstreamZoneSize}};{{end}} @@ -43,6 +42,10 @@ server { server_name {{$server.Name}}; + set $resource_type "ingress"; + set $resource_name "{{$.Ingress.Name}}"; + set $resource_namespace "{{$.Ingress.Namespace}}"; + {{range $proxyHideHeader := $server.ProxyHideHeaders}} proxy_hide_header {{$proxyHideHeader}};{{end}} {{range $proxyPassHeader := $server.ProxyPassHeaders}} @@ -85,8 +88,11 @@ server { {{range $location := $server.Locations}} location {{$location.Path}} { + set $service "{{$location.ServiceName}}"; {{with $location.MinionIngress}} # location for minion {{$location.MinionIngress.Namespace}}/{{$location.MinionIngress.Name}} + set $resource_name "{{$location.MinionIngress.Name}}"; + set $resource_namespace "{{$location.MinionIngress.Namespace}}"; {{end}} {{if $location.GRPC}} {{if not $server.GRPCOnly}} diff --git a/internal/configs/version1/nginx.tmpl b/internal/configs/version1/nginx.tmpl index 1ed57b7774..94440b38fc 100644 --- a/internal/configs/version1/nginx.tmpl +++ b/internal/configs/version1/nginx.tmpl @@ -92,6 +92,7 @@ http { server { # required to support the Websocket protocol in VirtualServer/VirtualServerRoutes set $default_connection_header ""; + set $resource_type ""; listen 80 default_server{{if .ProxyProtocol}} proxy_protocol{{end}}; diff --git a/internal/configs/version2/http.go b/internal/configs/version2/http.go index 60f44155aa..9de9b95d0b 100644 --- a/internal/configs/version2/http.go +++ b/internal/configs/version2/http.go @@ -70,6 +70,7 @@ type Server struct { IngressMTLS *IngressMTLS EgressMTLS *EgressMTLS PoliciesErrorReturn *Return + Namespace string } // SSL defines SSL configuration for a server. @@ -138,6 +139,10 @@ type Location struct { JWTAuth *JWTAuth EgressMTLS *EgressMTLS PoliciesErrorReturn *Return + ServiceName string + IsVSR bool + VSRName string + VSRNamespace string } // ReturnLocation defines a location for returning a fixed response. diff --git a/internal/configs/version2/nginx-plus.transportserver.tmpl b/internal/configs/version2/nginx-plus.transportserver.tmpl index bb92cd0cfe..013d8581ff 100644 --- a/internal/configs/version2/nginx-plus.transportserver.tmpl +++ b/internal/configs/version2/nginx-plus.transportserver.tmpl @@ -12,6 +12,10 @@ upstream {{ $u.Name }} { {{ $s := .Server }} server { + set $resource_type "transportserver"; + set $resource_name "{{$s.Name}}"; + set $resource_namespace "{{$s.Namespace}}"; + {{ if $s.TLSPassthrough }} listen {{ $s.UnixSocket }} proxy_protocol; set_real_ip_from unix:; diff --git a/internal/configs/version2/nginx-plus.virtualserver.tmpl b/internal/configs/version2/nginx-plus.virtualserver.tmpl index 71e2290f2b..7be245803f 100644 --- a/internal/configs/version2/nginx-plus.virtualserver.tmpl +++ b/internal/configs/version2/nginx-plus.virtualserver.tmpl @@ -61,6 +61,10 @@ server { server_name {{ $s.ServerName }}; status_zone {{ $s.StatusZone }}; + set $resource_type "virtualserver"; + set $resource_name "{{$s.ServerName}}"; + set $resource_namespace "{{$s.Namespace}}"; + {{ with $ssl := $s.SSL }} {{ if $s.TLSPassthrough }} listen unix:/var/lib/nginx/passthrough-https.sock{{ if $ssl.HTTP2 }} http2{{ end }} proxy_protocol; @@ -207,6 +211,13 @@ server { {{ range $l := $s.Locations }} location {{ $l.Path }} { + set $service "{{ $l.ServiceName }}"; + {{ if $l.IsVSR }} + set $resource_type "virtualserverroute"; + set $resource_name "{{ $l.VSRName }}"; + set $resource_namespace "{{ $l.VSRNamespace }}"; + {{ end }} + {{ if $l.Internal }} internal; {{ end }} diff --git a/internal/configs/version2/nginx.transportserver.tmpl b/internal/configs/version2/nginx.transportserver.tmpl index d19bfca69b..60aacb923c 100644 --- a/internal/configs/version2/nginx.transportserver.tmpl +++ b/internal/configs/version2/nginx.transportserver.tmpl @@ -12,6 +12,9 @@ upstream {{ $u.Name }} { {{ $s := .Server }} server { + set $resource_type "transportserver"; + set $resource_name "{{$s.Name}}"; + set $resource_namespace "{{$s.Namespace}}"; {{ if $s.TLSPassthrough }} listen {{ $s.UnixSocket }} proxy_protocol; set_real_ip_from unix:; diff --git a/internal/configs/version2/nginx.virtualserver.tmpl b/internal/configs/version2/nginx.virtualserver.tmpl index 54ebf40d44..d543bd7b43 100644 --- a/internal/configs/version2/nginx.virtualserver.tmpl +++ b/internal/configs/version2/nginx.virtualserver.tmpl @@ -44,6 +44,11 @@ server { server_name {{ $s.ServerName }}; + set $resource_type "virtualserver"; + set $resource_name "{{$s.ServerName}}"; + set $resource_namespace "{{$s.Namespace}}"; + + {{ with $ssl := $s.SSL }} {{ if $s.TLSPassthrough }} listen unix:/var/lib/nginx/passthrough-https.sock{{ if $ssl.HTTP2 }} http2{{ end }} proxy_protocol; @@ -171,6 +176,7 @@ server { {{ range $l := $s.Locations }} location {{ $l.Path }} { + set $service "{{$l.ServiceName}}"; {{ if $l.Internal }} internal; {{ end }} diff --git a/internal/configs/version2/stream.go b/internal/configs/version2/stream.go index aa8783fe86..ca6da09dc6 100644 --- a/internal/configs/version2/stream.go +++ b/internal/configs/version2/stream.go @@ -27,6 +27,8 @@ type StreamServer struct { ProxyRequests *int ProxyResponses *int ProxyPass string + Name string + Namespace string } // TLSPassthroughHostsConfig defines a mapping between TLS Passthrough hosts and the corresponding unix sockets. diff --git a/internal/configs/virtualserver.go b/internal/configs/virtualserver.go index 3e87a5636f..e5e1572ee0 100644 --- a/internal/configs/virtualserver.go +++ b/internal/configs/virtualserver.go @@ -359,6 +359,7 @@ func (vsc *virtualServerConfigurator) GenerateVirtualServerConfig( var vsrErrorPagesRouteIndex = make(map[string]int) var vsrLocationSnippetsFromVs = make(map[string]string) var vsrPoliciesFromVs = make(map[string][]conf_v1.PolicyReference) + isVSR := false matchesRoutes := 0 variableNamer := newVariableNamer(vsEx.VirtualServer) @@ -450,7 +451,7 @@ func (vsc *virtualServerConfigurator) GenerateVirtualServerConfig( proxySSLName := generateProxySSLName(upstream.Service, vsEx.VirtualServer.Namespace) loc, returnLoc := generateLocation(r.Path, upstreamName, upstream, r.Action, vsc.cfgParams, r.ErrorPages, false, - errorPageIndex, proxySSLName, r.Path, vsLocSnippets, vsc.enableSnippets, len(returnLocations)) + errorPageIndex, proxySSLName, r.Path, vsLocSnippets, vsc.enableSnippets, len(returnLocations), isVSR, "", "") addPoliciesCfgToLocation(routePoliciesCfg, &loc) locations = append(locations, loc) @@ -462,6 +463,7 @@ func (vsc *virtualServerConfigurator) GenerateVirtualServerConfig( // generate config for subroutes of each VirtualServerRoute for _, vsr := range vsEx.VirtualServerRoutes { + isVSR := true upstreamNamer := newUpstreamNamerForVirtualServerRoute(vsEx.VirtualServer, vsr) for _, r := range vsr.Spec.Subroutes { errorPageIndex := len(errorPageLocations) @@ -553,7 +555,7 @@ func (vsc *virtualServerConfigurator) GenerateVirtualServerConfig( proxySSLName := generateProxySSLName(upstream.Service, vsr.Namespace) loc, returnLoc := generateLocation(r.Path, upstreamName, upstream, r.Action, vsc.cfgParams, errorPages, false, - errorPageIndex, proxySSLName, r.Path, locSnippets, vsc.enableSnippets, len(returnLocations)) + errorPageIndex, proxySSLName, r.Path, locSnippets, vsc.enableSnippets, len(returnLocations), isVSR, vsr.Name, vsr.Namespace) addPoliciesCfgToLocation(routePoliciesCfg, &loc) locations = append(locations, loc) @@ -605,6 +607,7 @@ func (vsc *virtualServerConfigurator) GenerateVirtualServerConfig( IngressMTLS: policiesCfg.IngressMTLS, EgressMTLS: policiesCfg.EgressMTLS, PoliciesErrorReturn: policiesCfg.ErrorReturn, + Namespace: vsEx.VirtualServer.Namespace, }, SpiffeCerts: vsc.spiffeCerts, } @@ -1261,21 +1264,9 @@ func generateReturnBlock(text string, code int, defaultCode int) *version2.Retur return returnBlock } -func generateLocation( - path string, - upstreamName string, - upstream conf_v1.Upstream, - action *conf_v1.Action, - cfgParams *ConfigParams, - errorPages []conf_v1.ErrorPage, - internal bool, - errPageIndex int, - proxySSLName string, - originalPath string, - locSnippets string, - enableSnippets bool, - retLocIndex int, -) (version2.Location, *version2.ReturnLocation) { +func generateLocation(path string, upstreamName string, upstream conf_v1.Upstream, action *conf_v1.Action, + cfgParams *ConfigParams, errorPages []conf_v1.ErrorPage, internal bool, errPageIndex int, proxySSLName string, + originalPath string, locSnippets string, enableSnippets bool, retLocIndex int, isVSR bool, vsrName string, vsrNamespace string) (version2.Location, *version2.ReturnLocation) { locationSnippets := generateSnippets(enableSnippets, locSnippets, cfgParams.LocationSnippets) @@ -1287,19 +1278,8 @@ func generateLocation( return generateLocationForReturn(path, cfgParams.LocationSnippets, action.Return, retLocIndex) } - return generateLocationForProxying( - path, - upstreamName, - upstream, - cfgParams, - errorPages, - internal, - errPageIndex, - proxySSLName, - action.Proxy, - originalPath, - locationSnippets, - ), nil + return generateLocationForProxying(path, upstreamName, upstream, cfgParams, errorPages, internal, + errPageIndex, proxySSLName, action.Proxy, originalPath, locationSnippets, isVSR, vsrName, vsrNamespace), nil } func generateProxySetHeaders(proxy *conf_v1.ActionProxy) []version2.Header { @@ -1375,7 +1355,7 @@ func generateProxyAddHeaders(proxy *conf_v1.ActionProxy) []version2.AddHeader { func generateLocationForProxying(path string, upstreamName string, upstream conf_v1.Upstream, cfgParams *ConfigParams, errorPages []conf_v1.ErrorPage, internal bool, errPageIndex int, - proxySSLName string, proxy *conf_v1.ActionProxy, originalPath string, locationSnippets []string) version2.Location { + proxySSLName string, proxy *conf_v1.ActionProxy, originalPath string, locationSnippets []string, isVSR bool, vsrName string, vsrNamespace string) version2.Location { return version2.Location{ Path: generatePath(path), Internal: internal, @@ -1404,6 +1384,10 @@ func generateLocationForProxying(path string, upstreamName string, upstream conf HasKeepalive: upstreamHasKeepalive(upstream, cfgParams), ErrorPages: generateErrorPages(errPageIndex, errorPages), ProxySSLName: proxySSLName, + ServiceName: upstream.Service, + IsVSR: isVSR, + VSRName: vsrName, + VSRNamespace: vsrNamespace, } } @@ -1495,6 +1479,9 @@ func generateSplits( ) (version2.SplitClient, []version2.Location, []version2.ReturnLocation) { var distributions []version2.Distribution + isVSR := false + vsrName := "" + vsrNamespace := "" for i, s := range splits { d := version2.Distribution{ @@ -1520,7 +1507,7 @@ func generateSplits( proxySSLName := generateProxySSLName(upstream.Service, upstreamNamer.namespace) newRetLocIndex := retLocIndex + len(returnLocations) loc, returnLoc := generateLocation(path, upstreamName, upstream, s.Action, cfgParams, errorPages, true, - errPageIndex, proxySSLName, originalPath, locSnippets, enableSnippets, newRetLocIndex) + errPageIndex, proxySSLName, originalPath, locSnippets, enableSnippets, newRetLocIndex, isVSR, vsrName, vsrNamespace) locations = append(locations, loc) if returnLoc != nil { returnLocations = append(returnLocations, *returnLoc) @@ -1635,6 +1622,9 @@ func generateMatchesConfig(route conf_v1.Route, upstreamNamer *upstreamNamer, cr var locations []version2.Location var returnLocations []version2.ReturnLocation var splitClients []version2.SplitClient + isVSR := false + vsrName := "" + vsrNamespace := "" scLocalIndex = 0 for i, m := range route.Matches { @@ -1665,7 +1655,7 @@ func generateMatchesConfig(route conf_v1.Route, upstreamNamer *upstreamNamer, cr proxySSLName := generateProxySSLName(upstream.Service, upstreamNamer.namespace) newRetLocIndex := retLocIndex + len(returnLocations) loc, returnLoc := generateLocation(path, upstreamName, upstream, m.Action, cfgParams, errorPages, true, - errPageIndex, proxySSLName, route.Path, locSnippets, enableSnippets, newRetLocIndex) + errPageIndex, proxySSLName, route.Path, locSnippets, enableSnippets, newRetLocIndex, isVSR, vsrName, vsrNamespace) locations = append(locations, loc) if returnLoc != nil { returnLocations = append(returnLocations, *returnLoc) @@ -1700,7 +1690,7 @@ func generateMatchesConfig(route conf_v1.Route, upstreamNamer *upstreamNamer, cr proxySSLName := generateProxySSLName(upstream.Service, upstreamNamer.namespace) newRetLocIndex := retLocIndex + len(returnLocations) loc, returnLoc := generateLocation(path, upstreamName, upstream, route.Action, cfgParams, errorPages, true, - errPageIndex, proxySSLName, route.Path, locSnippets, enableSnippets, newRetLocIndex) + errPageIndex, proxySSLName, route.Path, locSnippets, enableSnippets, newRetLocIndex, isVSR, vsrName, vsrNamespace) locations = append(locations, loc) if returnLoc != nil { returnLocations = append(returnLocations, *returnLoc) diff --git a/internal/configs/virtualserver_test.go b/internal/configs/virtualserver_test.go index 9cd95f32be..f12718f22c 100644 --- a/internal/configs/virtualserver_test.go +++ b/internal/configs/virtualserver_test.go @@ -485,6 +485,7 @@ func TestGenerateVirtualServerConfig(t *testing.T) { Server: version2.Server{ ServerName: "cafe.example.com", StatusZone: "cafe.example.com", + Namespace: "default", ProxyProtocol: true, ServerTokens: "off", SetRealIPFrom: []string{"0.0.0.0/0"}, @@ -502,6 +503,7 @@ func TestGenerateVirtualServerConfig(t *testing.T) { HasKeepalive: true, ProxySSLName: "tea-svc.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "tea-svc", }, { Path: "/tea-latest", @@ -512,6 +514,7 @@ func TestGenerateVirtualServerConfig(t *testing.T) { HasKeepalive: true, ProxySSLName: "tea-svc.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "tea-svc", }, // Order changes here because we generate first all the VS Routes and then all the VSR Subroutes (separated for loops) { @@ -531,6 +534,7 @@ func TestGenerateVirtualServerConfig(t *testing.T) { }, ProxySSLName: "coffee-svc.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "coffee-svc", }, { Path: "/coffee", @@ -541,6 +545,10 @@ func TestGenerateVirtualServerConfig(t *testing.T) { HasKeepalive: true, ProxySSLName: "coffee-svc.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "coffee-svc", + IsVSR: true, + VSRName: "coffee", + VSRNamespace: "default", }, { Path: "/subtea", @@ -551,6 +559,10 @@ func TestGenerateVirtualServerConfig(t *testing.T) { HasKeepalive: true, ProxySSLName: "sub-tea-svc.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "sub-tea-svc", + IsVSR: true, + VSRName: "subtea", + VSRNamespace: "default", }, { @@ -570,6 +582,10 @@ func TestGenerateVirtualServerConfig(t *testing.T) { }, ProxySSLName: "coffee-svc.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "coffee-svc", + IsVSR: true, + VSRName: "subcoffee", + VSRNamespace: "default", }, { Path: "/coffee-errorpage-subroute-defined", @@ -588,6 +604,10 @@ func TestGenerateVirtualServerConfig(t *testing.T) { }, ProxySSLName: "coffee-svc.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "coffee-svc", + IsVSR: true, + VSRName: "subcoffee", + VSRNamespace: "default", }, }, ErrorPageLocations: []version2.ErrorPageLocation{ @@ -696,6 +716,7 @@ func TestGenerateVirtualServerConfigWithSpiffeCerts(t *testing.T) { Server: version2.Server{ ServerName: "cafe.example.com", StatusZone: "cafe.example.com", + Namespace: "default", ProxyProtocol: true, ServerTokens: "off", SetRealIPFrom: []string{"0.0.0.0/0"}, @@ -713,6 +734,7 @@ func TestGenerateVirtualServerConfigWithSpiffeCerts(t *testing.T) { HasKeepalive: true, ProxySSLName: "tea-svc.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "tea-svc", }, }, }, @@ -942,6 +964,7 @@ func TestGenerateVirtualServerConfigForVirtualServerWithSplits(t *testing.T) { Server: version2.Server{ ServerName: "cafe.example.com", StatusZone: "cafe.example.com", + Namespace: "default", InternalRedirectLocations: []version2.InternalRedirectLocation{ { Path: "/tea", @@ -962,6 +985,7 @@ func TestGenerateVirtualServerConfigForVirtualServerWithSplits(t *testing.T) { Internal: true, ProxySSLName: "tea-svc-v1.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "tea-svc-v1", }, { Path: "/internal_location_splits_0_split_1", @@ -972,6 +996,7 @@ func TestGenerateVirtualServerConfigForVirtualServerWithSplits(t *testing.T) { Internal: true, ProxySSLName: "tea-svc-v2.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "tea-svc-v2", }, { Path: "/internal_location_splits_1_split_0", @@ -982,6 +1007,7 @@ func TestGenerateVirtualServerConfigForVirtualServerWithSplits(t *testing.T) { Internal: true, ProxySSLName: "coffee-svc-v1.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "coffee-svc-v1", }, { Path: "/internal_location_splits_1_split_1", @@ -992,6 +1018,7 @@ func TestGenerateVirtualServerConfigForVirtualServerWithSplits(t *testing.T) { Internal: true, ProxySSLName: "coffee-svc-v2.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "coffee-svc-v2", }, }, }, @@ -1252,6 +1279,7 @@ func TestGenerateVirtualServerConfigForVirtualServerWithMatches(t *testing.T) { Server: version2.Server{ ServerName: "cafe.example.com", StatusZone: "cafe.example.com", + Namespace: "default", InternalRedirectLocations: []version2.InternalRedirectLocation{ { Path: "/tea", @@ -1272,6 +1300,7 @@ func TestGenerateVirtualServerConfigForVirtualServerWithMatches(t *testing.T) { Internal: true, ProxySSLName: "tea-svc-v2.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "tea-svc-v2", }, { Path: "/internal_location_matches_0_default", @@ -1282,6 +1311,7 @@ func TestGenerateVirtualServerConfigForVirtualServerWithMatches(t *testing.T) { Internal: true, ProxySSLName: "tea-svc-v1.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "tea-svc-v1", }, { Path: "/internal_location_matches_1_match_0", @@ -1292,6 +1322,7 @@ func TestGenerateVirtualServerConfigForVirtualServerWithMatches(t *testing.T) { Internal: true, ProxySSLName: "coffee-svc-v2.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "coffee-svc-v2", }, { Path: "/internal_location_matches_1_default", @@ -1302,6 +1333,7 @@ func TestGenerateVirtualServerConfigForVirtualServerWithMatches(t *testing.T) { Internal: true, ProxySSLName: "coffee-svc-v1.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "coffee-svc-v1", }, }, }, @@ -1562,6 +1594,7 @@ func TestGenerateVirtualServerConfigForVirtualServerWithReturns(t *testing.T) { Server: version2.Server{ ServerName: "example.com", StatusZone: "example.com", + Namespace: "default", InternalRedirectLocations: []version2.InternalRedirectLocation{ { Path: "/splits-with-return", @@ -2839,12 +2872,7 @@ func TestGenerateUpstreamWithKeepalive(t *testing.T) { vsc := newVirtualServerConfigurator(test.cfgParams, false, false, &StaticConfigParams{}) result := vsc.generateUpstream(nil, name, test.upstream, false, endpoints) if !reflect.DeepEqual(result, test.expected) { - t.Errorf( - "generateUpstream() returned %v but expected %v for the case of %v", - result, - test.expected, - test.msg, - ) + t.Errorf("generateUpstream() returned %v but expected %v for the case of %v", result, test.expected, test.msg) } if len(vsc.warnings) != 0 { @@ -2919,14 +2947,7 @@ func TestGenerateProxyPass(t *testing.T) { for _, test := range tests { result := generateProxyPass(test.tlsEnabled, test.upstreamName, test.internal, nil) if result != test.expected { - t.Errorf( - "generateProxyPass(%v, %v, %v) returned %v but expected %v", - test.tlsEnabled, - test.upstreamName, - test.internal, - result, - test.expected, - ) + t.Errorf("generateProxyPass(%v, %v, %v) returned %v but expected %v", test.tlsEnabled, test.upstreamName, test.internal, result, test.expected) } } } @@ -2953,12 +2974,7 @@ func TestGenerateProxyPassProtocol(t *testing.T) { for _, test := range tests { result := generateProxyPassProtocol(test.upstream.TLS.Enable) if result != test.expected { - t.Errorf( - "generateProxyPassProtocol(%v) returned %v but expected %v", - test.upstream.TLS.Enable, - result, - test.expected, - ) + t.Errorf("generateProxyPassProtocol(%v) returned %v but expected %v", test.upstream.TLS.Enable, result, test.expected) } } } @@ -3081,23 +3097,15 @@ func TestGenerateLocationForProxying(t *testing.T) { ProxyNextUpstreamTimeout: "0s", ProxyNextUpstreamTries: 0, ProxyPassRequestHeaders: true, + ServiceName: "", + IsVSR: false, + VSRName: "", + VSRNamespace: "", } - result := generateLocationForProxying( - path, - upstreamName, - conf_v1.Upstream{}, - &cfgParams, - nil, - false, - 0, - "", - nil, - "", - vsLocSnippets, - ) + result := generateLocationForProxying(path, upstreamName, conf_v1.Upstream{}, &cfgParams, nil, false, 0, "", nil, "", vsLocSnippets, false, "", "") if !reflect.DeepEqual(result, expected) { - t.Errorf("generateLocationForProxying() returned \n%v but expected \n%v", result, expected) + t.Errorf("generateLocationForProxying() returned \n%+v but expected \n%+v", result, expected) } } @@ -3335,12 +3343,7 @@ func TestGenerateSSLConfig(t *testing.T) { for _, test := range tests { result := generateSSLConfig(test.inputTLS, test.inputTLSPemFileName, test.inputCfgParams) if !reflect.DeepEqual(result, test.expected) { - t.Errorf( - "generateSSLConfig() returned %v but expected %v for the case of %s", - result, - test.expected, - test.msg, - ) + t.Errorf("generateSSLConfig() returned %v but expected %v for the case of %s", result, test.expected, test.msg) } } } @@ -3404,12 +3407,7 @@ func TestGenerateRedirectConfig(t *testing.T) { for _, test := range tests { result := generateTLSRedirectConfig(test.inputTLS) if !reflect.DeepEqual(result, test.expected) { - t.Errorf( - "generateTLSRedirectConfig() returned %v but expected %v for the case of %s", - result, - test.expected, - test.msg, - ) + t.Errorf("generateTLSRedirectConfig() returned %v but expected %v for the case of %s", result, test.expected, test.msg) } } } @@ -3788,6 +3786,7 @@ func TestGenerateSplits(t *testing.T) { ProxySSLName: "coffee-v1.default.svc", ProxyPassRequestHeaders: true, Snippets: []string{locSnippet}, + ServiceName: "coffee-v1", }, { Path: "/internal_location_splits_1_split_1", @@ -3812,6 +3811,7 @@ func TestGenerateSplits(t *testing.T) { ProxySSLName: "coffee-v2.default.svc", ProxyPassRequestHeaders: true, Snippets: []string{locSnippet}, + ServiceName: "coffee-v2", }, { Path: "/internal_location_splits_1_split_2", @@ -3919,6 +3919,7 @@ func TestGenerateDefaultSplitsConfig(t *testing.T) { Internal: true, ProxySSLName: "coffee-v1.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "coffee-v1", }, { Path: "/internal_location_splits_1_split_1", @@ -3929,6 +3930,7 @@ func TestGenerateDefaultSplitsConfig(t *testing.T) { Internal: true, ProxySSLName: "coffee-v2.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "coffee-v2", }, }, InternalRedirectLocation: version2.InternalRedirectLocation{ @@ -4218,6 +4220,7 @@ func TestGenerateMatchesConfig(t *testing.T) { }, ProxySSLName: "coffee-v1.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "coffee-v1", }, { Path: "/internal_location_splits_2_split_0", @@ -4241,6 +4244,7 @@ func TestGenerateMatchesConfig(t *testing.T) { }, ProxySSLName: "coffee-v1.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "coffee-v1", }, { Path: "/internal_location_splits_2_split_1", @@ -4264,6 +4268,7 @@ func TestGenerateMatchesConfig(t *testing.T) { }, ProxySSLName: "coffee-v2.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "coffee-v2", }, { Path: "/internal_location_matches_1_default", @@ -4287,6 +4292,7 @@ func TestGenerateMatchesConfig(t *testing.T) { }, ProxySSLName: "tea.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "tea", }, }, InternalRedirectLocation: version2.InternalRedirectLocation{ @@ -4515,6 +4521,7 @@ func TestGenerateMatchesConfigWithMultipleSplits(t *testing.T) { ProxyInterceptErrors: true, ProxySSLName: "coffee-v1.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "coffee-v1", }, { Path: "/internal_location_splits_2_split_1", @@ -4538,6 +4545,7 @@ func TestGenerateMatchesConfigWithMultipleSplits(t *testing.T) { ProxyInterceptErrors: true, ProxySSLName: "coffee-v2.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "coffee-v2", }, { Path: "/internal_location_splits_3_split_0", @@ -4561,6 +4569,7 @@ func TestGenerateMatchesConfigWithMultipleSplits(t *testing.T) { ProxyInterceptErrors: true, ProxySSLName: "coffee-v2.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "coffee-v2", }, { Path: "/internal_location_splits_3_split_1", @@ -4584,6 +4593,7 @@ func TestGenerateMatchesConfigWithMultipleSplits(t *testing.T) { ProxyInterceptErrors: true, ProxySSLName: "coffee-v1.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "coffee-v1", }, { Path: "/internal_location_splits_4_split_0", @@ -4607,6 +4617,7 @@ func TestGenerateMatchesConfigWithMultipleSplits(t *testing.T) { ProxyInterceptErrors: true, ProxySSLName: "coffee-v1.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "coffee-v1", }, { Path: "/internal_location_splits_4_split_1", @@ -4630,6 +4641,7 @@ func TestGenerateMatchesConfigWithMultipleSplits(t *testing.T) { ProxyInterceptErrors: true, ProxySSLName: "coffee-v2.default.svc", ProxyPassRequestHeaders: true, + ServiceName: "coffee-v2", }, }, InternalRedirectLocation: version2.InternalRedirectLocation{ @@ -4764,20 +4776,10 @@ func TestGenerateValueForMatchesRouteMap(t *testing.T) { for _, test := range tests { resultValue, resultIsNegative := generateValueForMatchesRouteMap(test.input) if resultValue != test.expectedValue { - t.Errorf( - "generateValueForMatchesRouteMap(%q) returned %q but expected %q as the value", - test.input, - resultValue, - test.expectedValue, - ) + t.Errorf("generateValueForMatchesRouteMap(%q) returned %q but expected %q as the value", test.input, resultValue, test.expectedValue) } if resultIsNegative != test.expectedIsNegative { - t.Errorf( - "generateValueForMatchesRouteMap(%q) returned %v but expected %v as the isNegative", - test.input, - resultIsNegative, - test.expectedIsNegative, - ) + t.Errorf("generateValueForMatchesRouteMap(%q) returned %v but expected %v as the isNegative", test.input, resultIsNegative, test.expectedIsNegative) } } } @@ -4821,13 +4823,7 @@ func TestGenerateParametersForMatchesRouteMap(t *testing.T) { for _, test := range tests { result := generateParametersForMatchesRouteMap(test.inputMatchedValue, test.inputSuccessfulResult) if !reflect.DeepEqual(result, test.expected) { - t.Errorf( - "generateParametersForMatchesRouteMap(%q, %q) returned %v but expected %v", - test.inputMatchedValue, - test.inputSuccessfulResult, - result, - test.expected, - ) + t.Errorf("generateParametersForMatchesRouteMap(%q, %q) returned %v but expected %v", test.inputMatchedValue, test.inputSuccessfulResult, result, test.expected) } } } @@ -4866,12 +4862,7 @@ func TestGetNameForSourceForMatchesRouteMapFromCondition(t *testing.T) { for _, test := range tests { result := getNameForSourceForMatchesRouteMapFromCondition(test.input) if result != test.expected { - t.Errorf( - "getNameForSourceForMatchesRouteMapFromCondition() returned %q but expected %q for input %v", - result, - test.expected, - test.input, - ) + t.Errorf("getNameForSourceForMatchesRouteMapFromCondition() returned %q but expected %q for input %v", result, test.expected, test.input) } } } @@ -4937,12 +4928,7 @@ func TestUpstreamHasKeepalive(t *testing.T) { for _, test := range tests { result := upstreamHasKeepalive(test.upstream, test.cfgParams) if result != test.expected { - t.Errorf( - "upstreamHasKeepalive() returned %v, but expected %v for the case of %v", - result, - test.expected, - test.msg, - ) + t.Errorf("upstreamHasKeepalive() returned %v, but expected %v for the case of %v", result, test.expected, test.msg) } } } @@ -5095,12 +5081,7 @@ func TestGenerateHealthCheck(t *testing.T) { for _, test := range tests { result := generateHealthCheck(test.upstream, test.upstreamName, baseCfgParams) if !reflect.DeepEqual(result, test.expected) { - t.Errorf( - "generateHealthCheck returned \n%v but expected \n%v \n for case: %v", - result, - test.expected, - test.msg, - ) + t.Errorf("generateHealthCheck returned \n%v but expected \n%v \n for case: %v", result, test.expected, test.msg) } } } @@ -5281,14 +5262,8 @@ func TestGenerateEndpointsForUpstream(t *testing.T) { ) result := vsc.generateEndpointsForUpstream(test.vsEx.VirtualServer, namespace, test.upstream, test.vsEx) if !reflect.DeepEqual(result, test.expected) { - t.Errorf( - "generateEndpointsForUpstream(isPlus=%v, isResolverConfigured=%v) returned %v, but expected %v for case: %v", - test.isPlus, - test.isResolverConfigured, - result, - test.expected, - test.msg, - ) + t.Errorf("generateEndpointsForUpstream(isPlus=%v, isResolverConfigured=%v) returned %v, but expected %v for case: %v", + test.isPlus, test.isResolverConfigured, result, test.expected, test.msg) } if len(vsc.warnings) == 0 && test.warningsExpected { @@ -5327,12 +5302,7 @@ func TestGenerateSlowStartForPlusWithInCompatibleLBMethods(t *testing.T) { result := vsc.generateSlowStartForPlus(&conf_v1.VirtualServer{}, upstream, lbMethod) if !reflect.DeepEqual(result, expected) { - t.Errorf( - "generateSlowStartForPlus returned %v, but expected %v for lbMethod %v", - result, - expected, - lbMethod, - ) + t.Errorf("generateSlowStartForPlus returned %v, but expected %v for lbMethod %v", result, expected, lbMethod) } if len(vsc.warnings) == 0 { @@ -5465,12 +5435,7 @@ func TestGenerateUpstreamWithQueue(t *testing.T) { vsc := newVirtualServerConfigurator(&ConfigParams{}, test.isPlus, false, &StaticConfigParams{}) result := vsc.generateUpstream(nil, test.name, test.upstream, false, []string{}) if !reflect.DeepEqual(result, test.expected) { - t.Errorf( - "generateUpstream() returned %v but expected %v for the case of %v", - result, - test.expected, - test.msg, - ) + t.Errorf("generateUpstream() returned %v but expected %v for the case of %v", result, test.expected, test.msg) } } @@ -5502,12 +5467,7 @@ func TestGenerateQueueForPlus(t *testing.T) { for _, test := range tests { result := generateQueueForPlus(test.upstreamQueue, "60s") if !reflect.DeepEqual(result, test.expected) { - t.Errorf( - "generateQueueForPlus() returned %v but expected %v for the case of %v", - result, - test.expected, - test.msg, - ) + t.Errorf("generateQueueForPlus() returned %v but expected %v for the case of %v", result, test.expected, test.msg) } } @@ -5538,12 +5498,7 @@ func TestGenerateSessionCookie(t *testing.T) { for _, test := range tests { result := generateSessionCookie(test.sc) if !reflect.DeepEqual(result, test.expected) { - t.Errorf( - "generateSessionCookie() returned %v, but expected %v for the case of: %v", - result, - test.expected, - test.msg, - ) + t.Errorf("generateSessionCookie() returned %v, but expected %v for the case of: %v", result, test.expected, test.msg) } } } @@ -5605,13 +5560,7 @@ func TestGenerateErrorPageName(t *testing.T) { for _, test := range tests { result := generateErrorPageName(test.routeIndex, test.index) if result != test.expected { - t.Errorf( - "generateErrorPageName(%v, %v) returned %v but expected %v", - test.routeIndex, - test.index, - result, - test.expected, - ) + t.Errorf("generateErrorPageName(%v, %v) returned %v but expected %v", test.routeIndex, test.index, result, test.expected) } } } @@ -5695,13 +5644,7 @@ func TestGenerateErrorPages(t *testing.T) { for i, test := range tests { result := generateErrorPages(i, test.errorPages) if !reflect.DeepEqual(result, test.expected) { - t.Errorf( - "generateErrorPages(%v, %v) returned %v but expected %v", - test.upstreamName, - test.errorPages, - result, - test.expected, - ) + t.Errorf("generateErrorPages(%v, %v) returned %v but expected %v", test.upstreamName, test.errorPages, result, test.expected) } } } @@ -5772,13 +5715,7 @@ func TestGenerateErrorPageLocations(t *testing.T) { for i, test := range tests { result := generateErrorPageLocations(i, test.errorPages) if !reflect.DeepEqual(result, test.expected) { - t.Errorf( - "generateErrorPageLocations(%v, %v) returned %v but expected %v", - test.upstreamName, - test.errorPages, - result, - test.expected, - ) + t.Errorf("generateErrorPageLocations(%v, %v) returned %v but expected %v", test.upstreamName, test.errorPages, result, test.expected) } } } @@ -5837,13 +5774,7 @@ func TestIsTLSEnabled(t *testing.T) { for _, test := range tests { result := isTLSEnabled(test.upstream, test.spiffeCert) if result != test.expected { - t.Errorf( - "isTLSEnabled(%v, %v) returned %v but expected %v", - test.upstream, - test.spiffeCert, - result, - test.expected, - ) + t.Errorf("isTLSEnabled(%v, %v) returned %v but expected %v", test.upstream, test.spiffeCert, result, test.expected) } } @@ -6053,12 +5984,7 @@ func TestGenerateProxyPassRequestHeaders(t *testing.T) { for _, test := range tests { result := generateProxyPassRequestHeaders(test.proxy) if result != test.expected { - t.Errorf( - "generateProxyPassRequestHeaders(%v) returned %v but expected %v", - test.proxy, - result, - test.expected, - ) + t.Errorf("generateProxyPassRequestHeaders(%v) returned %v but expected %v", test.proxy, result, test.expected) } } }