diff --git a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs index 7023cca0c..e6d7b9d6b 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -156,7 +156,8 @@ impl Struct { let status_struct = self.generate_kubernetes_status_struct(kubernetes_arguments, is_nested); let version_enum = self.generate_kubernetes_version_enum(kubernetes_arguments, tokens, vis, is_nested); - let convert_method = self.generate_kubernetes_conversion(versions); + let (try_convert_fn, convert_objects_fn) = + self.generate_kubernetes_conversion_functions(versions); let parse_object_error = quote! { #versioned_path::ParseObjectError }; @@ -178,7 +179,7 @@ impl Struct { #kube_core_path::crd::merge_crds(vec![#(#crd_fns),*], stored_apiversion.as_version_str()) } - #convert_method + #convert_objects_fn fn from_json_object(object_value: #serde_json_path::Value) -> ::std::result::Result { let object_kind = object_value @@ -227,6 +228,10 @@ impl Struct { } } + impl #versioned_path::KubernetesConvertable for #enum_ident { + #try_convert_fn + } + #version_enum #status_struct }) @@ -354,11 +359,23 @@ impl Struct { }) } - fn generate_kubernetes_conversion( + /// Generates functions that are related to Kubernetes conversion. + /// + /// It will return two functions: + /// + /// 1. `try_convert`: This function should be used to implement the + /// `stackable_versioned::KubernetesConvertable` trait. + /// 2. `convert_objects`: This is an internal helper for `try_convert` + fn generate_kubernetes_conversion_functions( &self, versions: &[VersionDefinition], - ) -> Option { - let kubernetes_arguments = self.common.options.kubernetes_arguments.as_ref()?; + ) -> (TokenStream, TokenStream) { + let kubernetes_arguments = self + .common + .options + .kubernetes_arguments + .as_ref() + .expect("The kubernetes arguments must be present when generating Kubernetes conversion functions"); let struct_ident = &self.common.idents.kubernetes; let version_enum_ident = &self.common.idents.kubernetes_version; @@ -398,10 +415,10 @@ impl Struct { } .into_doc_comments(); - Some(quote! { + let try_convert_fn = quote! { #(#[doc = #docs])* #try_convert_instrumentation - pub fn try_convert(review: #kube_core_path::conversion::ConversionReview) + fn try_convert(review: #kube_core_path::conversion::ConversionReview) -> #kube_core_path::conversion::ConversionReview { // First, turn the review into a conversion request @@ -462,7 +479,8 @@ impl Struct { response.into_review() } - + }; + let convert_objects_fn = quote! { #convert_objects_instrumentation fn convert_objects( objects: ::std::vec::Vec<#serde_json_path::Value>, @@ -501,7 +519,9 @@ impl Struct { ::std::result::Result::Ok(converted_objects) } - }) + }; + + (try_convert_fn, convert_objects_fn) } fn generate_kubernetes_conversion_match_arms( diff --git a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@basic.rs.snap b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@basic.rs.snap index cad771f3f..a2bd2c3fd 100644 --- a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@basic.rs.snap +++ b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@basic.rs.snap @@ -136,62 +136,6 @@ impl Foo { stored_apiversion.as_version_str(), ) } - ///Tries to convert a list of objects of kind [`Foo`] to the desired API version - ///specified in the [`ConversionReview`][cr]. - /// - ///The returned [`ConversionReview`][cr] either indicates a success or a failure, which - ///is handed back to the Kubernetes API server. - /// - ///[cr]: ::kube::core::conversion::ConversionReview - pub fn try_convert( - review: ::kube::core::conversion::ConversionReview, - ) -> ::kube::core::conversion::ConversionReview { - let request = match ::kube::core::conversion::ConversionRequest::from_review( - review, - ) { - ::std::result::Result::Ok(request) => request, - ::std::result::Result::Err(err) => { - return ::kube::core::conversion::ConversionResponse::invalid(::kube::client::Status { - status: Some(::kube::core::response::StatusSummary::Failure), - message: err.to_string(), - reason: err.to_string(), - details: None, - code: 400, - }) - .into_review(); - } - }; - let response = match Self::convert_objects( - request.objects, - &request.desired_api_version, - ) { - ::std::result::Result::Ok(converted_objects) => { - ::kube::core::conversion::ConversionResponse { - result: ::kube::client::Status::success(), - types: request.types, - uid: request.uid, - converted_objects, - } - } - ::std::result::Result::Err(err) => { - let code = err.http_status_code(); - let message = err.join_errors(); - ::kube::core::conversion::ConversionResponse { - result: ::kube::client::Status { - status: Some(::kube::core::response::StatusSummary::Failure), - message: message.clone(), - reason: message, - details: None, - code, - }, - types: request.types, - uid: request.uid, - converted_objects: vec![], - } - } - }; - response.into_review() - } fn convert_objects( objects: ::std::vec::Vec<::serde_json::Value>, desired_api_version: &str, @@ -368,6 +312,64 @@ impl Foo { } } } +impl ::stackable_versioned::KubernetesConvertable for Foo { + ///Tries to convert a list of objects of kind [`Foo`] to the desired API version + ///specified in the [`ConversionReview`][cr]. + /// + ///The returned [`ConversionReview`][cr] either indicates a success or a failure, which + ///is handed back to the Kubernetes API server. + /// + ///[cr]: ::kube::core::conversion::ConversionReview + fn try_convert( + review: ::kube::core::conversion::ConversionReview, + ) -> ::kube::core::conversion::ConversionReview { + let request = match ::kube::core::conversion::ConversionRequest::from_review( + review, + ) { + ::std::result::Result::Ok(request) => request, + ::std::result::Result::Err(err) => { + return ::kube::core::conversion::ConversionResponse::invalid(::kube::client::Status { + status: Some(::kube::core::response::StatusSummary::Failure), + message: err.to_string(), + reason: err.to_string(), + details: None, + code: 400, + }) + .into_review(); + } + }; + let response = match Self::convert_objects( + request.objects, + &request.desired_api_version, + ) { + ::std::result::Result::Ok(converted_objects) => { + ::kube::core::conversion::ConversionResponse { + result: ::kube::client::Status::success(), + types: request.types, + uid: request.uid, + converted_objects, + } + } + ::std::result::Result::Err(err) => { + let code = err.http_status_code(); + let message = err.join_errors(); + ::kube::core::conversion::ConversionResponse { + result: ::kube::client::Status { + status: Some(::kube::core::response::StatusSummary::Failure), + message: message.clone(), + reason: message, + details: None, + code, + }, + types: request.types, + uid: request.uid, + converted_objects: vec![], + } + } + }; + response.into_review() + } +} #[automatically_derived] #[derive(Copy, Clone, Debug)] pub(crate) enum FooVersion { diff --git a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@conversion_tracking.rs.snap b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@conversion_tracking.rs.snap index 9a7ee26d5..a3b7d386f 100644 --- a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@conversion_tracking.rs.snap +++ b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@conversion_tracking.rs.snap @@ -106,62 +106,6 @@ impl Foo { stored_apiversion.as_version_str(), ) } - ///Tries to convert a list of objects of kind [`Foo`] to the desired API version - ///specified in the [`ConversionReview`][cr]. - /// - ///The returned [`ConversionReview`][cr] either indicates a success or a failure, which - ///is handed back to the Kubernetes API server. - /// - ///[cr]: ::kube::core::conversion::ConversionReview - pub fn try_convert( - review: ::kube::core::conversion::ConversionReview, - ) -> ::kube::core::conversion::ConversionReview { - let request = match ::kube::core::conversion::ConversionRequest::from_review( - review, - ) { - ::std::result::Result::Ok(request) => request, - ::std::result::Result::Err(err) => { - return ::kube::core::conversion::ConversionResponse::invalid(::kube::client::Status { - status: Some(::kube::core::response::StatusSummary::Failure), - message: err.to_string(), - reason: err.to_string(), - details: None, - code: 400, - }) - .into_review(); - } - }; - let response = match Self::convert_objects( - request.objects, - &request.desired_api_version, - ) { - ::std::result::Result::Ok(converted_objects) => { - ::kube::core::conversion::ConversionResponse { - result: ::kube::client::Status::success(), - types: request.types, - uid: request.uid, - converted_objects, - } - } - ::std::result::Result::Err(err) => { - let code = err.http_status_code(); - let message = err.join_errors(); - ::kube::core::conversion::ConversionResponse { - result: ::kube::client::Status { - status: Some(::kube::core::response::StatusSummary::Failure), - message: message.clone(), - reason: message, - details: None, - code, - }, - types: request.types, - uid: request.uid, - converted_objects: vec![], - } - } - }; - response.into_review() - } fn convert_objects( objects: ::std::vec::Vec<::serde_json::Value>, desired_api_version: &str, @@ -338,6 +282,64 @@ impl Foo { } } } +impl ::stackable_versioned::KubernetesConvertable for Foo { + ///Tries to convert a list of objects of kind [`Foo`] to the desired API version + ///specified in the [`ConversionReview`][cr]. + /// + ///The returned [`ConversionReview`][cr] either indicates a success or a failure, which + ///is handed back to the Kubernetes API server. + /// + ///[cr]: ::kube::core::conversion::ConversionReview + fn try_convert( + review: ::kube::core::conversion::ConversionReview, + ) -> ::kube::core::conversion::ConversionReview { + let request = match ::kube::core::conversion::ConversionRequest::from_review( + review, + ) { + ::std::result::Result::Ok(request) => request, + ::std::result::Result::Err(err) => { + return ::kube::core::conversion::ConversionResponse::invalid(::kube::client::Status { + status: Some(::kube::core::response::StatusSummary::Failure), + message: err.to_string(), + reason: err.to_string(), + details: None, + code: 400, + }) + .into_review(); + } + }; + let response = match Self::convert_objects( + request.objects, + &request.desired_api_version, + ) { + ::std::result::Result::Ok(converted_objects) => { + ::kube::core::conversion::ConversionResponse { + result: ::kube::client::Status::success(), + types: request.types, + uid: request.uid, + converted_objects, + } + } + ::std::result::Result::Err(err) => { + let code = err.http_status_code(); + let message = err.join_errors(); + ::kube::core::conversion::ConversionResponse { + result: ::kube::client::Status { + status: Some(::kube::core::response::StatusSummary::Failure), + message: message.clone(), + reason: message, + details: None, + code, + }, + types: request.types, + uid: request.uid, + converted_objects: vec![], + } + } + }; + response.into_review() + } +} #[automatically_derived] #[derive(Copy, Clone, Debug)] pub(crate) enum FooVersion { diff --git a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@crate_overrides.rs.snap b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@crate_overrides.rs.snap index 2a120aa0e..460c03d30 100644 --- a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@crate_overrides.rs.snap +++ b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@crate_overrides.rs.snap @@ -127,62 +127,6 @@ impl Foo { stored_apiversion.as_version_str(), ) } - ///Tries to convert a list of objects of kind [`Foo`] to the desired API version - ///specified in the [`ConversionReview`][cr]. - /// - ///The returned [`ConversionReview`][cr] either indicates a success or a failure, which - ///is handed back to the Kubernetes API server. - /// - ///[cr]: ::kube::core::conversion::ConversionReview - pub fn try_convert( - review: ::kube::core::conversion::ConversionReview, - ) -> ::kube::core::conversion::ConversionReview { - let request = match ::kube::core::conversion::ConversionRequest::from_review( - review, - ) { - ::std::result::Result::Ok(request) => request, - ::std::result::Result::Err(err) => { - return ::kube::core::conversion::ConversionResponse::invalid(::kube::client::Status { - status: Some(::kube::core::response::StatusSummary::Failure), - message: err.to_string(), - reason: err.to_string(), - details: None, - code: 400, - }) - .into_review(); - } - }; - let response = match Self::convert_objects( - request.objects, - &request.desired_api_version, - ) { - ::std::result::Result::Ok(converted_objects) => { - ::kube::core::conversion::ConversionResponse { - result: ::kube::client::Status::success(), - types: request.types, - uid: request.uid, - converted_objects, - } - } - ::std::result::Result::Err(err) => { - let code = err.http_status_code(); - let message = err.join_errors(); - ::kube::core::conversion::ConversionResponse { - result: ::kube::client::Status { - status: Some(::kube::core::response::StatusSummary::Failure), - message: message.clone(), - reason: message, - details: None, - code, - }, - types: request.types, - uid: request.uid, - converted_objects: vec![], - } - } - }; - response.into_review() - } fn convert_objects( objects: ::std::vec::Vec<::serde_json::Value>, desired_api_version: &str, @@ -353,6 +297,64 @@ impl Foo { } } } +impl ::stackable_versioned::KubernetesConvertable for Foo { + ///Tries to convert a list of objects of kind [`Foo`] to the desired API version + ///specified in the [`ConversionReview`][cr]. + /// + ///The returned [`ConversionReview`][cr] either indicates a success or a failure, which + ///is handed back to the Kubernetes API server. + /// + ///[cr]: ::kube::core::conversion::ConversionReview + fn try_convert( + review: ::kube::core::conversion::ConversionReview, + ) -> ::kube::core::conversion::ConversionReview { + let request = match ::kube::core::conversion::ConversionRequest::from_review( + review, + ) { + ::std::result::Result::Ok(request) => request, + ::std::result::Result::Err(err) => { + return ::kube::core::conversion::ConversionResponse::invalid(::kube::client::Status { + status: Some(::kube::core::response::StatusSummary::Failure), + message: err.to_string(), + reason: err.to_string(), + details: None, + code: 400, + }) + .into_review(); + } + }; + let response = match Self::convert_objects( + request.objects, + &request.desired_api_version, + ) { + ::std::result::Result::Ok(converted_objects) => { + ::kube::core::conversion::ConversionResponse { + result: ::kube::client::Status::success(), + types: request.types, + uid: request.uid, + converted_objects, + } + } + ::std::result::Result::Err(err) => { + let code = err.http_status_code(); + let message = err.join_errors(); + ::kube::core::conversion::ConversionResponse { + result: ::kube::client::Status { + status: Some(::kube::core::response::StatusSummary::Failure), + message: message.clone(), + reason: message, + details: None, + code, + }, + types: request.types, + uid: request.uid, + converted_objects: vec![], + } + } + }; + response.into_review() + } +} #[automatically_derived] #[derive(Copy, Clone, Debug)] pub enum FooVersion { diff --git a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@module.rs.snap b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@module.rs.snap index 0eec1bba4..717011040 100644 --- a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@module.rs.snap +++ b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@module.rs.snap @@ -299,62 +299,6 @@ impl Foo { stored_apiversion.as_version_str(), ) } - ///Tries to convert a list of objects of kind [`Foo`] to the desired API version - ///specified in the [`ConversionReview`][cr]. - /// - ///The returned [`ConversionReview`][cr] either indicates a success or a failure, which - ///is handed back to the Kubernetes API server. - /// - ///[cr]: ::kube::core::conversion::ConversionReview - pub fn try_convert( - review: ::kube::core::conversion::ConversionReview, - ) -> ::kube::core::conversion::ConversionReview { - let request = match ::kube::core::conversion::ConversionRequest::from_review( - review, - ) { - ::std::result::Result::Ok(request) => request, - ::std::result::Result::Err(err) => { - return ::kube::core::conversion::ConversionResponse::invalid(::kube::client::Status { - status: Some(::kube::core::response::StatusSummary::Failure), - message: err.to_string(), - reason: err.to_string(), - details: None, - code: 400, - }) - .into_review(); - } - }; - let response = match Self::convert_objects( - request.objects, - &request.desired_api_version, - ) { - ::std::result::Result::Ok(converted_objects) => { - ::kube::core::conversion::ConversionResponse { - result: ::kube::client::Status::success(), - types: request.types, - uid: request.uid, - converted_objects, - } - } - ::std::result::Result::Err(err) => { - let code = err.http_status_code(); - let message = err.join_errors(); - ::kube::core::conversion::ConversionResponse { - result: ::kube::client::Status { - status: Some(::kube::core::response::StatusSummary::Failure), - message: message.clone(), - reason: message, - details: None, - code, - }, - types: request.types, - uid: request.uid, - converted_objects: vec![], - } - } - }; - response.into_review() - } fn convert_objects( objects: ::std::vec::Vec<::serde_json::Value>, desired_api_version: &str, @@ -525,6 +469,64 @@ impl Foo { } } } +impl ::stackable_versioned::KubernetesConvertable for Foo { + ///Tries to convert a list of objects of kind [`Foo`] to the desired API version + ///specified in the [`ConversionReview`][cr]. + /// + ///The returned [`ConversionReview`][cr] either indicates a success or a failure, which + ///is handed back to the Kubernetes API server. + /// + ///[cr]: ::kube::core::conversion::ConversionReview + fn try_convert( + review: ::kube::core::conversion::ConversionReview, + ) -> ::kube::core::conversion::ConversionReview { + let request = match ::kube::core::conversion::ConversionRequest::from_review( + review, + ) { + ::std::result::Result::Ok(request) => request, + ::std::result::Result::Err(err) => { + return ::kube::core::conversion::ConversionResponse::invalid(::kube::client::Status { + status: Some(::kube::core::response::StatusSummary::Failure), + message: err.to_string(), + reason: err.to_string(), + details: None, + code: 400, + }) + .into_review(); + } + }; + let response = match Self::convert_objects( + request.objects, + &request.desired_api_version, + ) { + ::std::result::Result::Ok(converted_objects) => { + ::kube::core::conversion::ConversionResponse { + result: ::kube::client::Status::success(), + types: request.types, + uid: request.uid, + converted_objects, + } + } + ::std::result::Result::Err(err) => { + let code = err.http_status_code(); + let message = err.join_errors(); + ::kube::core::conversion::ConversionResponse { + result: ::kube::client::Status { + status: Some(::kube::core::response::StatusSummary::Failure), + message: message.clone(), + reason: message, + details: None, + code, + }, + types: request.types, + uid: request.uid, + converted_objects: vec![], + } + } + }; + response.into_review() + } +} #[automatically_derived] #[derive(Copy, Clone, Debug)] pub(crate) enum FooVersion { @@ -596,62 +598,6 @@ impl Bar { stored_apiversion.as_version_str(), ) } - ///Tries to convert a list of objects of kind [`Bar`] to the desired API version - ///specified in the [`ConversionReview`][cr]. - /// - ///The returned [`ConversionReview`][cr] either indicates a success or a failure, which - ///is handed back to the Kubernetes API server. - /// - ///[cr]: ::kube::core::conversion::ConversionReview - pub fn try_convert( - review: ::kube::core::conversion::ConversionReview, - ) -> ::kube::core::conversion::ConversionReview { - let request = match ::kube::core::conversion::ConversionRequest::from_review( - review, - ) { - ::std::result::Result::Ok(request) => request, - ::std::result::Result::Err(err) => { - return ::kube::core::conversion::ConversionResponse::invalid(::kube::client::Status { - status: Some(::kube::core::response::StatusSummary::Failure), - message: err.to_string(), - reason: err.to_string(), - details: None, - code: 400, - }) - .into_review(); - } - }; - let response = match Self::convert_objects( - request.objects, - &request.desired_api_version, - ) { - ::std::result::Result::Ok(converted_objects) => { - ::kube::core::conversion::ConversionResponse { - result: ::kube::client::Status::success(), - types: request.types, - uid: request.uid, - converted_objects, - } - } - ::std::result::Result::Err(err) => { - let code = err.http_status_code(); - let message = err.join_errors(); - ::kube::core::conversion::ConversionResponse { - result: ::kube::client::Status { - status: Some(::kube::core::response::StatusSummary::Failure), - message: message.clone(), - reason: message, - details: None, - code, - }, - types: request.types, - uid: request.uid, - converted_objects: vec![], - } - } - }; - response.into_review() - } fn convert_objects( objects: ::std::vec::Vec<::serde_json::Value>, desired_api_version: &str, @@ -822,6 +768,64 @@ impl Bar { } } } +impl ::stackable_versioned::KubernetesConvertable for Bar { + ///Tries to convert a list of objects of kind [`Bar`] to the desired API version + ///specified in the [`ConversionReview`][cr]. + /// + ///The returned [`ConversionReview`][cr] either indicates a success or a failure, which + ///is handed back to the Kubernetes API server. + /// + ///[cr]: ::kube::core::conversion::ConversionReview + fn try_convert( + review: ::kube::core::conversion::ConversionReview, + ) -> ::kube::core::conversion::ConversionReview { + let request = match ::kube::core::conversion::ConversionRequest::from_review( + review, + ) { + ::std::result::Result::Ok(request) => request, + ::std::result::Result::Err(err) => { + return ::kube::core::conversion::ConversionResponse::invalid(::kube::client::Status { + status: Some(::kube::core::response::StatusSummary::Failure), + message: err.to_string(), + reason: err.to_string(), + details: None, + code: 400, + }) + .into_review(); + } + }; + let response = match Self::convert_objects( + request.objects, + &request.desired_api_version, + ) { + ::std::result::Result::Ok(converted_objects) => { + ::kube::core::conversion::ConversionResponse { + result: ::kube::client::Status::success(), + types: request.types, + uid: request.uid, + converted_objects, + } + } + ::std::result::Result::Err(err) => { + let code = err.http_status_code(); + let message = err.join_errors(); + ::kube::core::conversion::ConversionResponse { + result: ::kube::client::Status { + status: Some(::kube::core::response::StatusSummary::Failure), + message: message.clone(), + reason: message, + details: None, + code, + }, + types: request.types, + uid: request.uid, + converted_objects: vec![], + } + } + }; + response.into_review() + } +} #[automatically_derived] #[derive(Copy, Clone, Debug)] pub(crate) enum BarVersion { diff --git a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@module_preserve.rs.snap b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@module_preserve.rs.snap index 40f611cc6..175dd9839 100644 --- a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@module_preserve.rs.snap +++ b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@module_preserve.rs.snap @@ -280,62 +280,6 @@ pub(crate) mod versioned { stored_apiversion.as_version_str(), ) } - ///Tries to convert a list of objects of kind [`Foo`] to the desired API version - ///specified in the [`ConversionReview`][cr]. - /// - ///The returned [`ConversionReview`][cr] either indicates a success or a failure, which - ///is handed back to the Kubernetes API server. - /// - ///[cr]: ::kube::core::conversion::ConversionReview - pub fn try_convert( - review: ::kube::core::conversion::ConversionReview, - ) -> ::kube::core::conversion::ConversionReview { - let request = match ::kube::core::conversion::ConversionRequest::from_review( - review, - ) { - ::std::result::Result::Ok(request) => request, - ::std::result::Result::Err(err) => { - return ::kube::core::conversion::ConversionResponse::invalid(::kube::client::Status { - status: Some(::kube::core::response::StatusSummary::Failure), - message: err.to_string(), - reason: err.to_string(), - details: None, - code: 400, - }) - .into_review(); - } - }; - let response = match Self::convert_objects( - request.objects, - &request.desired_api_version, - ) { - ::std::result::Result::Ok(converted_objects) => { - ::kube::core::conversion::ConversionResponse { - result: ::kube::client::Status::success(), - types: request.types, - uid: request.uid, - converted_objects, - } - } - ::std::result::Result::Err(err) => { - let code = err.http_status_code(); - let message = err.join_errors(); - ::kube::core::conversion::ConversionResponse { - result: ::kube::client::Status { - status: Some(::kube::core::response::StatusSummary::Failure), - message: message.clone(), - reason: message, - details: None, - code, - }, - types: request.types, - uid: request.uid, - converted_objects: vec![], - } - } - }; - response.into_review() - } fn convert_objects( objects: ::std::vec::Vec<::serde_json::Value>, desired_api_version: &str, @@ -506,6 +450,64 @@ pub(crate) mod versioned { } } } + impl ::stackable_versioned::KubernetesConvertable for Foo { + ///Tries to convert a list of objects of kind [`Foo`] to the desired API version + ///specified in the [`ConversionReview`][cr]. + /// + ///The returned [`ConversionReview`][cr] either indicates a success or a failure, which + ///is handed back to the Kubernetes API server. + /// + ///[cr]: ::kube::core::conversion::ConversionReview + fn try_convert( + review: ::kube::core::conversion::ConversionReview, + ) -> ::kube::core::conversion::ConversionReview { + let request = match ::kube::core::conversion::ConversionRequest::from_review( + review, + ) { + ::std::result::Result::Ok(request) => request, + ::std::result::Result::Err(err) => { + return ::kube::core::conversion::ConversionResponse::invalid(::kube::client::Status { + status: Some(::kube::core::response::StatusSummary::Failure), + message: err.to_string(), + reason: err.to_string(), + details: None, + code: 400, + }) + .into_review(); + } + }; + let response = match Self::convert_objects( + request.objects, + &request.desired_api_version, + ) { + ::std::result::Result::Ok(converted_objects) => { + ::kube::core::conversion::ConversionResponse { + result: ::kube::client::Status::success(), + types: request.types, + uid: request.uid, + converted_objects, + } + } + ::std::result::Result::Err(err) => { + let code = err.http_status_code(); + let message = err.join_errors(); + ::kube::core::conversion::ConversionResponse { + result: ::kube::client::Status { + status: Some(::kube::core::response::StatusSummary::Failure), + message: message.clone(), + reason: message, + details: None, + code, + }, + types: request.types, + uid: request.uid, + converted_objects: vec![], + } + } + }; + response.into_review() + } + } #[derive(Copy, Clone, Debug)] pub enum FooVersion { V1Alpha1, @@ -572,62 +574,6 @@ pub(crate) mod versioned { stored_apiversion.as_version_str(), ) } - ///Tries to convert a list of objects of kind [`Bar`] to the desired API version - ///specified in the [`ConversionReview`][cr]. - /// - ///The returned [`ConversionReview`][cr] either indicates a success or a failure, which - ///is handed back to the Kubernetes API server. - /// - ///[cr]: ::kube::core::conversion::ConversionReview - pub fn try_convert( - review: ::kube::core::conversion::ConversionReview, - ) -> ::kube::core::conversion::ConversionReview { - let request = match ::kube::core::conversion::ConversionRequest::from_review( - review, - ) { - ::std::result::Result::Ok(request) => request, - ::std::result::Result::Err(err) => { - return ::kube::core::conversion::ConversionResponse::invalid(::kube::client::Status { - status: Some(::kube::core::response::StatusSummary::Failure), - message: err.to_string(), - reason: err.to_string(), - details: None, - code: 400, - }) - .into_review(); - } - }; - let response = match Self::convert_objects( - request.objects, - &request.desired_api_version, - ) { - ::std::result::Result::Ok(converted_objects) => { - ::kube::core::conversion::ConversionResponse { - result: ::kube::client::Status::success(), - types: request.types, - uid: request.uid, - converted_objects, - } - } - ::std::result::Result::Err(err) => { - let code = err.http_status_code(); - let message = err.join_errors(); - ::kube::core::conversion::ConversionResponse { - result: ::kube::client::Status { - status: Some(::kube::core::response::StatusSummary::Failure), - message: message.clone(), - reason: message, - details: None, - code, - }, - types: request.types, - uid: request.uid, - converted_objects: vec![], - } - } - }; - response.into_review() - } fn convert_objects( objects: ::std::vec::Vec<::serde_json::Value>, desired_api_version: &str, @@ -798,6 +744,64 @@ pub(crate) mod versioned { } } } + impl ::stackable_versioned::KubernetesConvertable for Bar { + ///Tries to convert a list of objects of kind [`Bar`] to the desired API version + ///specified in the [`ConversionReview`][cr]. + /// + ///The returned [`ConversionReview`][cr] either indicates a success or a failure, which + ///is handed back to the Kubernetes API server. + /// + ///[cr]: ::kube::core::conversion::ConversionReview + fn try_convert( + review: ::kube::core::conversion::ConversionReview, + ) -> ::kube::core::conversion::ConversionReview { + let request = match ::kube::core::conversion::ConversionRequest::from_review( + review, + ) { + ::std::result::Result::Ok(request) => request, + ::std::result::Result::Err(err) => { + return ::kube::core::conversion::ConversionResponse::invalid(::kube::client::Status { + status: Some(::kube::core::response::StatusSummary::Failure), + message: err.to_string(), + reason: err.to_string(), + details: None, + code: 400, + }) + .into_review(); + } + }; + let response = match Self::convert_objects( + request.objects, + &request.desired_api_version, + ) { + ::std::result::Result::Ok(converted_objects) => { + ::kube::core::conversion::ConversionResponse { + result: ::kube::client::Status::success(), + types: request.types, + uid: request.uid, + converted_objects, + } + } + ::std::result::Result::Err(err) => { + let code = err.http_status_code(); + let message = err.join_errors(); + ::kube::core::conversion::ConversionResponse { + result: ::kube::client::Status { + status: Some(::kube::core::response::StatusSummary::Failure), + message: message.clone(), + reason: message, + details: None, + code, + }, + types: request.types, + uid: request.uid, + converted_objects: vec![], + } + } + }; + response.into_review() + } + } #[derive(Copy, Clone, Debug)] pub enum BarVersion { V1Alpha1, diff --git a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@renamed_kind.rs.snap b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@renamed_kind.rs.snap index 899658557..218634986 100644 --- a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@renamed_kind.rs.snap +++ b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@renamed_kind.rs.snap @@ -112,62 +112,6 @@ impl FooBar { stored_apiversion.as_version_str(), ) } - ///Tries to convert a list of objects of kind [`FooBar`] to the desired API version - ///specified in the [`ConversionReview`][cr]. - /// - ///The returned [`ConversionReview`][cr] either indicates a success or a failure, which - ///is handed back to the Kubernetes API server. - /// - ///[cr]: ::kube::core::conversion::ConversionReview - pub fn try_convert( - review: ::kube::core::conversion::ConversionReview, - ) -> ::kube::core::conversion::ConversionReview { - let request = match ::kube::core::conversion::ConversionRequest::from_review( - review, - ) { - ::std::result::Result::Ok(request) => request, - ::std::result::Result::Err(err) => { - return ::kube::core::conversion::ConversionResponse::invalid(::kube::client::Status { - status: Some(::kube::core::response::StatusSummary::Failure), - message: err.to_string(), - reason: err.to_string(), - details: None, - code: 400, - }) - .into_review(); - } - }; - let response = match Self::convert_objects( - request.objects, - &request.desired_api_version, - ) { - ::std::result::Result::Ok(converted_objects) => { - ::kube::core::conversion::ConversionResponse { - result: ::kube::client::Status::success(), - types: request.types, - uid: request.uid, - converted_objects, - } - } - ::std::result::Result::Err(err) => { - let code = err.http_status_code(); - let message = err.join_errors(); - ::kube::core::conversion::ConversionResponse { - result: ::kube::client::Status { - status: Some(::kube::core::response::StatusSummary::Failure), - message: message.clone(), - reason: message, - details: None, - code, - }, - types: request.types, - uid: request.uid, - converted_objects: vec![], - } - } - }; - response.into_review() - } fn convert_objects( objects: ::std::vec::Vec<::serde_json::Value>, desired_api_version: &str, @@ -338,6 +282,64 @@ impl FooBar { } } } +impl ::stackable_versioned::KubernetesConvertable for FooBar { + ///Tries to convert a list of objects of kind [`FooBar`] to the desired API version + ///specified in the [`ConversionReview`][cr]. + /// + ///The returned [`ConversionReview`][cr] either indicates a success or a failure, which + ///is handed back to the Kubernetes API server. + /// + ///[cr]: ::kube::core::conversion::ConversionReview + fn try_convert( + review: ::kube::core::conversion::ConversionReview, + ) -> ::kube::core::conversion::ConversionReview { + let request = match ::kube::core::conversion::ConversionRequest::from_review( + review, + ) { + ::std::result::Result::Ok(request) => request, + ::std::result::Result::Err(err) => { + return ::kube::core::conversion::ConversionResponse::invalid(::kube::client::Status { + status: Some(::kube::core::response::StatusSummary::Failure), + message: err.to_string(), + reason: err.to_string(), + details: None, + code: 400, + }) + .into_review(); + } + }; + let response = match Self::convert_objects( + request.objects, + &request.desired_api_version, + ) { + ::std::result::Result::Ok(converted_objects) => { + ::kube::core::conversion::ConversionResponse { + result: ::kube::client::Status::success(), + types: request.types, + uid: request.uid, + converted_objects, + } + } + ::std::result::Result::Err(err) => { + let code = err.http_status_code(); + let message = err.join_errors(); + ::kube::core::conversion::ConversionResponse { + result: ::kube::client::Status { + status: Some(::kube::core::response::StatusSummary::Failure), + message: message.clone(), + reason: message, + details: None, + code, + }, + types: request.types, + uid: request.uid, + converted_objects: vec![], + } + } + }; + response.into_review() + } +} #[automatically_derived] #[derive(Copy, Clone, Debug)] pub enum FooBarVersion { diff --git a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@shortnames.rs.snap b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@shortnames.rs.snap index 6d0d019fc..e64cd9fb6 100644 --- a/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@shortnames.rs.snap +++ b/crates/stackable-versioned-macros/tests/snapshots/stackable_versioned_macros__snapshot_tests__k8s@shortnames.rs.snap @@ -41,62 +41,6 @@ impl Foo { stored_apiversion.as_version_str(), ) } - ///Tries to convert a list of objects of kind [`Foo`] to the desired API version - ///specified in the [`ConversionReview`][cr]. - /// - ///The returned [`ConversionReview`][cr] either indicates a success or a failure, which - ///is handed back to the Kubernetes API server. - /// - ///[cr]: ::kube::core::conversion::ConversionReview - pub fn try_convert( - review: ::kube::core::conversion::ConversionReview, - ) -> ::kube::core::conversion::ConversionReview { - let request = match ::kube::core::conversion::ConversionRequest::from_review( - review, - ) { - ::std::result::Result::Ok(request) => request, - ::std::result::Result::Err(err) => { - return ::kube::core::conversion::ConversionResponse::invalid(::kube::client::Status { - status: Some(::kube::core::response::StatusSummary::Failure), - message: err.to_string(), - reason: err.to_string(), - details: None, - code: 400, - }) - .into_review(); - } - }; - let response = match Self::convert_objects( - request.objects, - &request.desired_api_version, - ) { - ::std::result::Result::Ok(converted_objects) => { - ::kube::core::conversion::ConversionResponse { - result: ::kube::client::Status::success(), - types: request.types, - uid: request.uid, - converted_objects, - } - } - ::std::result::Result::Err(err) => { - let code = err.http_status_code(); - let message = err.join_errors(); - ::kube::core::conversion::ConversionResponse { - result: ::kube::client::Status { - status: Some(::kube::core::response::StatusSummary::Failure), - message: message.clone(), - reason: message, - details: None, - code, - }, - types: request.types, - uid: request.uid, - converted_objects: vec![], - } - } - }; - response.into_review() - } fn convert_objects( objects: ::std::vec::Vec<::serde_json::Value>, desired_api_version: &str, @@ -171,6 +115,64 @@ impl Foo { } } } +impl ::stackable_versioned::KubernetesConvertable for Foo { + ///Tries to convert a list of objects of kind [`Foo`] to the desired API version + ///specified in the [`ConversionReview`][cr]. + /// + ///The returned [`ConversionReview`][cr] either indicates a success or a failure, which + ///is handed back to the Kubernetes API server. + /// + ///[cr]: ::kube::core::conversion::ConversionReview + fn try_convert( + review: ::kube::core::conversion::ConversionReview, + ) -> ::kube::core::conversion::ConversionReview { + let request = match ::kube::core::conversion::ConversionRequest::from_review( + review, + ) { + ::std::result::Result::Ok(request) => request, + ::std::result::Result::Err(err) => { + return ::kube::core::conversion::ConversionResponse::invalid(::kube::client::Status { + status: Some(::kube::core::response::StatusSummary::Failure), + message: err.to_string(), + reason: err.to_string(), + details: None, + code: 400, + }) + .into_review(); + } + }; + let response = match Self::convert_objects( + request.objects, + &request.desired_api_version, + ) { + ::std::result::Result::Ok(converted_objects) => { + ::kube::core::conversion::ConversionResponse { + result: ::kube::client::Status::success(), + types: request.types, + uid: request.uid, + converted_objects, + } + } + ::std::result::Result::Err(err) => { + let code = err.http_status_code(); + let message = err.join_errors(); + ::kube::core::conversion::ConversionResponse { + result: ::kube::client::Status { + status: Some(::kube::core::response::StatusSummary::Failure), + message: message.clone(), + reason: message, + details: None, + code, + }, + types: request.types, + uid: request.uid, + converted_objects: vec![], + } + } + }; + response.into_review() + } +} #[automatically_derived] #[derive(Copy, Clone, Debug)] pub(crate) enum FooVersion { diff --git a/crates/stackable-versioned/CHANGELOG.md b/crates/stackable-versioned/CHANGELOG.md index 8435ff4c1..993f2bb92 100644 --- a/crates/stackable-versioned/CHANGELOG.md +++ b/crates/stackable-versioned/CHANGELOG.md @@ -7,7 +7,8 @@ All notable changes to this project will be documented in this file. ### Added - Add support for CRD conversions via ConversionReviews ([#1050], [#1061]). - - Add new `try_convert` function to convert objects received via a ConversionReview. + - Implement the new `KubernetesConvertable` trait with the `try_convert` function to convert + objects received via a ConversionReview. - Add new `enable_tracing` option to `#[versioned(k8s(options(...)))]`. - Add a `Version` enum with `from_api_version`, `as_version_str` and `as_api_version_str` functions. diff --git a/crates/stackable-versioned/Cargo.toml b/crates/stackable-versioned/Cargo.toml index 1db42accd..1718960e8 100644 --- a/crates/stackable-versioned/Cargo.toml +++ b/crates/stackable-versioned/Cargo.toml @@ -15,6 +15,8 @@ full = ["k8s"] k8s = [ "stackable-versioned-macros/k8s", # Forward the k8s feature to the underlying macro crate "dep:k8s-version", + "dep:k8s-openapi", + "dep:kube", "dep:schemars", "dep:serde_json", "dep:serde_yaml", @@ -26,6 +28,8 @@ k8s = [ k8s-version = { path = "../k8s-version", features = ["serde"], optional = true } stackable-versioned-macros = { path = "../stackable-versioned-macros" } +k8s-openapi = { workspace = true, optional = true } +kube = { workspace = true, optional = true } schemars = { workspace = true, optional = true } serde = { workspace = true, optional = true } serde_json = { workspace = true, optional = true } diff --git a/crates/stackable-versioned/src/k8s.rs b/crates/stackable-versioned/src/k8s.rs index f55182fa8..3f03a6976 100644 --- a/crates/stackable-versioned/src/k8s.rs +++ b/crates/stackable-versioned/src/k8s.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use k8s_version::Version; +use kube::core::conversion::ConversionReview; use schemars::schema::{InstanceType, Schema, SchemaObject, SingleOrVec}; use snafu::{ErrorCompat, Snafu}; @@ -63,6 +64,10 @@ pub enum ParseObjectError { UnexpectedKind { kind: String, expected: String }, } +pub trait KubernetesConvertable { + fn try_convert(review: ConversionReview) -> ConversionReview; +} + /// This error indicates that converting an object from a conversion review to the desired /// version failed. #[derive(Debug, Snafu)] diff --git a/crates/stackable-versioned/tests/conversions.rs b/crates/stackable-versioned/tests/conversions.rs index c5bb0e337..1e9e76b88 100644 --- a/crates/stackable-versioned/tests/conversions.rs +++ b/crates/stackable-versioned/tests/conversions.rs @@ -2,6 +2,7 @@ use std::{fs::File, path::Path}; use insta::{assert_snapshot, glob}; use kube::core::{conversion::ConversionReview, response::StatusSummary}; +use stackable_versioned::KubernetesConvertable; use crate::person::Person;