-
Notifications
You must be signed in to change notification settings - Fork 635
Developer documentation for CRD validation #4266
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| <!-- | ||
| # Copyright 2025 Crunchy Data Solutions, Inc. | ||
| # | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| --> | ||
|
|
||
| # Custom Resource Definitions | ||
|
|
||
| These directories contain Go types that serve as [DTO]s for communicating with the Kubernetes API. | ||
| We use the [controller-gen] tool to produce [CRD]s with schemas that match the Go types. | ||
| The CRD schema tells Kubernetes what fields and values are allowed in our API objects and how to handle changes to values. | ||
|
|
||
| > [!TIP] | ||
| > The CRD schema is *most* of the UX of our API | ||
|
|
||
| CRD schemas are modified OpenAPI 3.0 [validation] schemas. | ||
| Much of the schema defines what fields, types, and values are *allowed*. | ||
| `controller-gen` considers the [Go type] of a field and its [validation markers] for this. | ||
|
|
||
| Kubernetes uses its own algorithm to consider and accept changes to API objects: [Server-Side Apply], SSA. | ||
| CRD schemas contain non-standard attributes that affect SSA. | ||
| `controller-gen` considers the [processing markers] of a field for this. | ||
|
|
||
| 🤔 Validation is *what* and SSA/processing is *how* 🤔 | ||
|
|
||
| [controller-gen]: https://book.kubebuilder.io/reference/controller-gen | ||
| [CRD]: https://docs.k8s.io/tasks/extend-kubernetes/custom-resources/custom-resource-definitions | ||
| [DTO]: https://martinfowler.com/eaaCatalog/dataTransferObject.html | ||
| [Go type]: https://go.dev/ref/spec#Types | ||
| [Kubernetes API]: https://docs.k8s.io/concepts/overview/kubernetes-api | ||
| [processing markers]: https://book.kubebuilder.io/reference/markers/crd-processing | ||
| [Server-Side Apply]: https://docs.k8s.io/reference/using-api/server-side-apply | ||
| [validation]: https://docs.k8s.io/tasks/extend-kubernetes/custom-resources/custom-resource-definitions#validation | ||
| [validation markers]: https://book.kubebuilder.io/reference/markers/crd-validation | ||
|
|
||
|
|
||
| # OpenAPI Properties | ||
|
|
||
| Kubernetes supports a subset of the OpenAPI schema definition, which is a subset of an old draft of [JSON schema]. | ||
|
|
||
| Fields can have these properties: | ||
|
|
||
| - `enum` is a list of values allowed in the field. | ||
| - `required` is a boolean indicating the field must be present in whatever payload. | ||
| This does *NOT* indicate anything about the value being `null`, "zero," or "empty." | ||
| - `nullable` is a boolean indicating if the value can be `null`. | ||
| When this is omitted or `false`, a `null` value is removed from whatever payload or replaced with the field's [default value]. | ||
| - `type` is one of `integer`, `number`, `string`, `boolean`, `array`, or `object`. | ||
| - `format` constrains the `type` a bit further. | ||
| It affects how `kubectl` presents the field and how the value turns up in CEL validation. | ||
|
|
||
| Numeric fields can have these properties: | ||
|
|
||
| - `minimum` and `maximum` are the smallest and largest numbers allowed in the field. | ||
| - `exclusiveMinimum` and `exclusiveMaximum` are booleans that indicate if the exact values above are allowed. | ||
| That is, `true` here changes min and max from ≥ and ≤ to > and <. | ||
| - `multipleOf` is a number. Values in the field must be nicely divisible by this number. | ||
|
|
||
| String fields can have these properties: | ||
|
|
||
| - `minLength` and `maxLength` are the smallest and largest number of characters allowed in the field. | ||
| - `pattern` is a regular expression describing values allowed in the field. | ||
| In Kubernetes, this is an [RE2] expression, *NOT* an ECMA expression. | ||
|
|
||
| Array fields can have these properties: | ||
|
|
||
| - `items` is a schema that describes what values are allowed inside the field. | ||
| - `minItems` and `maxItems` are the smallest and largest number of items allowed in the field. | ||
|
|
||
| The value of an object field is an unordered set of key/value pairs; a JSON object, a YAML mapping. | ||
| Kubernetes supports only two ways to treat the keys of those values: known or unknown. | ||
|
|
||
| The `properties` property indicates that the keys are known; these fields can have these properties: | ||
|
|
||
| - `properties` is an unordered set of key/value pairs (JSON object, YAML mapping) in which: | ||
| - the key is the name of a field allowed in the object | ||
| - the value is a schema that describes what values are allowed in that field. | ||
|
|
||
| The `additionalProperties` property indicates that the keys are unknown; these fields can have these properties: | ||
|
|
||
| - `additionalProperties` is a schema that describes what values are allowed in every... key-value value of the field. | ||
| - `minProperties` and `maxProperties` are the smallest and largest number of key-value keys allowed in the field. | ||
|
|
||
| > [!TIP] | ||
| > `properties` is like a Go struct // `additionalProperties` is like a Go map | ||
|
|
||
| [default value]: https://docs.k8s.io/tasks/extend-kubernetes/custom-resources/custom-resource-definitions#defaulting-and-nullable | ||
| [JSON schema]: https://json-schema.org/draft-06 | ||
| [RE2]: https://github.com/google/re2#syntax | ||
|
|
||
|
|
||
| # CEL Rules | ||
|
|
||
| > [!IMPORTANT] | ||
| > When possible, use [OpenAPI properties](#FIXME) rather than CEL rules. | ||
| > The former do not affect the CRD [validation budget](#FIXME). <!-- https://imgur.com/CzpJn3j --> | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.