Skip to content

Commit c52ec12

Browse files
committed
Convert errors to correct respondes
1 parent 0383874 commit c52ec12

File tree

2 files changed

+77
-13
lines changed

2 files changed

+77
-13
lines changed

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

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,54 @@ pub(crate) fn generate_kubernetes_conversion(
4545
#[automatically_derived]
4646
impl #enum_ident {
4747
pub fn convert(review: kube::core::conversion::ConversionReview) -> kube::core::conversion::ConversionResponse {
48-
Self::try_convert(review).expect("Self::try_convert failed")
48+
// Intentionally not using `snafu::ResultExt` here to keep the number of dependencies minimal
49+
use kube::core::conversion::{ConversionRequest, ConversionResponse};
50+
use kube::core::response::StatusSummary;
51+
use stackable_versioned::ConversionError;
52+
53+
let request = match ConversionRequest::from_review(review) {
54+
Ok(request) => request,
55+
Err(err) => {
56+
return ConversionResponse::invalid(
57+
kube::client::Status {
58+
status: Some(StatusSummary::Failure),
59+
code: 400,
60+
message: format!("The ConversionReview send did not include any request: {err}"),
61+
reason: "ConversionReview request missing".to_string(),
62+
details: None,
63+
},
64+
);
65+
}
66+
};
67+
68+
let converted = Self::try_convert(&request);
69+
70+
let conversion_response = ConversionResponse::for_request(request);
71+
match converted {
72+
Ok(converted) => {
73+
conversion_response.success(converted)
74+
},
75+
Err(err) => {
76+
let error_message = err.as_human_readable_error_message();
77+
78+
conversion_response.failure(
79+
kube::client::Status {
80+
status: Some(StatusSummary::Success),
81+
code: err.http_return_code(),
82+
message: error_message.clone(),
83+
reason: error_message,
84+
details: None,
85+
},
86+
)
87+
}
88+
}
4989
}
5090

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
91+
fn try_convert(request: &kube::core::conversion::ConversionRequest) -> Result<Vec<serde_json::Value>, stackable_versioned::ConversionError> {
5392
use stackable_versioned::ConversionError;
5493

55-
let request = kube::core::conversion::ConversionRequest::from_review(review)
56-
.map_err(|err| ConversionError::ConvertReviewToRequest{source: err})?;
94+
// FIXME: Check that request.types.{kind,api_version} match the expected values
95+
5796
let desired_object_version = <Self as std::str::FromStr>::from_str(&request.desired_api_version)
5897
.map_err(|err| ConversionError::ParseDesiredResourceVersion{
5998
source: err,
@@ -83,8 +122,7 @@ pub(crate) fn generate_kubernetes_conversion(
83122
}
84123
}
85124

86-
let response = kube::core::conversion::ConversionResponse::for_request(request);
87-
Ok(response.success(converted))
125+
Ok(converted)
88126
}
89127
}
90128
})

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

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
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;
6+
use std::{error::Error, fmt::Write};
7+
78
use snafu::Snafu;
89

910
#[cfg(test)]
@@ -17,11 +18,6 @@ pub enum ParseResourceVersionError {
1718

1819
#[derive(Debug, Snafu)]
1920
pub enum ConversionError {
20-
#[snafu(display("failed to convert ConversionReview to ConversionRequest"))]
21-
ConvertReviewToRequest {
22-
source: ConvertConversionReviewError,
23-
},
24-
2521
#[snafu(display("failed to parse current resource version \"{version}\""))]
2622
ParseCurrentResourceVersion {
2723
source: ParseResourceVersionError,
@@ -69,3 +65,33 @@ pub enum ConversionError {
6965
kind: String,
7066
},
7167
}
68+
69+
impl ConversionError {
70+
pub fn http_return_code(&self) -> u16 {
71+
match &self {
72+
ConversionError::ParseCurrentResourceVersion { .. } => 500,
73+
ConversionError::ParseDesiredResourceVersion { .. } => 500,
74+
ConversionError::ObjectHasNoSpec {} => 400,
75+
ConversionError::ObjectHasNoKind {} => 400,
76+
ConversionError::ObjectHasNoApiVersion {} => 400,
77+
ConversionError::ObjectKindNotString { .. } => 400,
78+
ConversionError::ObjectApiVersionNotString { .. } => 400,
79+
ConversionError::WrongObjectKind { .. } => 400,
80+
ConversionError::DeserializeObjectSpec { .. } => 500,
81+
ConversionError::SerializeObjectSpec { .. } => 500,
82+
}
83+
}
84+
85+
pub fn as_human_readable_error_message(&self) -> String {
86+
let mut error_message = String::new();
87+
write!(error_message, "{self}").expect("Writing to Strings can not fail");
88+
89+
let mut source = self.source();
90+
while let Some(err) = source {
91+
write!(error_message, ": {err}").expect("Writing to Strings can not fail");
92+
source = err.source();
93+
}
94+
95+
error_message
96+
}
97+
}

0 commit comments

Comments
 (0)