Skip to content

Commit

Permalink
Change validation in Duration type in CRDs and NGF (#2525)
Browse files Browse the repository at this point in the history
Problem: Duration type in crds was limited to being in seconds or milliseconds. This is inconvenient with the keepalive_time nginx directive which defaults to 1 hour.

Solution: Relax the validation to allow for minutes and hours.

Testing: Tested that crds can use minutes and hours for their duration fields.
  • Loading branch information
bjee19 authored Sep 11, 2024
1 parent 605bef5 commit 8fb93bb
Show file tree
Hide file tree
Showing 8 changed files with 37 additions and 25 deletions.
7 changes: 4 additions & 3 deletions apis/v1alpha1/shared_types.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package v1alpha1

// Duration is a string value representing a duration in time.
// Duration can be specified in milliseconds (ms) or seconds (s) A value without a suffix is seconds.
// Examples: 120s, 50ms.
// Duration can be specified in milliseconds (ms), seconds (s), minutes (m), hours (h).
// A value without a suffix is seconds.
// Examples: 120s, 50ms, 5m, 1h.
//
// +kubebuilder:validation:Pattern=`^\d{1,4}(ms|s)?$`
// +kubebuilder:validation:Pattern=`^[0-9]{1,4}(ms|s|m|h)?$`
type Duration string

// SpanAttribute is a key value pair to be added to a tracing span.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ spec:
If a client does not transmit anything within this time, the request is terminated with the
408 (Request Time-out) error.
Default: https://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_timeout.
pattern: ^\d{1,4}(ms|s)?$
pattern: ^[0-9]{1,4}(ms|s|m|h)?$
type: string
type: object
keepAlive:
Expand All @@ -91,21 +91,21 @@ spec:
Time defines the maximum time during which requests can be processed through one keep-alive connection.
After this time is reached, the connection is closed following the subsequent request processing.
Default: https://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_time.
pattern: ^\d{1,4}(ms|s)?$
pattern: ^[0-9]{1,4}(ms|s|m|h)?$
type: string
timeout:
description: Timeout defines the keep-alive timeouts for clients.
properties:
header:
description: 'Header sets the timeout in the "Keep-Alive:
timeout=time" response header field.'
pattern: ^\d{1,4}(ms|s)?$
pattern: ^[0-9]{1,4}(ms|s|m|h)?$
type: string
server:
description: |-
Server sets the timeout during which a keep-alive client connection will stay open on the server side.
Setting this value to 0 disables keep-alive client connections.
pattern: ^\d{1,4}(ms|s)?$
pattern: ^[0-9]{1,4}(ms|s|m|h)?$
type: string
type: object
x-kubernetes-validations:
Expand Down
2 changes: 1 addition & 1 deletion config/crd/bases/gateway.nginx.org_nginxproxies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ spec:
description: |-
Interval is the maximum interval between two exports.
Default: https://nginx.org/en/docs/ngx_otel_module.html#otel_exporter
pattern: ^\d{1,4}(ms|s)?$
pattern: ^[0-9]{1,4}(ms|s|m|h)?$
type: string
required:
- endpoint
Expand Down
10 changes: 5 additions & 5 deletions deploy/crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ spec:
If a client does not transmit anything within this time, the request is terminated with the
408 (Request Time-out) error.
Default: https://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_timeout.
pattern: ^\d{1,4}(ms|s)?$
pattern: ^[0-9]{1,4}(ms|s|m|h)?$
type: string
type: object
keepAlive:
Expand All @@ -90,21 +90,21 @@ spec:
Time defines the maximum time during which requests can be processed through one keep-alive connection.
After this time is reached, the connection is closed following the subsequent request processing.
Default: https://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_time.
pattern: ^\d{1,4}(ms|s)?$
pattern: ^[0-9]{1,4}(ms|s|m|h)?$
type: string
timeout:
description: Timeout defines the keep-alive timeouts for clients.
properties:
header:
description: 'Header sets the timeout in the "Keep-Alive:
timeout=time" response header field.'
pattern: ^\d{1,4}(ms|s)?$
pattern: ^[0-9]{1,4}(ms|s|m|h)?$
type: string
server:
description: |-
Server sets the timeout during which a keep-alive client connection will stay open on the server side.
Setting this value to 0 disables keep-alive client connections.
pattern: ^\d{1,4}(ms|s)?$
pattern: ^[0-9]{1,4}(ms|s|m|h)?$
type: string
type: object
x-kubernetes-validations:
Expand Down Expand Up @@ -741,7 +741,7 @@ spec:
description: |-
Interval is the maximum interval between two exports.
Default: https://nginx.org/en/docs/ngx_otel_module.html#otel_exporter
pattern: ^\d{1,4}(ms|s)?$
pattern: ^[0-9]{1,4}(ms|s|m|h)?$
type: string
required:
- endpoint
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,19 @@ func TestValidator_Validate(t *testing.T) {
return p
}),
expConditions: []conditions.Condition{
staticConds.NewPolicyInvalid("[spec.body.timeout: Invalid value: \"invalid\": \\d{1,4}(ms|s)? " +
"(e.g. '5ms', or '10s', regex used for validation is 'must contain a number followed by 'ms' or 's''), " +
"spec.keepAlive.time: Invalid value: \"invalid\": \\d{1,4}(ms|s)? (e.g. '5ms', or '10s', regex used for " +
"validation is 'must contain a number followed by 'ms' or 's''), spec.keepAlive.timeout.server: Invalid value: " +
"\"invalid\": \\d{1,4}(ms|s)? (e.g. '5ms', or '10s', regex used for validation is 'must contain a number " +
"followed by 'ms' or 's''), spec.keepAlive.timeout.header: Invalid value: \"invalid\": \\d{1,4}(ms|s)? " +
"(e.g. '5ms', or '10s', regex used for validation is 'must contain a number followed by 'ms' or 's'')]"),
staticConds.NewPolicyInvalid(
"[spec.body.timeout: Invalid value: \"invalid\": ^[0-9]{1,4}(ms|s|m|h)? " +
"(e.g. '5ms', or '10s', or '500m', or '1000h', regex used for validation is " +
"'must contain an, at most, four digit number followed by 'ms', 's', 'm', or 'h''), " +
"spec.keepAlive.time: Invalid value: \"invalid\": ^[0-9]{1,4}(ms|s|m|h)? " +
"(e.g. '5ms', or '10s', or '500m', or '1000h', regex used for validation is " +
"'must contain an, at most, four digit number followed by 'ms', 's', 'm', or 'h''), " +
"spec.keepAlive.timeout.server: Invalid value: \"invalid\": ^[0-9]{1,4}(ms|s|m|h)? " +
"(e.g. '5ms', or '10s', or '500m', or '1000h', regex used for validation is " +
"'must contain an, at most, four digit number followed by 'ms', 's', 'm', or 'h''), " +
"spec.keepAlive.timeout.header: Invalid value: \"invalid\": ^[0-9]{1,4}(ms|s|m|h)? " +
"(e.g. '5ms', or '10s', or '500m', or '1000h', regex used for validation is " +
"'must contain an, at most, four digit number followed by 'ms', 's', 'm', or 'h'')]"),
},
},
{
Expand Down
6 changes: 4 additions & 2 deletions internal/mode/static/nginx/config/validation/generic.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ func (GenericValidator) ValidateServiceName(name string) error {
}

const (
durationStringFmt = `\d{1,4}(ms|s)?`
durationStringErrMsg = "must contain a number followed by 'ms' or 's'"
durationStringFmt = `^[0-9]{1,4}(ms|s|m|h)?`
durationStringErrMsg = "must contain an, at most, four digit number followed by 'ms', 's', 'm', or 'h'"
)

var durationStringFmtRegexp = regexp.MustCompile("^" + durationStringFmt + "$")
Expand All @@ -51,6 +51,8 @@ func (GenericValidator) ValidateNginxDuration(duration string) error {
examples := []string{
"5ms",
"10s",
"500m",
"1000h",
}

return errors.New(k8svalidation.RegexError(durationStringFmt, durationStringErrMsg, examples...))
Expand Down
4 changes: 3 additions & 1 deletion internal/mode/static/nginx/config/validation/generic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,16 @@ func TestValidateNginxDuration(t *testing.T) {
`5ms`,
`10s`,
`123ms`,
`5m`,
`2h`,
)

testInvalidValuesForSimpleValidator(
t,
validator.ValidateNginxDuration,
`test`,
`12345`,
`5m`,
`5k`,
)
}

Expand Down
5 changes: 3 additions & 2 deletions site/content/reference/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -812,8 +812,9 @@ Support: Gateway, HTTPRoute, GRPCRoute.</p>
</p>
<p>
<p>Duration is a string value representing a duration in time.
Duration can be specified in milliseconds (ms) or seconds (s) A value without a suffix is seconds.
Examples: 120s, 50ms.</p>
Duration can be specified in milliseconds (ms), seconds (s), minutes (m), hours (h).
A value without a suffix is seconds.
Examples: 120s, 50ms, 5m, 1h.</p>
</p>
<h3 id="gateway.nginx.org/v1alpha1.IPFamilyType">IPFamilyType
(<code>string</code> alias)</p><a class="headerlink" href="#gateway.nginx.org%2fv1alpha1.IPFamilyType" title="Permanent link">¶</a>
Expand Down

0 comments on commit 8fb93bb

Please sign in to comment.