Skip to content

Commit 0383874

Browse files
committed
snafufication
1 parent 077fff4 commit 0383874

File tree

3 files changed

+93
-28
lines changed

3 files changed

+93
-28
lines changed

crates/stackable-versioned-macros/src/codegen/flux_converter.rs

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,16 @@ pub(crate) fn generate_kubernetes_conversion(
2626
let src_lower = src_lower.parse::<TokenStream>().expect("The versions always needs to be a valid TokenStream");
2727

2828
quote! { (Self::#src, Self::#dst) => {
29-
let resource: #src_lower::#struct_ident = serde_json::from_value(object_spec)
30-
.expect(&format!("Failed to deserialize {}", stringify!(#enum_ident)));
29+
let resource: #src_lower::#struct_ident = serde_json::from_value(object_spec.clone())
30+
.map_err(|err| ConversionError::DeserializeObjectSpec{source: err, kind: stringify!(#enum_ident).to_string()})?;
3131

3232
#(
3333
let resource: #version_chain_string::#struct_ident = resource.into();
3434
)*
3535

3636
converted.push(
37-
serde_json::to_value(resource).expect(&format!("Failed to serialize {}", stringify!(#enum_ident)))
37+
serde_json::to_value(resource)
38+
.map_err(|err| ConversionError::SerializeObjectSpec{source: err, kind: stringify!(#enum_ident).to_string()})?
3839
);
3940
}}
4041
},
@@ -44,38 +45,46 @@ pub(crate) fn generate_kubernetes_conversion(
4445
#[automatically_derived]
4546
impl #enum_ident {
4647
pub fn convert(review: kube::core::conversion::ConversionReview) -> kube::core::conversion::ConversionResponse {
48+
Self::try_convert(review).expect("Self::try_convert failed")
49+
}
50+
51+
fn try_convert(review: kube::core::conversion::ConversionReview) -> Result<kube::core::conversion::ConversionResponse, stackable_versioned::ConversionError> {
52+
// Intentionally not using `snafu::ResultExt` here to keep the number of dependencies minimal
53+
use stackable_versioned::ConversionError;
54+
4755
let request = kube::core::conversion::ConversionRequest::from_review(review)
48-
.unwrap();
49-
let desired_api_version = <Self as std::str::FromStr>::from_str(&request.desired_api_version)
50-
.expect(&format!("invalid desired version for {} resource", stringify!(#enum_ident)));
56+
.map_err(|err| ConversionError::ConvertReviewToRequest{source: err})?;
57+
let desired_object_version = <Self as std::str::FromStr>::from_str(&request.desired_api_version)
58+
.map_err(|err| ConversionError::ParseDesiredResourceVersion{
59+
source: err,
60+
version: request.desired_api_version.to_string()
61+
})?;
5162

5263
let mut converted: Vec<serde_json::Value> = Vec::with_capacity(request.objects.len());
5364
for object in &request.objects {
54-
let object_spec = object
55-
.get("spec")
56-
.expect("The passed object had no spec")
57-
.clone();
58-
let kind = object
59-
.get("kind")
60-
.expect("The objected asked to convert has no kind");
61-
let api_version = object
62-
.get("apiVersion")
63-
.expect("The objected asked to convert has no apiVersion")
64-
.as_str()
65-
.expect("The apiVersion of the objected asked to convert wasn't a String");
66-
67-
assert_eq!(kind, stringify!(#enum_ident));
68-
69-
let current_api_version = <Self as std::str::FromStr>::from_str(api_version)
70-
.expect(&format!("invalid current version for {} resource", stringify!(#enum_ident)));
71-
72-
match (&current_api_version, &desired_api_version) {
65+
let object_spec = object.get("spec").ok_or_else(|| ConversionError::ObjectHasNoSpec{})?;
66+
let object_kind = object.get("kind").ok_or_else(|| ConversionError::ObjectHasNoKind{})?;
67+
let object_kind = object_kind.as_str().ok_or_else(|| ConversionError::ObjectKindNotString{kind: object_kind.clone()})?;
68+
let object_version = object.get("apiVersion").ok_or_else(|| ConversionError::ObjectHasNoApiVersion{})?;
69+
let object_version = object_version.as_str().ok_or_else(|| ConversionError::ObjectApiVersionNotString{api_version: object_version.clone()})?;
70+
71+
if object_kind != stringify!(#enum_ident) {
72+
return Err(ConversionError::WrongObjectKind{expected_kind: stringify!(#enum_ident).to_string(), send_kind: object_kind.to_string()});
73+
}
74+
75+
let current_object_version = <Self as std::str::FromStr>::from_str(object_version)
76+
.map_err(|err| ConversionError::ParseCurrentResourceVersion{
77+
source: err,
78+
version: object_version.to_string()
79+
})?;
80+
81+
match (&current_object_version, &desired_object_version) {
7382
#(#matches),*
7483
}
7584
}
7685

7786
let response = kube::core::conversion::ConversionResponse::for_request(request);
78-
response.success(converted)
87+
Ok(response.success(converted))
7988
}
8089
}
8190
})

crates/stackable-versioned/src/flux_converter/mod.rs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,69 @@
33
//! It converts between different CRD versions by using 1.21 GW of power,
44
//! 142km/h and time travel.
55
6+
use kube::core::conversion::ConvertConversionReviewError;
67
use snafu::Snafu;
78

89
#[cfg(test)]
910
mod tests;
1011

1112
#[derive(Debug, Snafu)]
1213
pub enum ParseResourceVersionError {
13-
#[snafu(display("The resource version \"{version}\" is not known"))]
14+
#[snafu(display("the resource version \"{version}\" is not known"))]
1415
UnknownResourceVersion { version: String },
1516
}
17+
18+
#[derive(Debug, Snafu)]
19+
pub enum ConversionError {
20+
#[snafu(display("failed to convert ConversionReview to ConversionRequest"))]
21+
ConvertReviewToRequest {
22+
source: ConvertConversionReviewError,
23+
},
24+
25+
#[snafu(display("failed to parse current resource version \"{version}\""))]
26+
ParseCurrentResourceVersion {
27+
source: ParseResourceVersionError,
28+
version: String,
29+
},
30+
31+
#[snafu(display("failed to parse desired resource version \"{version}\""))]
32+
ParseDesiredResourceVersion {
33+
source: ParseResourceVersionError,
34+
version: String,
35+
},
36+
37+
#[snafu(display("the object send for conversion has no \"spec\" field"))]
38+
ObjectHasNoSpec {},
39+
40+
#[snafu(display("the object send for conversion has no \"kind\" field"))]
41+
ObjectHasNoKind {},
42+
43+
#[snafu(display("the object send for conversion has no \"apiVersion\" field"))]
44+
ObjectHasNoApiVersion {},
45+
46+
#[snafu(display("the \"kind\" field of the object send for conversion isn't a String"))]
47+
ObjectKindNotString { kind: serde_json::Value },
48+
49+
#[snafu(display("the \"apiVersion\" field of the object send for conversion isn't a String"))]
50+
ObjectApiVersionNotString { api_version: serde_json::Value },
51+
52+
#[snafu(display(
53+
"I was asked to convert the kind \"{expected_kind}\", but I can only convert objects of kind \"{send_kind}\""
54+
))]
55+
WrongObjectKind {
56+
expected_kind: String,
57+
send_kind: String,
58+
},
59+
60+
#[snafu(display("failed to deserialize object of kind \"{kind}\""))]
61+
DeserializeObjectSpec {
62+
source: serde_json::Error,
63+
kind: String,
64+
},
65+
66+
#[snafu(display("failed to serialize object of kind \"{kind}\""))]
67+
SerializeObjectSpec {
68+
source: serde_json::Error,
69+
kind: String,
70+
},
71+
}

crates/stackable-versioned/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub use stackable_versioned_macros::*;
1818
mod flux_converter;
1919

2020
#[cfg(feature = "flux-converter")]
21-
pub use flux_converter::ParseResourceVersionError;
21+
pub use flux_converter::{ConversionError, ParseResourceVersionError};
2222

2323
// Unused for now, might get picked up again in the future.
2424
#[doc(hidden)]

0 commit comments

Comments
 (0)