Skip to content

Commit

Permalink
Implement a method for parsing DynamicObjects
Browse files Browse the repository at this point in the history
Issue: #1029

To avoid manually parsing DynamicObjects into
resources, this commit implements DynamicOjbect::try_parse. The
try_parse method will attempt to parse the DynamicObject into a type
implementing the Resource trait, using serde.

Signed-off-by: Jessie Chatham Spencer <jessie@teainspace.com>
  • Loading branch information
jmintb committed Oct 26, 2022
1 parent da6b5e7 commit 2780f2e
Showing 1 changed file with 47 additions and 1 deletion.
48 changes: 47 additions & 1 deletion kube-core/src/dynamic.rs
@@ -1,14 +1,28 @@
//! Contains types for using resource kinds not known at compile-time.
//!
//! For concrete usage see [examples prefixed with dynamic_](https://github.com/kube-rs/kube/tree/main/examples).

pub use crate::discovery::ApiResource;
use crate::{
metadata::TypeMeta,
resource::{DynamicResourceScope, Resource},
};

use k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta;
use std::borrow::Cow;
use thiserror::Error;

#[derive(Debug, Error)]
#[error("failed to parse this DynamicObject into a Resource")]
/// Failed to parse `DynamicObject` into `Resource`
pub struct ParseDynamicObjectError {
source: serde_json::Error,
}

impl From<serde_json::Error> for ParseDynamicObjectError {
fn from(err: serde_json::Error) -> ParseDynamicObjectError {
ParseDynamicObjectError { source: err }
}
}

/// A dynamic representation of a kubernetes object
///
Expand Down Expand Up @@ -57,6 +71,13 @@ impl DynamicObject {
self.metadata.namespace = Some(ns.into());
self
}

/// Attempt to convert this `DynamicObject` to a `Resource`
pub fn try_parse<K: Resource + for<'a> serde::Deserialize<'a>>(
self,
) -> Result<K, ParseDynamicObjectError> {
Ok(serde_json::from_value(serde_json::to_value(self)?)?)
}
}

impl Resource for DynamicObject {
Expand Down Expand Up @@ -101,6 +122,8 @@ mod test {
request::Request,
resource::Resource,
};
use k8s_openapi::api::core::v1::Pod;

#[test]
fn raw_custom_resource() {
let gvk = GroupVersionKind::gvk("clux.dev", "v1", "Foo");
Expand All @@ -127,4 +150,27 @@ mod test {
let req = Request::new(url).create(&pp, vec![]).unwrap();
assert_eq!(req.uri(), "/api/v1/services?");
}

#[test]
fn can_parse_dynamic_object_into_pod() -> Result<(), serde_json::Error> {
let original_pod: Pod = serde_json::from_value(serde_json::json!({
"apiVersion": "v1",
"kind": "Pod",
"metadata": { "name": "example" },
"spec": {
"containers": [{
"name": "example",
"image": "alpine",
// Do nothing
"command": ["tail", "-f", "/dev/null"],
}],
}
}))?;
let dynamic_pod: DynamicObject = serde_json::from_str(&serde_json::to_string(&original_pod)?)?;
let parsed_pod: Pod = dynamic_pod.try_parse().unwrap();

assert_eq!(parsed_pod, original_pod);

Ok(())
}
}

0 comments on commit 2780f2e

Please sign in to comment.