Skip to content

Commit b2e4268

Browse files
committed
Developer documentation for CRD validation
1 parent f0f1a38 commit b2e4268

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<!--
2+
# Copyright 2025 Crunchy Data Solutions, Inc.
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
-->
6+
7+
# Custom Resource Definitions
8+
9+
These directories contain Go types that serve as [DTO]s for communicating with the Kubernetes API.
10+
We use the [controller-gen] tool to produce [CRD]s with schemas that match the Go types.
11+
The CRD schema tells Kubernetes what fields and values are allowed in our API objects and how to handle changes to values.
12+
13+
> [!TIP]
14+
> The CRD schema is *most* of the UX of our API
15+
16+
CRD schemas are modified OpenAPI 3.0 [validation] schemas.
17+
Much of the schema defines what fields, types, and values are *allowed*.
18+
`controller-gen` considers the [Go type] of a field and its [validation markers] for this.
19+
20+
Kubernetes uses its own algorithm to consider and accept changes to API objects: [Server-Side Apply], SSA.
21+
CRD schemas contain non-standard attributes that affect SSA.
22+
`controller-gen` considers the [processing markers] of a field for this.
23+
24+
🤔 Validation is *what* and SSA/processing is *how* 🤔
25+
26+
[controller-gen]: https://book.kubebuilder.io/reference/controller-gen
27+
[CRD]: https://docs.k8s.io/tasks/extend-kubernetes/custom-resources/custom-resource-definitions
28+
[DTO]: https://martinfowler.com/eaaCatalog/dataTransferObject.html
29+
[Go type]: https://go.dev/ref/spec#Types
30+
[Kubernetes API]: https://docs.k8s.io/concepts/overview/kubernetes-api
31+
[processing markers]: https://book.kubebuilder.io/reference/markers/crd-processing
32+
[Server-Side Apply]: https://docs.k8s.io/reference/using-api/server-side-apply
33+
[validation]: https://docs.k8s.io/tasks/extend-kubernetes/custom-resources/custom-resource-definitions#validation
34+
[validation markers]: https://book.kubebuilder.io/reference/markers/crd-validation
35+
36+
37+
# OpenAPI Properties
38+
39+
Kubernetes supports a subset of the OpenAPI schema definition, which is a subset of an old draft of [JSON schema].
40+
41+
Fields can have these properties:
42+
43+
- `enum` is a list of values allowed in the field.
44+
- `required` is a boolean indicating the field must be present in whatever payload.
45+
This does *NOT* indicate anything about the value being `null`, "zero," or "empty."
46+
- `nullable` is a boolean indicating if the value can be `null`.
47+
When this is omitted or `false`, a `null` value is removed from whatever payload or replaced with the field's [default value].
48+
- `type` is one of `integer`, `number`, `string`, `boolean`, `array`, or `object`.
49+
- `format` constrains the `type` a bit further.
50+
It affects how `kubectl` presents the field and how the value turns up in CEL validation.
51+
52+
Numeric fields can have these properties:
53+
54+
- `minimum` and `maximum` are the smallest and largest numbers allowed in the field.
55+
- `exclusiveMinimum` and `exclusiveMaximum` are booleans that indicate if the exact values above are allowed.
56+
That is, `true` here changes min and max from ≥ and ≤ to > and <.
57+
- `multipleOf` is a number. Values in the field must be nicely divisible by this number.
58+
59+
String fields can have these properties:
60+
61+
- `minLength` and `maxLength` are the smallest and largest number of characters allowed in the field.
62+
- `pattern` is a regular expression describing values allowed in the field.
63+
In Kubernetes, this is an [RE2] expression, *NOT* an ECMA expression.
64+
65+
Array fields can have these properties:
66+
67+
- `items` is a schema that describes what values are allowed inside the field.
68+
- `minItems` and `maxItems` are the smallest and largest number of items allowed in the field.
69+
70+
The value of an object field is an unordered set of key/value pairs; a JSON object, a YAML mapping.
71+
Kubernetes supports only two ways to treat the keys of those values: known or unknown.
72+
73+
The `properties` property indicates that the keys are known; these fields can have these properties:
74+
75+
- `properties` is an unordered set of key/value pairs (JSON object, YAML mapping) in which:
76+
- the key is the name of a field allowed in the object
77+
- the value is a schema that describes what values are allowed in that field.
78+
79+
The `additionalProperties` property indicates that the keys are unknown; these fields can have these properties:
80+
81+
- `additionalProperties` is a schema that describes what values are allowed in every... key-value value of the field.
82+
- `minProperties` and `maxProperties` are the smallest and largest number of key-value keys allowed in the field.
83+
84+
> [!TIP]
85+
> `properties` is like a Go struct // `additionalProperties` is like a Go map
86+
87+
[default value]: https://docs.k8s.io/tasks/extend-kubernetes/custom-resources/custom-resource-definitions#defaulting-and-nullable
88+
[JSON schema]: https://json-schema.org/draft-06
89+
[RE2]: https://github.com/google/re2#syntax
90+
91+
92+
# CEL Rules
93+
94+
> [!IMPORTANT]
95+
> When possible, use [OpenAPI properties](#FIXME) rather than CEL rules.
96+
> The former do not affect the CRD [validation budget](#FIXME). <!-- https://imgur.com/CzpJn3j -->
97+

0 commit comments

Comments
 (0)