diff --git a/kube-core/src/schema.rs b/kube-core/src/schema.rs index 4f4306cc0..5cdcd84ab 100644 --- a/kube-core/src/schema.rs +++ b/kube-core/src/schema.rs @@ -63,6 +63,15 @@ impl Visitor for StructuralSchemaRewriter { .insert("x-kubernetes-preserve-unknown-fields".into(), true.into()); } } + + // As of version 1.30 Kubernetes does not support setting `uniqueItems` to `true`, + // so we need to remove this fields. + // Users can still set `x-kubernetes-list-type=set` in case they want the apiserver + // to do validation, but we can't make an assumption about the Set contents here. + // See https://kubernetes.io/docs/reference/using-api/server-side-apply/ for details. + if let Some(array) = &mut schema.array { + array.unique_items = None; + } } } diff --git a/kube-derive/tests/crd_schema_test.rs b/kube-derive/tests/crd_schema_test.rs index d1c9116a7..d3d5afa08 100644 --- a/kube-derive/tests/crd_schema_test.rs +++ b/kube-derive/tests/crd_schema_test.rs @@ -5,7 +5,7 @@ use chrono::{DateTime, NaiveDateTime, TimeZone, Utc}; use kube_derive::CustomResource; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; // 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)] @@ -46,6 +46,8 @@ struct FooSpec { /// This is a untagged enum with a description untagged_enum_person: UntaggedEnumPerson, + + set: HashSet, } fn default_value() -> String { @@ -138,7 +140,8 @@ fn test_serialized_matches_expected() { untagged_enum_person: UntaggedEnumPerson::GenderAndAge(GenderAndAge { age: 42, gender: Gender::Male, - }) + }), + set: HashSet::from(["foo".to_owned()]) })) .unwrap(), serde_json::json!({ @@ -161,7 +164,8 @@ fn test_serialized_matches_expected() { "untaggedEnumPerson": { "age": 42, "gender": "Male" - } + }, + "set": ["foo"] } }) ) @@ -299,11 +303,18 @@ fn test_crd_schema_matches_expected() { } ], "description": "This is a untagged enum with a description" - } + }, + "set": { + "type": "array", + "items": { + "type": "string" + }, + }, }, "required": [ "complexEnum", "nonNullable", + "set", "timestamp", "untaggedEnumPerson" ],