Skip to main content

KubeSchema

Derive Macro KubeSchema 

Source
#[derive(KubeSchema)]
{
    // Attributes available to this derive:
    #[x_kube]
    #[schemars]
    #[validate]
}
Expand description

Generates a JsonSchema implementation a set of CEL validation rules applied on the CRD.

use kube::KubeSchema;
use kube::CustomResource;
use serde::Deserialize;
use serde::Serialize;
use kube::core::crd::CustomResourceExt;

#[derive(CustomResource, KubeSchema, Serialize, Deserialize, Clone, Debug)]
#[kube(
    group = "kube.rs",
    version = "v1",
    kind = "Struct",
    validation = "self.metadata.name == 'singleton'",
)]
#[x_kube(validation = "self == oldSelf")]
struct MyStruct {
    #[serde(default = "default")]
    #[x_kube(validation = Rule::new("self != ''").message("failure message"))]
    field: String,
}

fn default() -> String {
    "value".into()
}

assert!(serde_json::to_string(&Struct::crd()).unwrap().contains("x-kubernetes-validations"));
assert!(serde_json::to_string(&Struct::crd()).unwrap().contains(r#""rule":"self == oldSelf""#));
assert!(serde_json::to_string(&Struct::crd()).unwrap().contains(r#""rule":"self != ''""#));
assert!(serde_json::to_string(&Struct::crd()).unwrap().contains(r#""message":"failure message""#));
assert!(serde_json::to_string(&Struct::crd()).unwrap().contains(r#""default":"value""#));
assert!(serde_json::to_string(&Struct::crd()).unwrap().contains(r#""rule":"self.metadata.name == 'singleton'""#));

§Client-side CEL validation with #[x_kube(cel)]

Adding cel to #[x_kube(...)] generates a static T::validate_cel(value, old) method that evaluates this type’s CEL rules locally, without an apiserver — handy in unit tests on a struct fragment. value is the serialized form (serde_json::to_value(&instance)); old supplies the previous state for transition rules (rules using oldSelf), or None on creation.

This requires the downstream crate to enable the kube/cel feature, since the generated code references kube::core::cel.

#[derive(KubeSchema, Serialize, Deserialize, Clone, Debug)]
#[x_kube(cel, validation = "self.max >= self.min")]
struct Range {
    min: i32,
    max: i32,
}

let ok = serde_json::json!({"min": 1, "max": 5});
assert!(Range::validate_cel(&ok, None).is_ok());

let bad = serde_json::json!({"min": 5, "max": 1});
assert!(Range::validate_cel(&bad, None).is_err());