sigs.k8s.io/gateway-api@v1.0.0/geps/gep-2257.md (about) 1 # GEP-2257: Gateway API Duration Format 2 3 * Issue: [#2257](https://github.com/kubernetes-sigs/gateway-api/issues/2257) 4 * Status: Experimental 5 6 ## TL;DR 7 8 As we extend the Gateway API to have more functionality, we need a standard 9 way to represent duration values. The first instance is the [HTTPRoute 10 Timeouts GEP][GEP-1742]; doubtless others will arise. 11 12 [GEP-1742]:/geps/gep-1742 13 14 ## Gateway API Duration Format 15 16 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", 17 "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be 18 interpreted as described in [RFC 8174]. 19 20 [RFC 8174]:https://datatracker.ietf.org/doc/html/rfc8174 21 22 A _Gateway API Duration_ or _GEP-2257 Duration_ is a string value that: 23 24 - MUST match the regular expression `^([0-9]{1,5}(h|m|s|ms)){1,4}$` and 25 - MUST be interpreted as specified by [Golang's `time.ParseDuration`][gotime]. 26 27 Since both of these conditions MUST be true, the effect is that GEP-2257 28 Durations are a subset of what `time.ParseDuration` supports: 29 30 - A GEP-2257 Duration MUST be one to four _components_, each of which consists 31 of an integer _value_ followed immediately by a _unit_. For example, `1h`, 32 `5m`, `1h5m`, and `1h30m30s500ms` are all valid GEP-2257 Durations. 33 34 - For each component, the value MUST be one to five decimal digits. Floating 35 point is not allowed. Leading zeroes do not mean octal; the value MUST 36 always be interpreted as a decimal integer. For example, `1h`, `60m`, `01h`, 37 and `00060m` are all equivalent GEP-2257 Durations. 38 39 - For each component, the unit MUST be one of `h` (hour), `m` (minute), `s` 40 (second), or `ms` (millisecond). No units larger than hours or smaller than 41 milliseconds are supported. 42 43 - The total duration expressed by a GEP-2257 Duration string is the sum of 44 each of its components. For example, `1h30m` would be a 90-minute duration, 45 and `1s500ms` would be a 1.5-second duration. 46 47 - There is no requirement that all units must be used. A GEP-2257 Duration of 48 `1h500ms` is supported (although probably not terribly useful). 49 50 - Units MAY be repeated, although users SHOULD NOT rely on this support since 51 this GEP is Experimental, and future revisions may remove support for 52 repeated units. If units are repeated, the total duration remains the sum of 53 all components: a GEP-2257 duration of `1h2h20m10m` is a duration of 3 hours 54 30 minutes. 55 56 - Since the value and the unit are both required within a component, `0` is 57 not a valid GEP-2257 duration string (though `0s` is). Likewise the empty 58 string is not a valid GEP-2257 duration. 59 60 - Users SHOULD represent the zero duration as `0s`, although they MAY use any 61 of `0h`, `0m`, etc. Implementations formatting a GEP-2257 Duration for 62 output MUST render the zero duration as `0s`. 63 64 - The “standard” form of a GEP-2257 Duration uses descending, nonrepeating 65 units, using the largest unit possible for each component (so `1h` rather 66 than `60m` or `30m1800s`, and `1h30m` rather than either `90m` or `30m1h`). 67 Users SHOULD use this standard form when writing GEP-2257 Durations. 68 Implementations formatting GEP-2257 Durations MUST render them using this 69 standard form. 70 71 - **Note**: Implementations of Kubernetes APIs MUST NOT modify user input. 72 For example, implementations MUST NOT normalize `30m1800s` to `1h` in a 73 CRD `spec`. This "standard form" requirement is limited to instances 74 where an implementation needs to format a GEP-2257 Duration value for 75 output. 76 77 A GEP-2257 Duration parser can be easily implemented by doing a regex-match 78 check before calling a parser equivalent to Go's `time.ParseDuration`. Such 79 parsers are readily available in (at least) [Go itself][gotime], [Rust's 80 `kube_core` crate from `kube-rs`][kube-core], and [Python's 81 `durationpy`][durationpy] package. We expect that these three languages cover 82 the vast majority of the Kubernetes ecosystem. 83 84 [gotime]:https://pkg.go.dev/time#ParseDuration 85 [kube-core]:https://docs.rs/kube-core/latest/kube_core/duration/struct.Duration.html 86 [durationpy]:https://github.com/icholy/durationpy 87 88 ## Alternatives 89 90 We considered three main alternatives: 91 92 - Raw Golang `time.ParseDuration` format. This is very widely used in the Go 93 ecosystem -- however, it is a very open-ended specification and, in 94 particular, its support for floating-point values and negative durations 95 makes it difficult to validate. 96 97 - Golang `strfmt.ParseDuration` as used in the APIServer's OpenAPI validation 98 code. It turns out that `strfmt.ParseDuration` is a superset of 99 `time.ParseDuration`, so all the problems in validation are still present. 100 Additionally, `strfmt.ParseDuration` supports day and week units, requiring 101 discussion of leap seconds. 102 103 - ISO8601/RFC3339 durations. These are considerably less user-friendly than 104 our proposal: `PT0.5S` is simply not as immediately clear as "500ms". 105 106 There is (a lot) more discussion in [PR 2155]. 107 108 [PR 2155]:https://github.com/kubernetes-sigs/gateway-api/pull/2155 109 110 ## Graduation Criteria 111 112 To graduate GEP-2257 to Standard channel, we need to meet the following 113 criteria: 114 115 - Publish a set of test vectors for the GEP-2257 duration format. 116 117 - Have Go, Rust, and Python implementations of the parser, with a test suite 118 covering all the test vectors. 119 120 - Have a custom CEL validator for GEP-2257 Duration fields. 121 122 - Have support for GEP-2257 Durations in standard Kubernetes libraries.