schemars
schemars copied to clipboard
support for k8s "structural" schemas
docs: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#specifying-a-structural-schema
currently, schemars generates schemas that are rejected as non-structural for complex enumerations of the type:
enum MyType {
Variant1(Variant1),
Variant2(Variant2),
...
VariantN(VariantN),
}
where Variant1, Variant2, ..., VariantN are themselves structs. as this is a common pattern to lift enumeration variants into the rust type system, this happens all over the place in idiomatic rust code. moreover, the structs generated by the k8s-openapi crate necessarily produces complex enums of this sort in the process of translating the k8s api types.
there may also be other kinds of structs that produce non-structural schemas and I'll document them here as I find them.
I'm happy to take on implementation of a fix for this issue if I can get some direction on how best to do so. is a crate-level feature a suitable way to toggle how enums are handled? this makes the update to k8s-openapi more straightforward but I notice that most features of this sort are handled as per-type macro arguments, currently.
More concretely, this is because schemars currently serializes enums as:
properties:
enum:
oneOf:
- type: object
- properties:
variantOne:
# properties...
required: [variantOne]
- type: object
properties:
variantTwo:
# properties...
required: [variantTwo]
Kubernetes doesn't allow the structure to depend on which variant is selected, so it instead requires all variants to be declared up-front, with oneOf used to select which variant is active. That would look like this instead:
properties:
enum:
type: object
properties:
variantOne:
# properties...
variantTwo:
# properties...
oneOf:
- required: [variantOne]
- required: [variantTwo]
It shouldn't be too difficult to implement, but AFAIK it doesn't accomodate cases where multiple variants share the same tag (with #[serde(rename)]), or untagged variants (or at least those would both be messier to support...). Thus, I'd propose that this be opt-in in some form, either by adding a #[schemars] attribute, or by a toggle in SchemaSettings.
FWIW I ended up implementing this in kube-rs as a schemars Visitor: https://github.com/kube-rs/kube-rs/pull/779.