diff --git a/docs/controllers/schemas.md b/docs/controllers/schemas.md new file mode 100644 index 0000000..afe0207 --- /dev/null +++ b/docs/controllers/schemas.md @@ -0,0 +1,58 @@ +# Schemas + +Schemas are a required part of a [CustomResource], and while normally derived automatically, there are [numerous ways](https://docs.rs/kube/latest/kube/derive.CustomResource.html#optional-kube-attributes) to customize or [override](https://docs.rs/kube/latest/kube/derive.CustomResource.html#kubeschema--mode) aspects of them. + +## Generating +### Deriving +Deriving a schema happens automatically when using `#[derive(CustomResource, JsonSchema)]` on a spec struct. + +The schema is [generated by kube-derive](https://github.com/kube-rs/kube/blob/823f4b8db3852e6bdd271e72c56b8c40d6f962a8/kube-derive/src/custom_resource.rs#L376-L383) using [schemars] and our own [conformance rewriter for structural schemas](https://docs.rs/kube/latest/kube/core/schema/struct.StructuralSchemaRewriter.html). + +The [CustomResourceDefinition] (along with schema(s)) can be extracted through the [CustomResourceExt] trait. + +For an example of what is generated look at [examples/crd_derive_schema](https://github.com/kube-rs/kube/blob/main/examples/crd_derive_schema.rs). + +### Replacing +Completely overriding can be done with `#[kube(schema = "disabled)]` and hooking in a manual schema string on to each `crd.spec.versions[].schema`. An example of this can be found in [examples/crd_derive_no_schema](https://github.com/kube-rs/kube/blob/main/examples/crd_derive_no_schema.rs). + +Doing this allows eliding the `#[derive(JsonSchema)]` instruction, which in some cases is your only choice if you do not own the struct. + +If you would like to do it more programmatically, and you have partial `JsonSchema` coverage, you could fill in the gaps with `#[kube(schema = "manual")]` which avoids having to modify the `CustomResourceDefinition`. See [examples/crd_derive_custom_schema](https://github.com/kube-rs/kube/blob/823f4b8db3852e6bdd271e72c56b8c40d6f962a8/examples/crd_derive_custom_schema.rs#L22-L56). + +### Overriding +Overriding specific parts of a schema can be done using [`#[schemars(schema_with)]`](https://graham.cool/schemars/examples/7-custom_serialization/). Some specific examples: + +- [overriding merge strategy on a vec](https://github.com/kube-rs/kube/blob/823f4b8db3852e6bdd271e72c56b8c40d6f962a8/examples/crd_derive_schema.rs#L85-L102) +- [overriding x-kubernetes properties on a condition](https://github.com/kube-rs/kube/blob/823f4b8db3852e6bdd271e72c56b8c40d6f962a8/examples/crd_derive.rs#L60-L85) + +## Versioning +It is possible to progress between two structs in a versionend manner. + +You can define multiple structs within versioned modules ala https://github.com/kube-rs/kube/blob/main/examples/crd_derive_multi.rs and then use [merge_crds] to combine them. + +See [CustomResource#versioning](https://docs.rs/kube/latest/kube/derive.CustomResource.html#versioning), and upstream docs on [Versions in CustomResourceDefinitions](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definition-versioning/) for more info. + +## Validation +Kubernetes >1.25 supports including [validation rules in the openapi schema](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#validation-rules), and there are a couple of ways to include these. + +See the [Openapi V3 blogpost for more context](https://kubernetes.io/blog/2023/04/24/openapi-v3-field-validation-ga/). + +### Manual Writing +This can be done by following upstream docs, and doing manual [[#overriding]]. + +This way will grant you entry to the [1.25 Common Expression Language feature](https://kubernetes.io/blog/2022/09/23/crd-validation-rules-beta/). Note however, that there are no recommended ways of doing client-side validation with this approach, but there are new [cel parser/interpreter crates](https://crates.io/search?q=cel) that might be useful here. + +### Deriving via Garde +Using [garde] is a nice for the simple case because it allows doing both client-side validation, and server-side validation, with the caveat that it only works on both sides for **basic validation rules** as [schemars can only pick up on some of them](https://graham.cool/schemars/deriving/attributes/#supported-validator-attributes). + +See [CustomResource#schema-validation](https://docs.rs/kube/latest/kube/derive.CustomResource.html#schema-validation). + + +--8<-- "includes/abbreviations.md" +--8<-- "includes/links.md" + + + +[//begin]: # "Autogenerated link references for markdown compatibility" +[#overriding]: schemas "Schemas" +[//end]: # "Autogenerated link references" \ No newline at end of file diff --git a/includes/links.md b/includes/links.md index 378f3dd..72d513c 100644 --- a/includes/links.md +++ b/includes/links.md @@ -11,6 +11,8 @@ [Api]: https://docs.rs/kube/latest/kube/struct.Api.html [Client]: https://docs.rs/kube/latest/kube/struct.Client.html [CustomResource]: https://docs.rs/kube/latest/kube/derive.CustomResource.html +[CustomResourceExt]: https://docs.rs/kube/latest/kube/trait.CustomResourceExt.html +[CustomResourceDefinition]: https://docs.rs/k8s-openapi/latest/k8s_openapi/apiextensions_apiserver/pkg/apis/apiextensions/v1/struct.CustomResourceDefinition.html [Resource]: https://docs.rs/kube/latest/kube/trait.Resource.html [ApiResource]: https://docs.rs/kube/latest/kube/core/struct.ApiResource.html [ListParams]: https://docs.rs/kube/latest/kube/api/struct.ListParams.html @@ -35,6 +37,7 @@ [DefaultBackoff]: https://docs.rs/kube/latest/kube/runtime/watcher/struct.DefaultBackoff.html [discovery]: https://docs.rs/kube/latest/kube/discovery/index.html [recommended_kind]: https://docs.rs/kube/latest/kube/discovery/struct.ApiGroup.html#method.recommended_kind +[merge_crds]: https://docs.rs/kube/latest/kube/core/crd/v1/fn.merge_crds.html [kube]: https://crates.io/crates/kube [kopium]: https://github.com/kube-rs/kopium [controller-rs]: https://github.com/kube-rs/controller-rs @@ -45,6 +48,7 @@ [schemars]: https://graham.cool/schemars/ [serde_json::Value]: https://docs.serde.rs/serde_json/enum.Value.html [json]: https://docs.serde.rs/serde_json/macro.json.html +[garde]: https://docs.rs/garde/latest/garde/ [proc_macro]: https://doc.rust-lang.org/reference/procedural-macros.html [k8s-pb]: https://github.com/kube-rs/k8s-pb [k8s-openapi]: https://crates.io/crates/k8s-openapi diff --git a/mkdocs.yml b/mkdocs.yml index c104384..0ef5695 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -66,6 +66,7 @@ nav: - controllers/application.md - controllers/observability.md - controllers/relations.md + - controllers/schemas.md - controllers/optimization.md - controllers/streams.md - controllers/testing.md