diff --git a/docs/virtualserver-and-virtualserverroute.md b/docs/virtualserver-and-virtualserverroute.md index d60628e826..cf7a9dc8f3 100644 --- a/docs/virtualserver-and-virtualserverroute.md +++ b/docs/virtualserver-and-virtualserverroute.md @@ -4,7 +4,7 @@ The VirtualServer and VirtualServerRoute resources are new load balancing config This document is the reference documentation for the resources. To see additional examples of using the resources for specific use cases, go to the [examples-of-custom-resources](../examples-of-custom-resources) folder. -**Feature Status**: The VirtualServer and VirtualServerRoute resources are available as a preview feature: it is suitable for experimenting and testing; however, it must be used with caution in production environments. Additionally, while the feature is in preview, we might introduce some backward-incompatible changes to the resources specification in the next releases. +**Feature Status**: The VirtualServer and VirtualServerRoute resources are available as a preview feature: it is suitable for experimenting and testing; however, it must be used with caution in production environments. Additionally, while the feature is in preview, we might introduce some backward-incompatible changes to the resources specification in the next releases. ## Contents - [VirtualServer and VirtualServerRoute Resources](#VirtualServer-and-VirtualServerRoute-Resources) @@ -25,7 +25,7 @@ This document is the reference documentation for the resources. To see additiona - [Validation](#Validation) - [Customization via ConfigMap](#Customization-via-ConfigMap) -## Prerequisites +## Prerequisites The VirtualServer and VirtualServerRoute resources are disabled by default. Make sure to follow Step 1.4 of the [installation](installation.md) doc during the installation process to enable the resources. @@ -124,7 +124,7 @@ VirtualServerRoute: apiVersion: k8s.nginx.org/v1alpha1 kind: VirtualServerRoute metadata: - name: coffee + name: coffee namespace: coffee-ns spec: host: cafe.example.com @@ -132,7 +132,7 @@ spec: - name: latte service: latte-svc port: 80 - - name: espresso + - name: espresso service: espresso-svc port: 80 subroutes: @@ -179,7 +179,10 @@ port: 80 lb-method: round_robin fail-timeout: 10s max-fails: 1 -``` +connect-timeout: 30s +read-timeout: 30s +send-timeout: 30s +``` | Field | Description | Type | Required | | ----- | ----------- | ---- | -------- | @@ -189,6 +192,9 @@ max-fails: 1 | `lb-method` | The load [balancing method](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/#choosing-a-load-balancing-method). To use the round-robin method, specify `round_robin`. The default is specified in the `lb-method` ConfigMap key. | `string` | No | | `fail-timeout` | The time during which the specified number of unsuccessful attempts to communicate with an upstream server should happen to consider the server unavailable. See the [fail_timeout](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#fail_timeout) parameter of the server directive. The default is set in the `fail-timeout` ConfigMap key. | `string` | No | | `max-fails` | The number of unsuccessful attempts to communicate with an upstream server that should happen in the duration set by the `fail-timeout` to consider the server unavailable. See the [max_fails](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#max_fails) parameter of the server directive. The default is set in the `max-fails` ConfgMap key. | `int` | No | +`connect-timeout` | The timeout for establishing a connection with an upstream server. See the [proxy_connect_timeout](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_connect_timeout) directive. The default is specified in the `proxy-connect-timeout` ConfigMap key. | `string` | No +`read-timeout` | The timeout for reading a response from an upstream server. See the [proxy_read_timeout](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_read_timeout) directive. The default is specified in the `proxy-read-timeout` ConfigMap key. | `string` | No +`send-timeout` | The timeout for transmitting a request to an upstream server. See the [proxy_send_timeout](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_send_timeout) directive. The default is `60s`. | `string` | No ### Split @@ -210,12 +216,12 @@ splits: ### Rules -The rules defines a set of content-based routing rules in a route or subroute. +The rules defines a set of content-based routing rules in a route or subroute. In the example below, NGINX routes requests with the path `/coffee` to different upstreams based on the value of the cookie `user`: * `user=john` -> `coffee-future` * `user=bob` -> `coffee-deprecated` -* If the cookie is not set or not equal to either `john` or `bob`, NGINX routes to `coffee-stable` +* If the cookie is not set or not equal to either `john` or `bob`, NGINX routes to `coffee-stable` ```yaml path: /coffee @@ -233,8 +239,8 @@ rules: ``` In the next example, NGINX routes requests based on the value of the built-in [`$request_method` variable](http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_method), which represents the HTTP method of a request: -* all POST requests -> `coffee-post` -* all non-POST requests -> `coffee` +* all POST requests -> `coffee-post` +* all non-POST requests -> `coffee` ```yaml path: /coffee @@ -242,7 +248,7 @@ rules: conditions: - variable: $request_method matches: - - values: + - values: - POST upstream: coffee-post defaultUpstream: coffee @@ -311,9 +317,9 @@ In the kubectl get and similar commands, you can also use the short name `vs` in Working with VirtualServerRoute resources is analogous. In the kubectl commands, use `virtualserverroute` or the short name `vsr`. -### Validation +### Validation -The Ingress Controller validates VirtualServer and VirtualServerRoute resources. If a resource is invalid, the Ingress Controller will reject it. +The Ingress Controller validates VirtualServer and VirtualServerRoute resources. If a resource is invalid, the Ingress Controller will reject it. You can check if the Ingress Controller successfully applied the configuration for a VirtualServer. For our example `cafe` VirtualServer, we can run: ``` diff --git a/internal/configs/config_params.go b/internal/configs/config_params.go index fa3fda4198..d4ce98a373 100644 --- a/internal/configs/config_params.go +++ b/internal/configs/config_params.go @@ -8,6 +8,7 @@ type ConfigParams struct { ServerTokens string ProxyConnectTimeout string ProxyReadTimeout string + ProxySendTimeout string ClientMaxBodySize string HTTP2 bool RedirectToHTTPS bool @@ -91,6 +92,7 @@ func NewDefaultConfigParams() *ConfigParams { ServerTokens: "on", ProxyConnectTimeout: "60s", ProxyReadTimeout: "60s", + ProxySendTimeout: "60s", ClientMaxBodySize: "1m", SSLRedirect: true, MainServerNamesHashMaxSize: "512", diff --git a/internal/configs/version2/config.go b/internal/configs/version2/config.go index a477abe6b8..5ff90ad681 100644 --- a/internal/configs/version2/config.go +++ b/internal/configs/version2/config.go @@ -53,6 +53,7 @@ type Location struct { Snippets []string ProxyConnectTimeout string ProxyReadTimeout string + ProxySendTimeout string ClientMaxBodySize string ProxyMaxTempFileSize string ProxyBuffering bool diff --git a/internal/configs/version2/nginx-plus.virtualserver.tmpl b/internal/configs/version2/nginx-plus.virtualserver.tmpl index 56a9deef52..96cd05f75f 100644 --- a/internal/configs/version2/nginx-plus.virtualserver.tmpl +++ b/internal/configs/version2/nginx-plus.virtualserver.tmpl @@ -35,7 +35,7 @@ server { listen 80{{ if $s.ProxyProtocol }} proxy_protocol{{ end }}; server_name {{ $s.ServerName }}; - + {{ with $ssl := $s.SSL }} listen 443 ssl{{ if $ssl.HTTP2 }} http2{{ end }}{{ if $s.ProxyProtocol }} proxy_protocol{{ end }}; @@ -45,11 +45,11 @@ server { {{ if $ssl.Ciphers }} ssl_ciphers {{ $ssl.Ciphers }}; {{ end }} - + {{ if $ssl.RedirectToHTTPS }} if ($scheme = http) { return 301 https://$host$request_uri; - } + } {{ end }} {{ end }} @@ -90,6 +90,7 @@ server { proxy_connect_timeout {{ $l.ProxyConnectTimeout }}; proxy_read_timeout {{ $l.ProxyReadTimeout }}; + proxy_send_timeout {{ $l.ProxySendTimeout }}; client_max_body_size {{ $l.ClientMaxBodySize }}; {{ if $l.ProxyMaxTempFileSize }} diff --git a/internal/configs/version2/nginx.virtualserver.tmpl b/internal/configs/version2/nginx.virtualserver.tmpl index 456f41a4d1..96cd05f75f 100644 --- a/internal/configs/version2/nginx.virtualserver.tmpl +++ b/internal/configs/version2/nginx.virtualserver.tmpl @@ -90,6 +90,7 @@ server { proxy_connect_timeout {{ $l.ProxyConnectTimeout }}; proxy_read_timeout {{ $l.ProxyReadTimeout }}; + proxy_send_timeout {{ $l.ProxySendTimeout }}; client_max_body_size {{ $l.ClientMaxBodySize }}; {{ if $l.ProxyMaxTempFileSize }} @@ -116,7 +117,7 @@ server { proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Port $server_port; proxy_set_header X-Forwarded-Proto $scheme; - + proxy_pass {{ $l.ProxyPass }}; } {{ end }} diff --git a/internal/configs/version2/templates_test.go b/internal/configs/version2/templates_test.go index 256a11ddb2..9117baccf0 100644 --- a/internal/configs/version2/templates_test.go +++ b/internal/configs/version2/templates_test.go @@ -117,6 +117,7 @@ var virtualServerCfg = VirtualServerConfig{ Snippets: []string{"# location snippet"}, ProxyConnectTimeout: "30s", ProxyReadTimeout: "31s", + ProxySendTimeout: "32s", ClientMaxBodySize: "1m", ProxyBuffering: true, ProxyBuffers: "8 4k", @@ -128,6 +129,7 @@ var virtualServerCfg = VirtualServerConfig{ Path: "@loc0", ProxyConnectTimeout: "30s", ProxyReadTimeout: "31s", + ProxySendTimeout: "32s", ClientMaxBodySize: "1m", ProxyPass: "http://coffee-v1", }, @@ -135,6 +137,7 @@ var virtualServerCfg = VirtualServerConfig{ Path: "@loc1", ProxyConnectTimeout: "30s", ProxyReadTimeout: "31s", + ProxySendTimeout: "32s", ClientMaxBodySize: "1m", ProxyPass: "http://coffee-v2", }, @@ -142,6 +145,7 @@ var virtualServerCfg = VirtualServerConfig{ Path: "@match_loc_0", ProxyConnectTimeout: "30s", ProxyReadTimeout: "31s", + ProxySendTimeout: "32s", ClientMaxBodySize: "1m", ProxyPass: "http://coffee-v2", }, @@ -149,6 +153,7 @@ var virtualServerCfg = VirtualServerConfig{ Path: "@match_loc_default", ProxyConnectTimeout: "30s", ProxyReadTimeout: "31s", + ProxySendTimeout: "32s", ClientMaxBodySize: "1m", ProxyPass: "http://coffee-v1", }, diff --git a/internal/configs/virtualserver.go b/internal/configs/virtualserver.go index 0b44832e6c..1209958850 100644 --- a/internal/configs/virtualserver.go +++ b/internal/configs/virtualserver.go @@ -84,6 +84,10 @@ func (namer *variableNamer) GetNameForVariableForRulesRouteMainMap(rulesIndex in func generateVirtualServerConfig(virtualServerEx *VirtualServerEx, tlsPemFileName string, baseCfgParams *ConfigParams, isPlus bool) version2.VirtualServerConfig { ssl := generateSSLConfig(virtualServerEx.VirtualServer.Spec.TLS, tlsPemFileName, baseCfgParams) + // crUpstreams maps an UpstreamName to its conf_v1alpha1.Upstream as they are generated + // necessary for generateLocation to know what Upstream each Location references + crUpstreams := make(map[string]conf_v1alpha1.Upstream) + virtualServerUpstreamNamer := newUpstreamNamerForVirtualServer(virtualServerEx.VirtualServer) var upstreams []version2.Upstream @@ -94,6 +98,7 @@ func generateVirtualServerConfig(virtualServerEx *VirtualServerEx, tlsPemFileNam endpointsKey := GenerateEndpointsKey(virtualServerEx.VirtualServer.Namespace, u.Service, u.Port) ups := generateUpstream(upstreamName, u, virtualServerEx.Endpoints[endpointsKey], isPlus, baseCfgParams) upstreams = append(upstreams, ups) + crUpstreams[upstreamName] = u } // generate upstreams for each VirtualServerRoute for _, vsr := range virtualServerEx.VirtualServerRoutes { @@ -103,6 +108,7 @@ func generateVirtualServerConfig(virtualServerEx *VirtualServerEx, tlsPemFileNam endpointsKey := GenerateEndpointsKey(vsr.Namespace, u.Service, u.Port) ups := generateUpstream(upstreamName, u, virtualServerEx.Endpoints[endpointsKey], isPlus, baseCfgParams) upstreams = append(upstreams, ups) + crUpstreams[upstreamName] = u } } @@ -123,13 +129,13 @@ func generateVirtualServerConfig(virtualServerEx *VirtualServerEx, tlsPemFileNam } if len(r.Splits) > 0 { - splitCfg := generateSplitRouteConfig(r, virtualServerUpstreamNamer, variableNamer, len(splitClients), baseCfgParams) + splitCfg := generateSplitRouteConfig(r, virtualServerUpstreamNamer, crUpstreams, variableNamer, len(splitClients), baseCfgParams) splitClients = append(splitClients, splitCfg.SplitClient) locations = append(locations, splitCfg.Locations...) internalRedirectLocations = append(internalRedirectLocations, splitCfg.InternalRedirectLocation) } else if r.Rules != nil { - rulesRouteCfg := generateRulesRouteConfig(r, virtualServerUpstreamNamer, variableNamer, rulesRoutes, baseCfgParams) + rulesRouteCfg := generateRulesRouteConfig(r, virtualServerUpstreamNamer, crUpstreams, variableNamer, rulesRoutes, baseCfgParams) maps = append(maps, rulesRouteCfg.Maps...) locations = append(locations, rulesRouteCfg.Locations...) @@ -138,9 +144,11 @@ func generateVirtualServerConfig(virtualServerEx *VirtualServerEx, tlsPemFileNam rulesRoutes++ } else { upstreamName := virtualServerUpstreamNamer.GetNameForUpstream(r.Upstream) - loc := generateLocation(r.Path, upstreamName, baseCfgParams) + upstream := crUpstreams[upstreamName] + loc := generateLocation(r.Path, upstreamName, upstream, baseCfgParams) locations = append(locations, loc) } + } // generate config for subroutes of each VirtualServerRoute @@ -148,13 +156,13 @@ func generateVirtualServerConfig(virtualServerEx *VirtualServerEx, tlsPemFileNam upstreamNamer := newUpstreamNamerForVirtualServerRoute(virtualServerEx.VirtualServer, vsr) for _, r := range vsr.Spec.Subroutes { if len(r.Splits) > 0 { - splitCfg := generateSplitRouteConfig(r, upstreamNamer, variableNamer, len(splitClients), baseCfgParams) + splitCfg := generateSplitRouteConfig(r, upstreamNamer, crUpstreams, variableNamer, len(splitClients), baseCfgParams) splitClients = append(splitClients, splitCfg.SplitClient) locations = append(locations, splitCfg.Locations...) internalRedirectLocations = append(internalRedirectLocations, splitCfg.InternalRedirectLocation) } else if r.Rules != nil { - rulesRouteCfg := generateRulesRouteConfig(r, upstreamNamer, variableNamer, rulesRoutes, baseCfgParams) + rulesRouteCfg := generateRulesRouteConfig(r, upstreamNamer, crUpstreams, variableNamer, rulesRoutes, baseCfgParams) maps = append(maps, rulesRouteCfg.Maps...) locations = append(locations, rulesRouteCfg.Locations...) @@ -163,7 +171,8 @@ func generateVirtualServerConfig(virtualServerEx *VirtualServerEx, tlsPemFileNam rulesRoutes++ } else { upstreamName := upstreamNamer.GetNameForUpstream(r.Upstream) - loc := generateLocation(r.Path, upstreamName, baseCfgParams) + upstream := crUpstreams[upstreamName] + loc := generateLocation(r.Path, upstreamName, upstream, baseCfgParams) locations = append(locations, loc) } } @@ -216,13 +225,11 @@ func generateUpstream(upstreamName string, upstream conf_v1alpha1.Upstream, endp upsServers = append(upsServers, s) } - ups := version2.Upstream{ + return version2.Upstream{ Name: upstreamName, Servers: upsServers, LBMethod: generateLBMethod(upstream.LBMethod, cfgParams.LBMethod), } - - return ups } func generateLBMethod(method string, defaultMethod string) string { @@ -231,7 +238,6 @@ func generateLBMethod(method string, defaultMethod string) string { } else if method == "round_robin" { return "" } - return method } @@ -249,12 +255,13 @@ func generatePositiveIntFromPointer(n *int, defaultN int) int { return *n } -func generateLocation(path string, upstreamName string, cfgParams *ConfigParams) version2.Location { - loc := version2.Location{ +func generateLocation(path string, upstreamName string, upstream conf_v1alpha1.Upstream, cfgParams *ConfigParams) version2.Location { + return version2.Location{ Path: path, Snippets: cfgParams.LocationSnippets, - ProxyConnectTimeout: cfgParams.ProxyConnectTimeout, - ProxyReadTimeout: cfgParams.ProxyReadTimeout, + ProxyConnectTimeout: generateTime(upstream.ProxyConnectTimeout, cfgParams.ProxyConnectTimeout), + ProxyReadTimeout: generateTime(upstream.ProxyReadTimeout, cfgParams.ProxyReadTimeout), + ProxySendTimeout: generateTime(upstream.ProxySendTimeout, cfgParams.ProxySendTimeout), ClientMaxBodySize: cfgParams.ClientMaxBodySize, ProxyMaxTempFileSize: cfgParams.ProxyMaxTempFileSize, ProxyBuffering: cfgParams.ProxyBuffering, @@ -262,7 +269,6 @@ func generateLocation(path string, upstreamName string, cfgParams *ConfigParams) ProxyBufferSize: cfgParams.ProxyBufferSize, ProxyPass: fmt.Sprintf("http://%v", upstreamName), } - return loc } type splitRouteCfg struct { @@ -271,7 +277,7 @@ type splitRouteCfg struct { InternalRedirectLocation version2.InternalRedirectLocation } -func generateSplitRouteConfig(route conf_v1alpha1.Route, upstreamNamer *upstreamNamer, variableNamer *variableNamer, index int, cfgParams *ConfigParams) splitRouteCfg { +func generateSplitRouteConfig(route conf_v1alpha1.Route, upstreamNamer *upstreamNamer, crUpstreams map[string]conf_v1alpha1.Upstream, variableNamer *variableNamer, index int, cfgParams *ConfigParams) splitRouteCfg { splitClientVarName := variableNamer.GetNameForSplitClientVariable(index) // Generate a SplitClient @@ -297,7 +303,8 @@ func generateSplitRouteConfig(route conf_v1alpha1.Route, upstreamNamer *upstream for i, s := range route.Splits { path := fmt.Sprintf("@splits_%d_split_%d", index, i) upstreamName := upstreamNamer.GetNameForUpstream(s.Upstream) - loc := generateLocation(path, upstreamName, cfgParams) + upstream := crUpstreams[upstreamName] + loc := generateLocation(path, upstreamName, upstream, cfgParams) locations = append(locations, loc) } @@ -320,7 +327,8 @@ type rulesRouteCfg struct { InternalRedirectLocation version2.InternalRedirectLocation } -func generateRulesRouteConfig(route conf_v1alpha1.Route, upstreamNamer *upstreamNamer, variableNamer *variableNamer, index int, cfgParams *ConfigParams) rulesRouteCfg { +func generateRulesRouteConfig(route conf_v1alpha1.Route, upstreamNamer *upstreamNamer, crUpstreams map[string]conf_v1alpha1.Upstream, + variableNamer *variableNamer, index int, cfgParams *ConfigParams) rulesRouteCfg { // Generate maps var maps []version2.Map @@ -378,14 +386,16 @@ func generateRulesRouteConfig(route conf_v1alpha1.Route, upstreamNamer *upstream for i, m := range route.Rules.Matches { path := fmt.Sprintf("@rules_%d_match_%d", index, i) upstreamName := upstreamNamer.GetNameForUpstream(m.Upstream) - loc := generateLocation(path, upstreamName, cfgParams) + upstream := crUpstreams[upstreamName] + loc := generateLocation(path, upstreamName, upstream, cfgParams) locations = append(locations, loc) } - // Generate defaultUpsteam location + // Generate defaultUpstream location path := fmt.Sprintf("@rules_%d_default", index) upstreamName := upstreamNamer.GetNameForUpstream(route.Rules.DefaultUpstream) - loc := generateLocation(path, upstreamName, cfgParams) + upstream := crUpstreams[upstreamName] + loc := generateLocation(path, upstreamName, upstream, cfgParams) locations = append(locations, loc) // Generate an InternalRedirectLocation to the location defined by the main map variable @@ -521,11 +531,9 @@ func createUpstreamServersForPlus(virtualServerEx *VirtualServerEx) map[string][ } func createUpstreamServersConfig(baseCfgParams *ConfigParams) nginx.ServerConfig { - cfg := nginx.ServerConfig{ + return nginx.ServerConfig{ MaxFails: baseCfgParams.MaxFails, FailTimeout: baseCfgParams.FailTimeout, SlowStart: baseCfgParams.SlowStart, } - - return cfg } diff --git a/internal/configs/virtualserver_test.go b/internal/configs/virtualserver_test.go index c26b192dca..cdb3e10ef1 100644 --- a/internal/configs/virtualserver_test.go +++ b/internal/configs/virtualserver_test.go @@ -4,10 +4,8 @@ import ( "reflect" "testing" - "github.com/nginxinc/kubernetes-ingress/internal/nginx" - "github.com/nginxinc/kubernetes-ingress/internal/configs/version2" - + "github.com/nginxinc/kubernetes-ingress/internal/nginx" conf_v1alpha1 "github.com/nginxinc/kubernetes-ingress/pkg/apis/configuration/v1alpha1" meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -803,6 +801,7 @@ func TestGenerateLocation(t *testing.T) { cfgParams := ConfigParams{ ProxyConnectTimeout: "30s", ProxyReadTimeout: "31s", + ProxySendTimeout: "32s", ClientMaxBodySize: "1m", ProxyMaxTempFileSize: "1024m", ProxyBuffering: true, @@ -818,6 +817,7 @@ func TestGenerateLocation(t *testing.T) { Snippets: []string{"# location snippet"}, ProxyConnectTimeout: "30s", ProxyReadTimeout: "31s", + ProxySendTimeout: "32s", ClientMaxBodySize: "1m", ProxyMaxTempFileSize: "1024m", ProxyBuffering: true, @@ -826,7 +826,7 @@ func TestGenerateLocation(t *testing.T) { ProxyPass: "http://test-upstream", } - result := generateLocation(path, upstreamName, &cfgParams) + result := generateLocation(path, upstreamName, conf_v1alpha1.Upstream{}, &cfgParams) if !reflect.DeepEqual(result, expected) { t.Errorf("generateLocation() returned %v but expected %v", result, expected) } @@ -1074,7 +1074,7 @@ func TestGenerateSplitRouteConfig(t *testing.T) { cfgParams := ConfigParams{} - result := generateSplitRouteConfig(route, upstreamNamer, variableNamer, index, &cfgParams) + result := generateSplitRouteConfig(route, upstreamNamer, map[string]conf_v1alpha1.Upstream{}, variableNamer, index, &cfgParams) if !reflect.DeepEqual(result, expected) { t.Errorf("generateSplitRouteConfig() returned %v but expected %v", result, expected) } @@ -1286,7 +1286,7 @@ func TestGenerateRulesRouteConfig(t *testing.T) { cfgParams := ConfigParams{} - result := generateRulesRouteConfig(route, upstreamNamer, variableNamer, index, &cfgParams) + result := generateRulesRouteConfig(route, upstreamNamer, map[string]conf_v1alpha1.Upstream{}, variableNamer, index, &cfgParams) if !reflect.DeepEqual(result, expected) { t.Errorf("generateRulesRouteConfig() returned \n%v but expected \n%v", result, expected) } diff --git a/pkg/apis/configuration/v1alpha1/types.go b/pkg/apis/configuration/v1alpha1/types.go index 2f9ba0820c..87c40a95f2 100644 --- a/pkg/apis/configuration/v1alpha1/types.go +++ b/pkg/apis/configuration/v1alpha1/types.go @@ -25,12 +25,15 @@ type VirtualServerSpec struct { // Upstream defines an upstream. type Upstream struct { - Name string `json:"name"` - Service string `json:"service"` - Port uint16 `json:"port"` - LBMethod string `json:"lb-method"` - FailTimeout string `json:"fail-timeout"` - MaxFails *int `json:"max-fails"` + Name string `json:"name"` + Service string `json:"service"` + Port uint16 `json:"port"` + LBMethod string `json:"lb-method"` + FailTimeout string `json:"fail-timeout"` + MaxFails *int `json:"max-fails"` + ProxyConnectTimeout string `json:"connect-timeout"` + ProxyReadTimeout string `json:"read-timeout"` + ProxySendTimeout string `json:"send-timeout"` } // Route defines a route. diff --git a/pkg/apis/configuration/validation/validation.go b/pkg/apis/configuration/validation/validation.go index ba40f5792b..51dc6daefe 100644 --- a/pkg/apis/configuration/validation/validation.go +++ b/pkg/apis/configuration/validation/validation.go @@ -138,6 +138,11 @@ func validateUpstreams(upstreams []v1alpha1.Upstream, fieldPath *field.Path, isP } allErrs = append(allErrs, validateServiceName(u.Service, idxPath.Child("service"))...) + + allErrs = append(allErrs, validateTime(u.ProxyConnectTimeout, idxPath.Child("connect-timeout"))...) + allErrs = append(allErrs, validateTime(u.ProxyReadTimeout, idxPath.Child("read-timeout"))...) + allErrs = append(allErrs, validateTime(u.ProxySendTimeout, idxPath.Child("send-timeout"))...) + allErrs = append(allErrs, validateUpstreamLBMethod(u.LBMethod, idxPath.Child("lb-method"), isPlus)...) allErrs = append(allErrs, validateTime(u.FailTimeout, idxPath.Child("fail-timeout"))...) allErrs = append(allErrs, validatePositiveIntOrZero(u.MaxFails, idxPath.Child("max-fails"))...)