Skip to content

Commit da44dd0

Browse files
authored
Merge pull request #1780 from Danil-Grigorev/update-schemars-1.0
Update to schemars 1.0
2 parents a4c0e34 + 17426a5 commit da44dd0

File tree

10 files changed

+383
-153
lines changed

10 files changed

+383
-153
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ hyper-timeout = "0.5.1"
6060
hyper-util = "0.1.11"
6161
json-patch = "4"
6262
jsonpath-rust = "0.7.3"
63-
k8s-openapi = { version = "0.25.0", default-features = false }
63+
k8s-openapi = { git = "https://github.com/Arnavion/k8s-openapi.git", rev = "e9a9eaf", default-features = false }
6464
openssl = "0.10.36"
6565
parking_lot = "0.12.0"
6666
pem = "3.0.1"
@@ -69,7 +69,7 @@ proc-macro2 = "1.0.29"
6969
quote = "1.0.10"
7070
rand = "0.9.0"
7171
rustls = { version = "0.23.16", default-features = false }
72-
schemars = "0.8.6"
72+
schemars = "1.0.0"
7373
secrecy = "0.10.2"
7474
serde = "1.0.130"
7575
serde_json = "1.0.68"

examples/crd_derive.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ fn main() {
6262
println!("Status (via HasStatus): {:?}", foo.status());
6363
}
6464

65-
fn conditions(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
65+
fn conditions(_: &mut schemars::generate::SchemaGenerator) -> schemars::Schema {
6666
serde_json::from_value(serde_json::json!({
6767
"type": "array",
6868
"x-kubernetes-list-type": "map",

examples/crd_derive_custom_schema.rs

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1+
use std::borrow::Cow;
2+
13
use kube::CustomResourceExt;
24
use kube_derive::CustomResource;
3-
use schemars::{
4-
schema::{InstanceType, ObjectValidation, Schema, SchemaObject},
5-
JsonSchema,
6-
};
5+
use schemars::{json_schema, JsonSchema};
76
use serde::{Deserialize, Serialize};
87

98
/// CustomResource with manually implemented `JsonSchema`
@@ -20,44 +19,36 @@ pub struct MyBar {
2019
}
2120

2221
impl JsonSchema for Bar {
23-
fn schema_name() -> String {
24-
"Bar".to_string()
22+
fn schema_name() -> Cow<'static, str> {
23+
"Bar".into()
2524
}
2625

27-
fn json_schema(__gen: &mut schemars::gen::SchemaGenerator) -> Schema {
28-
Schema::Object(SchemaObject {
29-
object: Some(Box::new(ObjectValidation {
30-
required: ["spec".to_string()].into(),
31-
properties: [(
32-
"spec".to_string(),
33-
Schema::Object(SchemaObject {
34-
instance_type: Some(InstanceType::Object.into()),
35-
object: Some(Box::new(ObjectValidation {
36-
required: ["bars".to_string()].into(),
37-
properties: [(
38-
"bars".to_string(),
39-
Schema::Object(SchemaObject {
40-
instance_type: Some(InstanceType::Integer.into()),
41-
..SchemaObject::default()
42-
}),
43-
)]
44-
.into(),
45-
..ObjectValidation::default()
46-
})),
47-
..SchemaObject::default()
48-
}),
49-
)]
50-
.into(),
51-
..ObjectValidation::default()
52-
})),
53-
..SchemaObject::default()
26+
fn json_schema(__gen: &mut schemars::generate::SchemaGenerator) -> schemars::Schema {
27+
json_schema!({
28+
"properties": {
29+
"spec": {
30+
"properties": {
31+
"bars": {
32+
"type": "integer"
33+
}
34+
},
35+
"required": [
36+
"bars"
37+
],
38+
"type": "object"
39+
}
40+
},
41+
"required": [
42+
"spec"
43+
],
44+
"title": "Bar"
5445
})
5546
}
5647
}
5748

5849
fn main() {
5950
let crd = Bar::crd();
60-
println!("{}", serde_yaml::to_string(&crd).unwrap());
51+
println!("{}", serde_json::to_string(&crd).unwrap());
6152
}
6253

6354
// Verify CustomResource derivable still

examples/crd_derive_schema.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ impl FooSpec {
120120
}
121121

122122
// https://kubernetes.io/docs/reference/using-api/server-side-apply/#merge-strategy
123-
fn set_listable_schema(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
123+
fn set_listable_schema(_: &mut schemars::generate::SchemaGenerator) -> schemars::Schema {
124124
serde_json::from_value(serde_json::json!({
125125
"type": "array",
126126
"items": {

kube-core/src/cel.rs

Lines changed: 65 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use std::{collections::BTreeMap, str::FromStr};
44

55
use derive_more::From;
6-
#[cfg(feature = "schema")] use schemars::schema::Schema;
6+
#[cfg(feature = "schema")] use schemars::Schema;
77
use serde::{Deserialize, Serialize};
88
use serde_json::Value;
99

@@ -168,10 +168,10 @@ impl FromStr for Reason {
168168
/// on the top level under the "x-kubernetes-validations".
169169
///
170170
/// ```rust
171-
/// use schemars::schema::Schema;
171+
/// use schemars::Schema;
172172
/// use kube::core::{Rule, Reason, Message, validate};
173173
///
174-
/// let mut schema = Schema::Object(Default::default());
174+
/// let mut schema = Schema::default();
175175
/// let rule = Rule{
176176
/// rule: "self.spec.host == self.url.host".into(),
177177
/// message: Some("must be a URL with the host matching spec.host".into()),
@@ -189,21 +189,15 @@ impl FromStr for Reason {
189189
#[cfg_attr(docsrs, doc(cfg(feature = "schema")))]
190190
pub fn validate(s: &mut Schema, rule: impl Into<Rule>) -> Result<(), serde_json::Error> {
191191
let rule: Rule = rule.into();
192-
match s {
193-
Schema::Bool(_) => (),
194-
Schema::Object(schema_object) => {
195-
let rule = serde_json::to_value(rule)?;
196-
schema_object
197-
.extensions
198-
.entry("x-kubernetes-validations".into())
199-
.and_modify(|rules| {
200-
if let Value::Array(rules) = rules {
201-
rules.push(rule.clone());
202-
}
203-
})
204-
.or_insert(serde_json::to_value(&[rule])?);
205-
}
206-
};
192+
let rule = serde_json::to_value(rule)?;
193+
s.ensure_object()
194+
.entry("x-kubernetes-validations")
195+
.and_modify(|rules| {
196+
if let Value::Array(rules) = rules {
197+
rules.push(rule.clone());
198+
}
199+
})
200+
.or_insert(serde_json::to_value(&[rule])?);
207201
Ok(())
208202
}
209203

@@ -219,13 +213,13 @@ pub fn validate(s: &mut Schema, rule: impl Into<Rule>) -> Result<(), serde_json:
219213
/// field: Option<String>,
220214
/// }
221215
///
222-
/// let gen = &mut schemars::gen::SchemaSettings::openapi3().into_generator();
223-
/// let mut schema = MyStruct::json_schema(gen);
216+
/// let generate = &mut schemars::generate::SchemaSettings::openapi3().into_generator();
217+
/// let mut schema = MyStruct::json_schema(generate);
224218
/// let rule = Rule::new("self != oldSelf");
225219
/// validate_property(&mut schema, 0, rule)?;
226220
/// assert_eq!(
227221
/// serde_json::to_string(&schema).unwrap(),
228-
/// r#"{"type":"object","properties":{"field":{"type":"string","nullable":true,"x-kubernetes-validations":[{"rule":"self != oldSelf"}]}}}"#
222+
/// r#"{"type":"object","properties":{"field":{"type":["string","null"],"x-kubernetes-validations":[{"rule":"self != oldSelf"}]}}}"#
229223
/// );
230224
/// # Ok::<(), serde_json::Error>(())
231225
///```
@@ -234,20 +228,22 @@ pub fn validate(s: &mut Schema, rule: impl Into<Rule>) -> Result<(), serde_json:
234228
pub fn validate_property(
235229
s: &mut Schema,
236230
property_index: usize,
237-
rule: impl Into<Rule>,
231+
rule: impl Into<Rule> + Clone,
238232
) -> Result<(), serde_json::Error> {
239-
match s {
240-
Schema::Bool(_) => (),
241-
Schema::Object(schema_object) => {
242-
let obj = schema_object.object();
243-
for (n, (_, schema)) in obj.properties.iter_mut().enumerate() {
244-
if n == property_index {
245-
return validate(schema, rule);
246-
}
233+
let obj = s.ensure_object();
234+
if let Some(properties) = obj
235+
.entry("properties")
236+
.or_insert(serde_json::Value::Object(Default::default()))
237+
.as_object_mut()
238+
{
239+
for (n, (_, schema)) in properties.iter_mut().enumerate() {
240+
if n == property_index {
241+
let mut prop = Schema::try_from(schema.clone())?;
242+
validate(&mut prop, rule.clone())?;
243+
*schema = prop.to_value();
247244
}
248245
}
249-
};
250-
246+
}
251247
Ok(())
252248
}
253249

@@ -267,25 +263,33 @@ pub fn validate_property(
267263
/// a: bool,
268264
/// b: Option<bool>,
269265
/// }
270-
/// let gen = &mut schemars::gen::SchemaSettings::openapi3().into_generator();
271-
/// let mut first = MyStruct::json_schema(gen);
272-
/// let mut second = MySecondStruct::json_schema(gen);
266+
/// let generate = &mut schemars::generate::SchemaSettings::openapi3().into_generator();
267+
/// let mut first = MyStruct::json_schema(generate);
268+
/// let mut second = MySecondStruct::json_schema(generate);
273269
/// merge_properties(&mut first, &mut second);
274270
///
275271
/// assert_eq!(
276272
/// serde_json::to_string(&first).unwrap(),
277-
/// r#"{"type":"object","properties":{"a":{"type":"boolean"},"b":{"type":"boolean","nullable":true}}}"#
273+
/// r#"{"type":"object","properties":{"a":{"type":"boolean"},"b":{"type":["boolean","null"]}}}"#
278274
/// );
279275
/// # Ok::<(), serde_json::Error>(())
280276
#[cfg(feature = "schema")]
281277
#[cfg_attr(docsrs, doc(cfg(feature = "schema")))]
282278
pub fn merge_properties(s: &mut Schema, merge: &mut Schema) {
283-
match s {
284-
schemars::schema::Schema::Bool(_) => (),
285-
schemars::schema::Schema::Object(schema_object) => {
286-
let obj = schema_object.object();
287-
for (k, v) in &merge.clone().into_object().object().properties {
288-
obj.properties.insert(k.clone(), v.clone());
279+
if let Some(properties) = s
280+
.ensure_object()
281+
.entry("properties")
282+
.or_insert(serde_json::Value::Object(Default::default()))
283+
.as_object_mut()
284+
{
285+
if let Some(merge_properties) = merge
286+
.ensure_object()
287+
.entry("properties")
288+
.or_insert(serde_json::Value::Object(Default::default()))
289+
.as_object_mut()
290+
{
291+
for (k, v) in merge_properties {
292+
properties.insert(k.clone(), v.clone());
289293
}
290294
}
291295
}
@@ -366,12 +370,12 @@ impl MergeStrategy {
366370
/// field: Option<String>,
367371
/// }
368372
///
369-
/// let gen = &mut schemars::gen::SchemaSettings::openapi3().into_generator();
370-
/// let mut schema = MyStruct::json_schema(gen);
373+
/// let generate = &mut schemars::generate::SchemaSettings::openapi3().into_generator();
374+
/// let mut schema = MyStruct::json_schema(generate);
371375
/// merge_strategy_property(&mut schema, 0, MapMerge::Atomic)?;
372376
/// assert_eq!(
373377
/// serde_json::to_string(&schema).unwrap(),
374-
/// r#"{"type":"object","properties":{"field":{"type":"string","nullable":true,"x-kubernetes-map-type":"atomic"}}}"#
378+
/// r#"{"type":"object","properties":{"field":{"type":["string","null"],"x-kubernetes-map-type":"atomic"}}}"#
375379
/// );
376380
///
377381
/// # Ok::<(), serde_json::Error>(())
@@ -383,17 +387,18 @@ pub fn merge_strategy_property(
383387
property_index: usize,
384388
strategy: impl Into<MergeStrategy>,
385389
) -> Result<(), serde_json::Error> {
386-
match s {
387-
Schema::Bool(_) => (),
388-
Schema::Object(schema_object) => {
389-
let obj = schema_object.object();
390-
for (n, (_, schema)) in obj.properties.iter_mut().enumerate() {
391-
if n == property_index {
392-
return merge_strategy(schema, strategy.into());
393-
}
390+
if let Some(properties) = s
391+
.ensure_object()
392+
.entry("properties")
393+
.or_insert(serde_json::Value::Object(Default::default()))
394+
.as_object_mut()
395+
{
396+
for (n, (_, schema)) in properties.iter_mut().enumerate() {
397+
if n == property_index {
398+
return merge_strategy(schema, strategy.into());
394399
}
395400
}
396-
};
401+
}
397402

398403
Ok(())
399404
}
@@ -402,10 +407,9 @@ pub fn merge_strategy_property(
402407
/// such as "x-kubernetes-list-type" and "x-kubernetes-list-map-keys".
403408
///
404409
/// ```rust
405-
/// use schemars::schema::Schema;
406410
/// use kube::core::{ListMerge, Reason, Message, merge_strategy};
407411
///
408-
/// let mut schema = Schema::Object(Default::default());
412+
/// let mut schema = serde_json::Value::Object(Default::default());
409413
/// merge_strategy(&mut schema, ListMerge::Map(vec!["key".into(),"another".into()]).into())?;
410414
/// assert_eq!(
411415
/// serde_json::to_string(&schema).unwrap(),
@@ -416,15 +420,11 @@ pub fn merge_strategy_property(
416420
///```
417421
#[cfg(feature = "schema")]
418422
#[cfg_attr(docsrs, doc(cfg(feature = "schema")))]
419-
pub fn merge_strategy(s: &mut Schema, strategy: MergeStrategy) -> Result<(), serde_json::Error> {
420-
match s {
421-
Schema::Bool(_) => (),
422-
Schema::Object(schema_object) => {
423-
for (key, value) in strategy.keys()? {
424-
schema_object.extensions.insert(key, value);
425-
}
423+
pub fn merge_strategy(s: &mut Value, strategy: MergeStrategy) -> Result<(), serde_json::Error> {
424+
for (key, value) in strategy.keys()? {
425+
if let Some(s) = s.as_object_mut() {
426+
s.insert(key, value);
426427
}
427-
};
428-
428+
}
429429
Ok(())
430430
}

kube-core/src/duration.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Kubernetes [`Duration`]s.
22
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
3+
#[cfg(feature = "schema")] use std::borrow::Cow;
34
use std::{cmp::Ordering, fmt, str::FromStr, time};
45

56
/// A Kubernetes duration.
@@ -273,24 +274,23 @@ impl PartialOrd<time::Duration> for Duration {
273274
impl schemars::JsonSchema for Duration {
274275
// see
275276
// https://github.com/kubernetes/apimachinery/blob/756e2227bf3a486098f504af1a0ffb736ad16f4c/pkg/apis/meta/v1/duration.go#L61
276-
fn schema_name() -> String {
277-
"Duration".to_owned()
277+
fn schema_name() -> Cow<'static, str> {
278+
"Duration".into()
278279
}
279280

280-
fn is_referenceable() -> bool {
281-
false
281+
fn inline_schema() -> bool {
282+
true
282283
}
283284

284-
fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
285-
schemars::schema::SchemaObject {
286-
instance_type: Some(schemars::schema::InstanceType::String.into()),
287-
// the format should *not* be "duration", because "duration" means
288-
// the duration is formatted in ISO 8601, as described here:
289-
// https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-02#section-7.3.1
290-
format: None,
291-
..Default::default()
292-
}
293-
.into()
285+
fn json_schema(_: &mut schemars::generate::SchemaGenerator) -> schemars::Schema {
286+
use schemars::json_schema;
287+
288+
// the format should *not* be "duration", because "duration" means
289+
// the duration is formatted in ISO 8601, as described here:
290+
// https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-02#section-7.3.1
291+
json_schema!({
292+
"type": "string",
293+
})
294294
}
295295
}
296296

0 commit comments

Comments
 (0)