Skip to content

Commit

Permalink
Fix schemas containing both properties and additionalProperties due t…
Browse files Browse the repository at this point in the history
…o serde(flatten)

See also: #844

Signed-off-by: Julius Michaelis <gitter@liftm.de>
  • Loading branch information
jcaesar committed Mar 5, 2022
1 parent 0b5e803 commit b89cc98
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 0 deletions.
14 changes: 14 additions & 0 deletions kube-core/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ use schemars::{

/// schemars [`Visitor`] that rewrites a [`Schema`] to conform to Kubernetes' "structural schema" rules
///
/// The following two transformations are applied
/// * Rewrite enums from `oneOf` to `object`s with multiple variants ([schemars#84](https://github.com/GREsau/schemars/issues/84))
/// * Rewrite `additionalProperties` from `#[serde(flatten)]` to `x-kubernetes-preserve-unknown-fields` ([kube-rs#844](https://github.com/kube-rs/kube-rs/issues/844))
///
/// This is used automatically by `kube::derive`'s `#[derive(CustomResource)]`,
/// but it can also be used manually with [`SchemaSettings::with_visitor`].
///
Expand Down Expand Up @@ -77,5 +81,15 @@ impl Visitor for StructuralSchemaRewriter {
}
}
}
if let Some(object) = &mut schema.object {
if !object.properties.is_empty() {
if object.additional_properties.as_deref() == Some(&Schema::Bool(true)) {
object.additional_properties = None;
schema
.extensions
.insert("x-kubernetes-preserve-unknown-fields".into(), true.into());
}
}
}
}
}
24 changes: 24 additions & 0 deletions kube-derive/tests/crd_schema_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use chrono::{DateTime, NaiveDateTime, Utc};
use kube_derive::CustomResource;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

// See `crd_derive_schema` example for how the schema generated from this struct affects defaulting and validation.
#[derive(CustomResource, Serialize, Deserialize, Debug, PartialEq, Clone, JsonSchema)]
Expand Down Expand Up @@ -48,6 +49,14 @@ fn default_nullable() -> Option<String> {
Some("default_nullable".into())
}

#[derive(CustomResource, Deserialize, Serialize, Clone, Debug, JsonSchema)]
#[kube(group = "clux.dev", version = "v1", kind = "Flattening")]
pub struct FlatteningSpec {
foo: String,
#[serde(flatten)]
arbitrary: HashMap<String, serde_json::Value>,
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, JsonSchema)]
#[serde(rename_all = "camelCase")]
enum ComplexEnum {
Expand Down Expand Up @@ -222,3 +231,18 @@ fn test_crd_schema_matches_expected() {
.unwrap()
);
}

#[test]
fn flattening() {
use kube::core::CustomResourceExt;
let spec = &Flattening::crd().spec.versions[0]
.schema
.clone()
.unwrap()
.open_api_v3_schema
.unwrap()
.properties
.unwrap()["spec"];
assert_eq!(spec.x_kubernetes_preserve_unknown_fields, Some(true));
assert_eq!(spec.additional_properties, None);
}

0 comments on commit b89cc98

Please sign in to comment.