Skip to content

Commit

Permalink
an example to manually impl JsonSchema for merge strategies
Browse files Browse the repository at this point in the history
an addon, and illustration of the more manual parts of #129
  • Loading branch information
clux committed Jan 25, 2021
1 parent cca8bd3 commit d9c742d
Showing 1 changed file with 49 additions and 1 deletion.
50 changes: 49 additions & 1 deletion examples/crd_derive_schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use anyhow::{anyhow, Result};
use futures::{StreamExt, TryStreamExt};
use k8s_openapi::apiextensions_apiserver::pkg::apis::apiextensions::v1::CustomResourceDefinition;
use kube::{
api::{Api, DeleteParams, ListParams, PostParams, Resource, WatchEvent},
api::{Api, DeleteParams, ListParams, Patch, PatchParams, PostParams, Resource, WatchEvent},
Client, CustomResource,
};
use schemars::JsonSchema;
Expand Down Expand Up @@ -73,6 +73,36 @@ pub struct FooSpec {
// If the resource is created with `kubectl` and if this field was missing, defaulting will happen.
#[serde(default = "default_nullable")]
nullable_with_default: Option<String>,

/// Default listable field
#[serde(default)]
default_listable: Vec<u32>,

// Listable field with specified set merge strategy
#[serde(default)]
set_listable: SetListable,
}
#[derive(Serialize, Deserialize, Debug, Default, PartialEq, Eq, Clone)]
struct SetListable(Vec<u32>);
// https://kubernetes.io/docs/reference/using-api/server-side-apply/#merge-strategy
use schemars::{gen::SchemaGenerator, schema::Schema};
impl JsonSchema for SetListable {
fn schema_name() -> String {
"SetListable".into()
}

fn json_schema(_: &mut SchemaGenerator) -> Schema {
serde_json::from_value(serde_json::json!({
"type": "array",
"items": {
"format": "u32",
"minium": 0,
"type": "integer"
},
"x-kubernetes-list-type": "set"
}))
.unwrap()
}
}

fn default_value() -> String {
Expand Down Expand Up @@ -116,6 +146,9 @@ async fn main() -> Result<()> {
// Defaulting did not happen because `null` was sent.
// Deserialization does not apply the default either.
nullable_with_default: None,
// Listables all default
default_listable: Default::default(),
set_listable: Default::default(),
});

// Set up dynamic resource to test using raw values.
Expand Down Expand Up @@ -145,6 +178,7 @@ async fn main() -> Result<()> {
"spec": {
"non_nullable": "a required field",
// `non_nullable_with_default` field is missing
"set_listable": SetListable(vec![2]), // a value patch later
}
}))?;
let val = client
Expand All @@ -153,6 +187,7 @@ async fn main() -> Result<()> {
println!("{:?}", val["spec"]);
// Defaulting happened for non-nullable field
assert_eq!(val["spec"]["non_nullable_with_default"], default_value());
//assert_eq!(val["spec"]["atomic_listable"], "[2]");

// Missing required field (non-nullable without default) is an error
let data = serde_json::to_vec(&serde_json::json!({
Expand Down Expand Up @@ -180,6 +215,19 @@ async fn main() -> Result<()> {
_ => assert!(false),
}

// Test the manually specified merge strategy
let ssapply = PatchParams::apply("crd_derive_schema_example").force();
let patch = serde_json::json!({
"apiVersion": "clux.dev/v1",
"kind": "Foo",
"spec": {
"set_listable": SetListable(vec![3])
}
});
let pres = foos.patch("baz", &ssapply, &Patch::Apply(patch)).await?;
assert_eq!(pres.spec.set_listable, SetListable(vec![2, 3]));
println!("{:?}", serde_json::to_value(pres.spec));

delete_crd(client.clone()).await?;

Ok(())
Expand Down

0 comments on commit d9c742d

Please sign in to comment.