Skip to content

Commit

Permalink
Minor fixes to ObjectList (#1398)
Browse files Browse the repository at this point in the history
* fix: ObjectList handle missing apiVersion and kind during deserialization

The `serde` crate has a bug that prevents the proper deserialization of
attributes that are using the `flatten` and `default` directives.
See [1] and [2].

This bug affects the freshly introduced `ObjectList.types` attribute.
It's not possible to deserialize an `ObjectList` that is missing the
`apiVersion` and/or the `kind` values.

This commit introduces a custom deserializer for the `types` attribute
of `ObjectList`.

On top of handling the deserialization case, the custom deserializer
provides better default values compared to the ones of the stock
`TypeMeta`.
The `TypeMeta` struct has empty strings as default values. However, in the
context of `ObjectList`, proper default values should be `v1` and `List`
instead.

[1] serde-rs/serde#1626
[2] serde-rs/serde#1879

Signed-off-by: Flavio Castelli <fcastelli@suse.com>

* ObjectList: derive the `Clone` trait

Ensure `ObjectList` derive the `Clone` trait.

Signed-off-by: Flavio Castelli <fcastelli@suse.com>

* chore: fix rustfmt warning

Signed-off-by: Flavio Castelli <fcastelli@suse.com>

---------

Signed-off-by: Flavio Castelli <fcastelli@suse.com>
  • Loading branch information
flavio authored Jan 26, 2024
1 parent 2ad41b2 commit b700529
Showing 1 changed file with 33 additions and 2 deletions.
35 changes: 33 additions & 2 deletions kube-core/src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ use std::borrow::Cow;
/// and is generally produced from list/watch/delete collection queries on an [`Resource`](super::Resource).
///
/// This is almost equivalent to [`k8s_openapi::List<T>`](k8s_openapi::List), but iterable.
#[derive(Serialize, Deserialize, Debug)]
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ObjectList<T>
where
T: Clone,
{
/// The type fields, always present
#[serde(flatten, default)]
#[serde(flatten, deserialize_with = "deserialize_v1_list_as_default")]
pub types: TypeMeta,

/// ListMeta - only really used for its `resourceVersion`
Expand All @@ -38,6 +38,17 @@ where
pub items: Vec<T>,
}

fn deserialize_v1_list_as_default<'de, D>(deserializer: D) -> Result<TypeMeta, D::Error>
where
D: Deserializer<'de>,
{
let meta = Option::<TypeMeta>::deserialize(deserializer)?;
Ok(meta.unwrap_or(TypeMeta {
api_version: "v1".to_owned(),
kind: "List".to_owned(),
}))
}

fn deserialize_null_as_default<'de, D, T>(deserializer: D) -> Result<T, D::Error>
where
T: Default + Deserialize<'de>,
Expand Down Expand Up @@ -394,4 +405,24 @@ mod test {
assert!(mypod.status.is_none());
assert!(mypod.spec.is_none());
}

#[test]
fn k8s_object_list_default_types() {
use k8s_openapi::api::core::v1::Pod;

let raw_value = serde_json::json!({
"metadata": {
"resourceVersion": ""
},
"items": []
});
let pod_list: ObjectList<Pod> = serde_json::from_value(raw_value).unwrap();
assert_eq!(
TypeMeta {
api_version: "v1".to_owned(),
kind: "List".to_owned(),
},
pod_list.types,
);
}
}

0 comments on commit b700529

Please sign in to comment.