Skip to content

Commit 05f32da

Browse files
committed
POC HTTPRoute Timeouts:
* update HTTPRoute interfaces according to latest proposal in GEP-1742 * include Request and BackendRequest in HTTPRouteTimeouts * add validation for HTTPRouteTimeouts
1 parent b692c69 commit 05f32da

File tree

4 files changed

+142
-0
lines changed

4 files changed

+142
-0
lines changed

apis/v1beta1/httproute_types.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,49 @@ type HTTPRouteRule struct {
244244
// +optional
245245
// +kubebuilder:validation:MaxItems=16
246246
BackendRefs []HTTPBackendRef `json:"backendRefs,omitempty"`
247+
248+
// Timeouts defines the timeouts that can be configured for an HTTP request.
249+
//
250+
// Support: Core
251+
//
252+
// +optional
253+
// <gateway:experimental>
254+
Timeouts *HTTPRouteTimeouts `json:"timeouts,omitempty"`
255+
}
256+
257+
// HTTPRouteTimeouts defines timeouts that can be configured for an HTTPRoute.
258+
// Timeout values are formatted like 1h/1m/1s/1ms as parsed by Golang time.ParseDuration
259+
// and MUST BE >= 1ms.
260+
type HTTPRouteTimeouts struct {
261+
// Request specifies a timeout for responding to client HTTP requests,
262+
// disabled by default.
263+
//
264+
// For example, the following rule will timeout if a client request is taking
265+
// longer than 10 seconds to complete:
266+
//
267+
// ```
268+
// rules:
269+
// - timeouts:
270+
// request: 10s
271+
// backendRefs:
272+
// ...
273+
// ```
274+
//
275+
// Support: Core
276+
//
277+
// +optional
278+
// +kubebuilder:validation:Format=duration
279+
Request *metav1.Duration `json:"request,omitempty"`
280+
281+
// BackendRequest specifies a timeout for an individual request from the gateway
282+
// to a backend service.
283+
// Default is the value of Request timeout.
284+
//
285+
// Support: Extended
286+
//
287+
// +optional
288+
// +kubebuilder:validation:Format=duration
289+
BackendRequest *metav1.Duration `json:"backendRequest,omitempty"`
247290
}
248291

249292
// PathMatchType specifies the semantics of how HTTP paths should be compared.

apis/v1beta1/validation/httproute.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ var (
4040

4141
// All valid path characters per RFC-3986
4242
validPathCharacters = "^(?:[A-Za-z0-9\\/\\-._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$"
43+
44+
// Minimum value of timeout in milliseconds
45+
timeoutMinValue = 1
4346
)
4447

4548
// ValidateHTTPRoute validates HTTPRoute according to the Gateway API specification.
@@ -71,6 +74,10 @@ func ValidateHTTPRouteSpec(spec *gatewayv1b1.HTTPRouteSpec, path *field.Path) fi
7174
errs = append(errs, validateHTTPQueryParamMatches(m.QueryParams, matchPath.Child("queryParams"))...)
7275
}
7376
}
77+
78+
if rule.Timeouts != nil {
79+
errs = append(errs, validateHTTPRouteTimeouts(rule.Timeouts, path.Child("rules").Child("timeouts"))...)
80+
}
7481
}
7582
errs = append(errs, validateHTTPRouteBackendServicePorts(spec.Rules, path.Child("rules"))...)
7683
errs = append(errs, ValidateParentRefs(spec.ParentRefs, path.Child("spec"))...)
@@ -334,6 +341,28 @@ func validateHTTPHeaderModifier(filter gatewayv1b1.HTTPHeaderFilter, path *field
334341
return errs
335342
}
336343

344+
func validateHTTPRouteTimeouts(timeouts *gatewayv1b1.HTTPRouteTimeouts, path *field.Path) field.ErrorList {
345+
var errs field.ErrorList
346+
errorString := fmt.Sprintf("timeout value must be greater than or equal to %d ms", timeoutMinValue)
347+
if timeouts.BackendRequest != nil {
348+
if int(timeouts.BackendRequest.Duration.Milliseconds()) < timeoutMinValue {
349+
errs = append(errs, field.Invalid(path.Child("backendRequest"), timeouts.BackendRequest.Duration, errorString))
350+
}
351+
if timeouts.Request != nil {
352+
if int(timeouts.BackendRequest.Duration.Milliseconds()) > int(timeouts.Request.Duration.Milliseconds()) {
353+
errs = append(errs, field.Invalid(path.Child("backendRequest"), timeouts.BackendRequest.Duration, "backendRequest timeout cannot be longer than request timeout"))
354+
}
355+
}
356+
}
357+
if timeouts.Request != nil {
358+
if int(timeouts.Request.Duration.Milliseconds()) < timeoutMinValue {
359+
errs = append(errs, field.Invalid(path.Child("request"), timeouts.Request.Duration, errorString))
360+
}
361+
}
362+
363+
return errs
364+
}
365+
337366
func hasExactlyOnePrefixMatch(matches []gatewayv1b1.HTTPRouteMatch) bool {
338367
if len(matches) != 1 || matches[0].Path == nil {
339368
return false

apis/v1beta1/zz_generated.deepcopy.go

Lines changed: 30 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml

Lines changed: 40 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)