Skip to content

Commit

Permalink
Add type meta data for list types (#1380)
Browse files Browse the repository at this point in the history
* Add type meta data for list types

Signed-off-by: Danil Grigorev <[email protected]>

* Add helper methods: list and resource for TypeMeta

Signed-off-by: Danil Grigorev <[email protected]>

---------

Signed-off-by: Danil Grigorev <[email protected]>
Co-authored-by: Eirik A <[email protected]>
  • Loading branch information
Danil-Grigorev and clux authored Jan 3, 2024
1 parent 538c11b commit f2090b8
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 9 deletions.
36 changes: 36 additions & 0 deletions kube-core/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,42 @@ pub struct TypeMeta {
pub kind: String,
}

impl TypeMeta {
/// Construct a new `TypeMeta` for the object list from the given resource.
///
/// ```
/// # use k8s_openapi::api::core::v1::Pod;
/// # use kube_core::TypeMeta;
///
/// let type_meta = TypeMeta::list::<Pod>();
/// assert_eq!(type_meta.kind, "PodList");
/// assert_eq!(type_meta.api_version, "v1");
/// ```
pub fn list<K: Resource<DynamicType = ()>>() -> Self {
TypeMeta {
api_version: K::api_version(&()).into(),
kind: K::kind(&()).to_string() + "List",
}
}

/// Construct a new `TypeMeta` for the object from the given resource.
///
/// ```
/// # use k8s_openapi::api::core::v1::Pod;
/// # use kube_core::TypeMeta;
///
/// let type_meta = TypeMeta::resource::<Pod>();
/// assert_eq!(type_meta.kind, "Pod");
/// assert_eq!(type_meta.api_version, "v1");
/// ```
pub fn resource<K: Resource<DynamicType = ()>>() -> Self {
TypeMeta {
api_version: K::api_version(&()).into(),
kind: K::kind(&()).into(),
}
}
}

/// A generic representation of any object with `ObjectMeta`.
///
/// It allows clients to get access to a particular `ObjectMeta`
Expand Down
66 changes: 57 additions & 9 deletions kube-core/src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ pub struct ObjectList<T>
where
T: Clone,
{
// NB: kind and apiVersion can be set here, but no need for it atm
/// The type fields, always present
#[serde(flatten, default)]
pub types: TypeMeta,

/// ListMeta - only really used for its `resourceVersion`
///
/// See [ListMeta](k8s_openapi::apimachinery::pkg::apis::meta::v1::ListMeta)
Expand Down Expand Up @@ -50,11 +53,13 @@ impl<T: Clone> ObjectList<T> {
/// # Example
///
/// ```
/// use kube::api::{ListMeta, ObjectList};
/// use kube::api::{ListMeta, ObjectList, TypeMeta};
/// use k8s_openapi::api::core::v1::Pod;
///
/// let types: TypeMeta = TypeMeta::list::<Pod>();
/// let metadata: ListMeta = Default::default();
/// let items = vec![1, 2, 3];
/// let objectlist = ObjectList { metadata, items };
/// # let objectlist = ObjectList { types, metadata, items };
///
/// let first = objectlist.iter().next();
/// println!("First element: {:?}", first); // prints "First element: Some(1)"
Expand All @@ -68,11 +73,13 @@ impl<T: Clone> ObjectList<T> {
/// # Example
///
/// ```
/// use kube::api::{ObjectList, ListMeta};
/// use kube::api::{ListMeta, ObjectList, TypeMeta};
/// use k8s_openapi::api::core::v1::Pod;
///
/// let types: TypeMeta = TypeMeta::list::<Pod>();
/// let metadata: ListMeta = Default::default();
/// let items = vec![1, 2, 3];
/// let mut objectlist = ObjectList { metadata, items };
/// # let mut objectlist = ObjectList { types, metadata, items };
///
/// let mut first = objectlist.iter_mut().next();
///
Expand Down Expand Up @@ -300,7 +307,9 @@ pub struct NotUsed {}

#[cfg(test)]
mod test {
use super::{ApiResource, HasSpec, HasStatus, NotUsed, Object, Resource};
use k8s_openapi::apimachinery::pkg::apis::meta::v1::{ObjectMeta, ListMeta};

use super::{ApiResource, HasSpec, HasStatus, NotUsed, Object, Resource, ObjectList, TypeMeta};
use crate::resource::ResourceExt;

#[test]
Expand Down Expand Up @@ -337,14 +346,53 @@ mod test {
assert_eq!(mypod.namespace().unwrap(), "dev");
assert_eq!(mypod.name_unchecked(), "blog");
assert!(mypod.status().is_none());
assert_eq!(mypod.spec().containers[0], ContainerSimple {
image: "blog".into()
});
assert_eq!(
mypod.spec().containers[0],
ContainerSimple { image: "blog".into() }
);

assert_eq!(PodSimple::api_version(&ar), "v1");
assert_eq!(PodSimple::version(&ar), "v1");
assert_eq!(PodSimple::plural(&ar), "pods");
assert_eq!(PodSimple::kind(&ar), "Pod");
assert_eq!(PodSimple::group(&ar), "");
}

#[test]
fn k8s_object_list() {
use k8s_openapi::api::core::v1::Pod;
// by grabbing the ApiResource info from the Resource trait
let ar = ApiResource::erase::<Pod>(&());
assert_eq!(ar.group, "");
assert_eq!(ar.kind, "Pod");
let podlist: ObjectList<Pod> = ObjectList {
types: TypeMeta{
api_version: ar.api_version,
kind: ar.kind + "List",
},
metadata: ListMeta{..Default::default()},
items: vec![Pod {
metadata: ObjectMeta {
name: Some("test".into()),
namespace: Some("dev".into()),
..ObjectMeta::default()
},
spec: None,
status: None,
}],
};

assert_eq!(&podlist.types.kind, "PodList");
assert_eq!(&podlist.types.api_version, "v1");

let mypod = &podlist.items[0];
let meta = mypod.meta();
assert_eq!(&mypod.metadata, meta);
assert_eq!(meta.namespace.as_ref().unwrap(), "dev");
assert_eq!(meta.name.as_ref().unwrap(), "test");
assert_eq!(mypod.namespace().unwrap(), "dev");
assert_eq!(mypod.name_unchecked(), "test");
assert!(mypod.status.is_none());
assert!(mypod.spec.is_none());
}
}
4 changes: 4 additions & 0 deletions kube/src/mock_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ impl ApiServerVerifier {
assert!(!req_uri.contains("continue=")); // first list has no continue

let respdata = json!({
"kind": "HackList",
"apiVersion": "kube.rs/v1",
"metadata": {
"continue": "first",
},
Expand All @@ -111,6 +113,8 @@ impl ApiServerVerifier {
let req_uri = request.uri().to_string();
assert!(req_uri.contains("&continue=first"));
let respdata = json!({
"kind": "HackList",
"apiVersion": "kube.rs/v1",
"metadata": {
"continue": "",
"resourceVersion": "2"
Expand Down

0 comments on commit f2090b8

Please sign in to comment.