Closed andygrove closed 5 years ago
Every resource type impls serde::Deserialize
, so you first identify what the apiVersion and kind of the document are, and then use the corresponding type as the deserialization target:
let api_version_key = serde_yaml::Value::String("apiVersion".to_owned());
let kind_key = serde_yaml::Value::String("kind".to_owned());
let file = std::fs::File::open("...")?;
let file: serde_yaml::Sequence = serde_yaml::from_reader(file)?;
for document in file {
if let serde_yaml::Value::Mapping(mapping) = &document {
let api_version = mapping.get(&api_version_key).and_then(serde_yaml::Value::as_str);
let kind = mapping.get(&kind_key).and_then(serde_yaml::Value::as_str);
match (api_version, kind) {
(Some(api_version), Some(kind)) if
api_version == <k8s_openapi::api::core::v1::Pod as k8s_openapi::Resource>::api_version() &&
kind == <k8s_openapi::api::core::v1::Pod as k8s_openapi::Resource>::kind() =>
{
let pod: k8s_openapi::api::core::v1::Pod = serde::Deserialize::deserialize(document)?;
...
},
(Some(api_version), Some(kind)) if
api_version == <k8s_openapi::api::apps::v1::Deployment as k8s_openapi::Resource>::api_version() &&
kind == <k8s_openapi::api::apps::v1::Deployment as k8s_openapi::Resource>::kind() =>
{
let deployment: k8s_openapi::api::apps::v1::Deployment = serde::Deserialize::deserialize(document)?;
...
},
...
}
}
}
A macro will help to reduce the boilerplate of the match arms.
It does require you to have a static mapping of apiVersion + kind to type. Not sure there's a way around that.
But note that kubectl apply -f
/ kubectl create -f
do not parse the template as structured types. They parse them as unstructured types (runtime.Object
, ie the equivalent of serde_yaml::Value
) and POST them directly.
First of all, thanks for creating this crate. It is really great. I am using it in https://github.com/andygrove/ballista and it is working well. However, I have a new requirement now that I don't think there is a solution for.
I would like to be able to parse k8s yaml templates and then do the equivalent of
kubectl apply -f yamlfile
. To implement this, I need the ability to deserialize yaml into the standard API structs. Is there any way to do this using this crate?