From ee724daf433717dd19a4c56ef14e1b2cbcc52b80 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Tue, 17 Jun 2025 17:33:10 +0200 Subject: [PATCH 01/33] fix: ConversionReview not working correctly. Also added some tests --- Cargo.lock | 3 + .../src/codegen/container/struct/k8s.rs | 55 +++++-- crates/stackable-versioned/Cargo.toml | 5 + .../fixtures/inputs/fail/request_missing.json | 4 + .../inputs/fail/unkown_current_version.json | 22 +++ .../inputs/fail/unkown_desired_version.json | 22 +++ .../fail/unparseable_missing_field.json | 20 +++ .../fixtures/inputs/fail/wrong_kind.json | 22 +++ .../inputs/pass/persons_to_v1alpha1.json | 64 ++++++++ .../fixtures/inputs/pass/persons_to_v3.json | 64 ++++++++ crates/stackable-versioned/src/k8s.rs | 5 + crates/stackable-versioned/src/lib.rs | 3 + ...sts__tests__fail@request_missing.json.snap | 19 +++ ...sts__fail@unkown_current_version.json.snap | 19 +++ ...sts__fail@unkown_desired_version.json.snap | 19 +++ ...__fail@unparseable_missing_field.json.snap | 19 +++ ...ests__tests__fail@wrong_kind.json.snap.new | 33 ++++ ..._tests__pass@persons_to_v1alpha1.json.snap | 61 ++++++++ ...tests__tests__pass@persons_to_v3.json.snap | 76 ++++++++++ crates/stackable-versioned/src/tests.rs | 142 ++++++++++++++++++ 20 files changed, 665 insertions(+), 12 deletions(-) create mode 100644 crates/stackable-versioned/fixtures/inputs/fail/request_missing.json create mode 100644 crates/stackable-versioned/fixtures/inputs/fail/unkown_current_version.json create mode 100644 crates/stackable-versioned/fixtures/inputs/fail/unkown_desired_version.json create mode 100644 crates/stackable-versioned/fixtures/inputs/fail/unparseable_missing_field.json create mode 100644 crates/stackable-versioned/fixtures/inputs/fail/wrong_kind.json create mode 100644 crates/stackable-versioned/fixtures/inputs/pass/persons_to_v1alpha1.json create mode 100644 crates/stackable-versioned/fixtures/inputs/pass/persons_to_v3.json create mode 100644 crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@request_missing.json.snap create mode 100644 crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@unkown_current_version.json.snap create mode 100644 crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@unkown_desired_version.json.snap create mode 100644 crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@unparseable_missing_field.json.snap create mode 100644 crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@wrong_kind.json.snap.new create mode 100644 crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__pass@persons_to_v1alpha1.json.snap create mode 100644 crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__pass@persons_to_v3.json.snap create mode 100644 crates/stackable-versioned/src/tests.rs diff --git a/Cargo.lock b/Cargo.lock index fc857bfdc..c89c0e3e1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3067,7 +3067,10 @@ dependencies = [ name = "stackable-versioned" version = "0.7.1" dependencies = [ + "insta", + "k8s-openapi", "k8s-version", + "kube", "schemars", "serde", "serde_json", 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 53b3b5361..521d3ce9d 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -186,8 +186,8 @@ impl Struct { .ok_or_else(|| #parse_object_error::FieldNotStr)?; let object = match api_version { - #(#api_versions | #variant_strings => { - let object = #serde_json_path::from_value(value) + #(#api_versions => { + let object = #serde_json_path::from_value(value) .map_err(|source| #parse_object_error::Deserialize { source })?; Self::#variant_idents(object) @@ -324,8 +324,10 @@ impl Struct { let convert_object_error = quote! { #versioned_path::ConvertObjectError }; // Generate conversion paths and the match arms for these paths - let match_arms = + let conversion_match_arms = self.generate_kubernetes_conversion_match_arms(versions, kubernetes_arguments); + let noop_match_arms = + self.generate_kubernetes_noop_match_arms(versions, kubernetes_arguments); // TODO (@Techassi): Make this a feature, drop the option from the macro arguments // Generate tracing attributes and events if tracing is enabled @@ -435,12 +437,13 @@ impl Struct { .map_err(|source| #convert_object_error::Parse { source })?; match (current_object, desired_api_version) { - #(#match_arms,)* - // If no match arm matches, this is a noop. This is the case if the desired - // version matches the current object api version. - // NOTE (@Techassi): I'm curious if this will ever happen? In theory the K8s - // apiserver should never send such a conversion review. - _ => converted_objects.push(object), + #(#conversion_match_arms,)* + #(#noop_match_arms,)* + (_, unknown_desired_api_version) => return ::std::result::Result::Err( + #convert_object_error::DesiredApiVersionUnknown{ + unknown_desired_api_version: unknown_desired_api_version.to_string() + } + ) } } @@ -454,6 +457,7 @@ impl Struct { versions: &[VersionDefinition], kubernetes_arguments: &KubernetesArguments, ) -> Vec { + let group = &kubernetes_arguments.group; let variant_data_ident = &self.common.idents.kubernetes_parameter; let struct_ident = &self.common.idents.kubernetes; let spec_ident = &self.common.idents.original; @@ -470,7 +474,10 @@ impl Struct { let current_object_version_string = &start.inner.to_string(); let desired_object_version = path.last().expect("the path always contains at least one element"); - let desired_object_version_string = desired_object_version.inner.to_string(); + let desired_object_api_version_string = format!( + "{group}/{desired_object_version}", + desired_object_version= desired_object_version.inner + ); let desired_object_variant_ident = &desired_object_version.idents.variant; let desired_object_module_ident = &desired_object_version.idents.module; @@ -493,7 +500,7 @@ impl Struct { let convert_object_trace = kubernetes_arguments.options.enable_tracing.is_present().then(|| quote! { ::tracing::trace!( - #DESIRED_API_VERSION_ATTRIBUTE = #desired_object_version_string, + #DESIRED_API_VERSION_ATTRIBUTE = #desired_object_api_version_string, #API_VERSION_ATTRIBUTE = #current_object_version_string, #STEPS_ATTRIBUTE = #steps, #KIND_ATTRIBUTE = #kind, @@ -507,7 +514,7 @@ impl Struct { .then(|| quote! { status: #variant_data_ident.status, }); quote! { - (Self::#current_object_version_ident(#variant_data_ident), #desired_object_version_string) => { + (Self::#current_object_version_ident(#variant_data_ident), #desired_object_api_version_string) => { #(#conversions)* let desired_object = Self::#desired_object_variant_ident(#desired_object_module_ident::#struct_ident { @@ -528,6 +535,30 @@ impl Struct { .collect() } + fn generate_kubernetes_noop_match_arms( + &self, + versions: &[VersionDefinition], + kubernetes_arguments: &KubernetesArguments, + ) -> Vec { + let group = &kubernetes_arguments.group; + + versions + .iter() + .map(|version| { + let version_ident = &version.idents.variant; + let version_string = version.inner.to_string(); + let api_version_string = format!("{group}/{version_string}"); + + quote! { + // This is the case if the desired version matches the current object api version. + // NOTE (@Techassi): I'm curious if this will ever happen? In theory the K8s + // apiserver should never send such a conversion review. + (Self::#version_ident(_), #api_version_string) => converted_objects.push(object) + } + }) + .collect() + } + fn generate_kubernetes_conversion_tracing( &self, kubernetes_arguments: &KubernetesArguments, diff --git a/crates/stackable-versioned/Cargo.toml b/crates/stackable-versioned/Cargo.toml index f25cc40db..1db42accd 100644 --- a/crates/stackable-versioned/Cargo.toml +++ b/crates/stackable-versioned/Cargo.toml @@ -31,3 +31,8 @@ serde = { workspace = true, optional = true } serde_json = { workspace = true, optional = true } serde_yaml = { workspace = true, optional = true } snafu = { workspace = true, optional = true } + +[dev-dependencies] +insta.workspace = true +k8s-openapi.workspace = true +kube.workspace = true diff --git a/crates/stackable-versioned/fixtures/inputs/fail/request_missing.json b/crates/stackable-versioned/fixtures/inputs/fail/request_missing.json new file mode 100644 index 000000000..b5759bcdb --- /dev/null +++ b/crates/stackable-versioned/fixtures/inputs/fail/request_missing.json @@ -0,0 +1,4 @@ +{ + "kind": "ConversionReview", + "apiVersion": "apiextensions.k8s.io/v1" +} diff --git a/crates/stackable-versioned/fixtures/inputs/fail/unkown_current_version.json b/crates/stackable-versioned/fixtures/inputs/fail/unkown_current_version.json new file mode 100644 index 000000000..6df3bb2d1 --- /dev/null +++ b/crates/stackable-versioned/fixtures/inputs/fail/unkown_current_version.json @@ -0,0 +1,22 @@ +{ + "kind": "ConversionReview", + "apiVersion": "apiextensions.k8s.io/v1", + "request": { + "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", + "desiredAPIVersion": "test.stackable.tech/v3", + "objects": [ + { + "apiVersion": "test.stackable.tech/v99", + "kind": "Person", + "metadata": { + "name": "sbernauer", + "namespace": "default", + "uid": "d41e2019-5de3-409c-a7b2-0799ecb95e4b" + }, + "spec": { + "username": "sbernauer" + } + } + ] + } +} diff --git a/crates/stackable-versioned/fixtures/inputs/fail/unkown_desired_version.json b/crates/stackable-versioned/fixtures/inputs/fail/unkown_desired_version.json new file mode 100644 index 000000000..736a95dfb --- /dev/null +++ b/crates/stackable-versioned/fixtures/inputs/fail/unkown_desired_version.json @@ -0,0 +1,22 @@ +{ + "kind": "ConversionReview", + "apiVersion": "apiextensions.k8s.io/v1", + "request": { + "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", + "desiredAPIVersion": "test.stackable.tech/v99", + "objects": [ + { + "apiVersion": "test.stackable.tech/v1alpha1", + "kind": "Person", + "metadata": { + "name": "sbernauer", + "namespace": "default", + "uid": "d41e2019-5de3-409c-a7b2-0799ecb95e4b" + }, + "spec": { + "username": "sbernauer" + } + } + ] + } +} diff --git a/crates/stackable-versioned/fixtures/inputs/fail/unparseable_missing_field.json b/crates/stackable-versioned/fixtures/inputs/fail/unparseable_missing_field.json new file mode 100644 index 000000000..56b8c5c8d --- /dev/null +++ b/crates/stackable-versioned/fixtures/inputs/fail/unparseable_missing_field.json @@ -0,0 +1,20 @@ +{ + "kind": "ConversionReview", + "apiVersion": "apiextensions.k8s.io/v1", + "request": { + "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", + "desiredAPIVersion": "test.stackable.tech/v3", + "objects": [ + { + "apiVersion": "test.stackable.tech/v1alpha1", + "kind": "Person", + "metadata": { + "name": "sbernauer", + "namespace": "default", + "uid": "d41e2019-5de3-409c-a7b2-0799ecb95e4b" + }, + "spec": {} + } + ] + } +} diff --git a/crates/stackable-versioned/fixtures/inputs/fail/wrong_kind.json b/crates/stackable-versioned/fixtures/inputs/fail/wrong_kind.json new file mode 100644 index 000000000..3c5bbcd67 --- /dev/null +++ b/crates/stackable-versioned/fixtures/inputs/fail/wrong_kind.json @@ -0,0 +1,22 @@ +{ + "kind": "ConversionReview", + "apiVersion": "apiextensions.k8s.io/v1", + "request": { + "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", + "desiredAPIVersion": "test.stackable.tech/v3", + "objects": [ + { + "apiVersion": "test.stackable.tech/v1alpha1", + "kind": "SomeOtherResource", + "metadata": { + "name": "sbernauer", + "namespace": "default", + "uid": "d41e2019-5de3-409c-a7b2-0799ecb95e4b" + }, + "spec": { + "username": "sbernauer" + } + } + ] + } +} diff --git a/crates/stackable-versioned/fixtures/inputs/pass/persons_to_v1alpha1.json b/crates/stackable-versioned/fixtures/inputs/pass/persons_to_v1alpha1.json new file mode 100644 index 000000000..2a0529763 --- /dev/null +++ b/crates/stackable-versioned/fixtures/inputs/pass/persons_to_v1alpha1.json @@ -0,0 +1,64 @@ +{ + "kind": "ConversionReview", + "apiVersion": "apiextensions.k8s.io/v1", + "request": { + "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", + "desiredAPIVersion": "test.stackable.tech/v1alpha1", + "objects": [ + { + "apiVersion": "test.stackable.tech/v1alpha1", + "kind": "Person", + "metadata": { + "name": "sbernauer", + "namespace": "default", + "uid": "d41e2019-5de3-409c-a7b2-0799ecb95e4b" + }, + "spec": { + "username": "sbernauer" + } + }, + { + "apiVersion": "test.stackable.tech/v1alpha2", + "kind": "Person", + "metadata": {}, + "spec": { + "username": "sbernauer", + "firstName": "Sebastian", + "lastName": "Bernauer" + } + }, + { + "apiVersion": "test.stackable.tech/v1beta1", + "kind": "Person", + "metadata": {}, + "spec": { + "username": "sbernauer", + "firstName": "Sebastian", + "lastName": "Bernauer" + } + }, + { + "apiVersion": "test.stackable.tech/v2", + "kind": "Person", + "metadata": {}, + "spec": { + "username": "sbernauer", + "firstName": "Sebastian", + "lastName": "Bernauer", + "gender": "Male" + } + }, + { + "apiVersion": "test.stackable.tech/v3", + "kind": "Person", + "metadata": {}, + "spec": { + "username": "sbernauer", + "firstName": "Sebastian", + "lastName": "Bernauer", + "gender": "Male" + } + } + ] + } +} diff --git a/crates/stackable-versioned/fixtures/inputs/pass/persons_to_v3.json b/crates/stackable-versioned/fixtures/inputs/pass/persons_to_v3.json new file mode 100644 index 000000000..14848515e --- /dev/null +++ b/crates/stackable-versioned/fixtures/inputs/pass/persons_to_v3.json @@ -0,0 +1,64 @@ +{ + "kind": "ConversionReview", + "apiVersion": "apiextensions.k8s.io/v1", + "request": { + "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", + "desiredAPIVersion": "test.stackable.tech/v3", + "objects": [ + { + "apiVersion": "test.stackable.tech/v1alpha1", + "kind": "Person", + "metadata": { + "name": "sbernauer", + "namespace": "default", + "uid": "d41e2019-5de3-409c-a7b2-0799ecb95e4b" + }, + "spec": { + "username": "sbernauer" + } + }, + { + "apiVersion": "test.stackable.tech/v1alpha2", + "kind": "Person", + "metadata": {}, + "spec": { + "username": "sbernauer", + "firstName": "Sebastian", + "lastName": "Bernauer" + } + }, + { + "apiVersion": "test.stackable.tech/v1beta1", + "kind": "Person", + "metadata": {}, + "spec": { + "username": "sbernauer", + "firstName": "Sebastian", + "lastName": "Bernauer" + } + }, + { + "apiVersion": "test.stackable.tech/v2", + "kind": "Person", + "metadata": {}, + "spec": { + "username": "sbernauer", + "firstName": "Sebastian", + "lastName": "Bernauer", + "gender": "Male" + } + }, + { + "apiVersion": "test.stackable.tech/v3", + "kind": "Person", + "metadata": {}, + "spec": { + "username": "sbernauer", + "firstName": "Sebastian", + "lastName": "Bernauer", + "gender": "Male" + } + } + ] + } +} diff --git a/crates/stackable-versioned/src/k8s.rs b/crates/stackable-versioned/src/k8s.rs index 63dd01ade..25eed324a 100644 --- a/crates/stackable-versioned/src/k8s.rs +++ b/crates/stackable-versioned/src/k8s.rs @@ -69,6 +69,9 @@ pub enum ConvertObjectError { #[snafu(display("failed to serialize object into json"))] Serialize { source: serde_json::Error }, + + #[snafu(display("unknown desired API version {unknown_desired_api_version:?}"))] + DesiredApiVersionUnknown { unknown_desired_api_version: String }, } impl ConvertObjectError { @@ -89,6 +92,8 @@ impl ConvertObjectError { match self { ConvertObjectError::Parse { .. } => 400, ConvertObjectError::Serialize { .. } => 500, + // This is likely the clients fault, as it is requesting a unsupported version + ConvertObjectError::DesiredApiVersionUnknown { .. } => 400, } } } diff --git a/crates/stackable-versioned/src/lib.rs b/crates/stackable-versioned/src/lib.rs index 5538eae65..0c3da4448 100644 --- a/crates/stackable-versioned/src/lib.rs +++ b/crates/stackable-versioned/src/lib.rs @@ -17,3 +17,6 @@ pub use stackable_versioned_macros::versioned; mod k8s; #[cfg(feature = "k8s")] pub use k8s::*; + +#[cfg(test)] +mod tests; diff --git a/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@request_missing.json.snap b/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@request_missing.json.snap new file mode 100644 index 000000000..1e3c4016a --- /dev/null +++ b/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@request_missing.json.snap @@ -0,0 +1,19 @@ +--- +source: crates/stackable-versioned/src/tests.rs +expression: formatted +input_file: crates/stackable-versioned/fixtures/inputs/fail/request_missing.json +--- +{ + "apiVersion": "apiextensions.k8s.io/v1", + "kind": "ConversionReview", + "response": { + "uid": "", + "result": { + "status": "Failure", + "code": 400, + "message": "request missing in ConversionReview", + "reason": "request missing in ConversionReview" + }, + "convertedObjects": [] + } +} diff --git a/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@unkown_current_version.json.snap b/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@unkown_current_version.json.snap new file mode 100644 index 000000000..77a7e15ce --- /dev/null +++ b/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@unkown_current_version.json.snap @@ -0,0 +1,19 @@ +--- +source: crates/stackable-versioned/src/tests.rs +expression: formatted +input_file: crates/stackable-versioned/fixtures/inputs/fail/unkown_current_version.json +--- +{ + "apiVersion": "apiextensions.k8s.io/v1", + "kind": "ConversionReview", + "response": { + "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", + "result": { + "status": "Failure", + "code": 400, + "message": "failed to parse object: encountered unknown object API version \"test.stackable.tech/v99\"", + "reason": "failed to parse object: encountered unknown object API version \"test.stackable.tech/v99\"" + }, + "convertedObjects": [] + } +} diff --git a/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@unkown_desired_version.json.snap b/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@unkown_desired_version.json.snap new file mode 100644 index 000000000..9a99786ae --- /dev/null +++ b/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@unkown_desired_version.json.snap @@ -0,0 +1,19 @@ +--- +source: crates/stackable-versioned/src/tests.rs +expression: formatted +input_file: crates/stackable-versioned/fixtures/inputs/fail/unkown_desired_version.json +--- +{ + "apiVersion": "apiextensions.k8s.io/v1", + "kind": "ConversionReview", + "response": { + "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", + "result": { + "status": "Failure", + "code": 400, + "message": "unknown desired API version \"test.stackable.tech/v99\"", + "reason": "unknown desired API version \"test.stackable.tech/v99\"" + }, + "convertedObjects": [] + } +} diff --git a/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@unparseable_missing_field.json.snap b/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@unparseable_missing_field.json.snap new file mode 100644 index 000000000..4697cab9c --- /dev/null +++ b/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@unparseable_missing_field.json.snap @@ -0,0 +1,19 @@ +--- +source: crates/stackable-versioned/src/tests.rs +expression: formatted +input_file: crates/stackable-versioned/fixtures/inputs/fail/unparseable_missing_field.json +--- +{ + "apiVersion": "apiextensions.k8s.io/v1", + "kind": "ConversionReview", + "response": { + "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", + "result": { + "status": "Failure", + "code": 400, + "message": "failed to parse object: failed to deserialize object from JSON: missing field `username`", + "reason": "failed to parse object: failed to deserialize object from JSON: missing field `username`" + }, + "convertedObjects": [] + } +} diff --git a/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@wrong_kind.json.snap.new b/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@wrong_kind.json.snap.new new file mode 100644 index 000000000..1afa10a64 --- /dev/null +++ b/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@wrong_kind.json.snap.new @@ -0,0 +1,33 @@ +--- +source: crates/stackable-versioned/src/tests.rs +assertion_line: 117 +expression: formatted +input_file: crates/stackable-versioned/fixtures/inputs/fail/wrong_kind.json +--- +{ + "apiVersion": "apiextensions.k8s.io/v1", + "kind": "ConversionReview", + "response": { + "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", + "result": { + "status": "Success" + }, + "convertedObjects": [ + { + "apiVersion": "test.stackable.tech/v3", + "kind": "Person", + "metadata": { + "name": "sbernauer", + "namespace": "default", + "uid": "d41e2019-5de3-409c-a7b2-0799ecb95e4b" + }, + "spec": { + "firstName": "", + "gender": "Unknown", + "lastName": "", + "username": "sbernauer" + } + } + ] + } +} diff --git a/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__pass@persons_to_v1alpha1.json.snap b/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__pass@persons_to_v1alpha1.json.snap new file mode 100644 index 000000000..0f0099b09 --- /dev/null +++ b/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__pass@persons_to_v1alpha1.json.snap @@ -0,0 +1,61 @@ +--- +source: crates/stackable-versioned/src/tests.rs +expression: formatted +input_file: crates/stackable-versioned/fixtures/inputs/pass/persons_to_v1alpha1.json +--- +{ + "apiVersion": "apiextensions.k8s.io/v1", + "kind": "ConversionReview", + "response": { + "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", + "result": { + "status": "Success" + }, + "convertedObjects": [ + { + "apiVersion": "test.stackable.tech/v1alpha1", + "kind": "Person", + "metadata": { + "name": "sbernauer", + "namespace": "default", + "uid": "d41e2019-5de3-409c-a7b2-0799ecb95e4b" + }, + "spec": { + "username": "sbernauer" + } + }, + { + "apiVersion": "test.stackable.tech/v1alpha1", + "kind": "Person", + "metadata": {}, + "spec": { + "username": "sbernauer" + } + }, + { + "apiVersion": "test.stackable.tech/v1alpha1", + "kind": "Person", + "metadata": {}, + "spec": { + "username": "sbernauer" + } + }, + { + "apiVersion": "test.stackable.tech/v1alpha1", + "kind": "Person", + "metadata": {}, + "spec": { + "username": "sbernauer" + } + }, + { + "apiVersion": "test.stackable.tech/v1alpha1", + "kind": "Person", + "metadata": {}, + "spec": { + "username": "sbernauer" + } + } + ] + } +} diff --git a/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__pass@persons_to_v3.json.snap b/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__pass@persons_to_v3.json.snap new file mode 100644 index 000000000..348394e86 --- /dev/null +++ b/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__pass@persons_to_v3.json.snap @@ -0,0 +1,76 @@ +--- +source: crates/stackable-versioned/src/tests.rs +expression: formatted +input_file: crates/stackable-versioned/fixtures/inputs/pass/persons_to_v3.json +--- +{ + "apiVersion": "apiextensions.k8s.io/v1", + "kind": "ConversionReview", + "response": { + "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", + "result": { + "status": "Success" + }, + "convertedObjects": [ + { + "apiVersion": "test.stackable.tech/v3", + "kind": "Person", + "metadata": { + "name": "sbernauer", + "namespace": "default", + "uid": "d41e2019-5de3-409c-a7b2-0799ecb95e4b" + }, + "spec": { + "firstName": "", + "gender": "Unknown", + "lastName": "", + "username": "sbernauer" + } + }, + { + "apiVersion": "test.stackable.tech/v3", + "kind": "Person", + "metadata": {}, + "spec": { + "firstName": "Sebastian", + "gender": "Unknown", + "lastName": "Bernauer", + "username": "sbernauer" + } + }, + { + "apiVersion": "test.stackable.tech/v3", + "kind": "Person", + "metadata": {}, + "spec": { + "firstName": "Sebastian", + "gender": "Unknown", + "lastName": "Bernauer", + "username": "sbernauer" + } + }, + { + "apiVersion": "test.stackable.tech/v3", + "kind": "Person", + "metadata": {}, + "spec": { + "firstName": "Sebastian", + "gender": "Male", + "lastName": "Bernauer", + "username": "sbernauer" + } + }, + { + "apiVersion": "test.stackable.tech/v3", + "kind": "Person", + "metadata": {}, + "spec": { + "firstName": "Sebastian", + "gender": "Male", + "lastName": "Bernauer", + "username": "sbernauer" + } + } + ] + } +} diff --git a/crates/stackable-versioned/src/tests.rs b/crates/stackable-versioned/src/tests.rs new file mode 100644 index 000000000..9e2516b97 --- /dev/null +++ b/crates/stackable-versioned/src/tests.rs @@ -0,0 +1,142 @@ +use kube::CustomResource; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use stackable_versioned_macros::versioned; + +#[versioned( + k8s(group = "test.stackable.tech", crates(versioned = "crate")), + version(name = "v1alpha1"), + version(name = "v1alpha2"), + version(name = "v1beta1"), + version(name = "v2"), + version(name = "v3") +)] +#[derive( + Clone, + Debug, + Eq, + Hash, + Ord, + PartialEq, + PartialOrd, + CustomResource, + Deserialize, + JsonSchema, + Serialize, +)] +#[serde(rename_all = "camelCase")] +struct PersonSpec { + username: String, + + // In v1alpha2 first and last name have been added + #[versioned(added(since = "v1alpha2"))] + first_name: String, + #[versioned(added(since = "v1alpha2"))] + last_name: String, + + // We started out with a enum. As we *need* to provide a default, we have a Unknown variant. + // Afterwards we figured let's be more flexible and accept any arbitrary String. + #[versioned( + added(since = "v2", default = "default_gender"), + changed(since = "v3", from_type = "Gender") + )] + gender: String, +} + +fn default_gender() -> Gender { + Gender::Unknown +} + +#[derive( + Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Deserialize, JsonSchema, Serialize, +)] +#[serde(rename_all = "PascalCase")] +pub enum Gender { + Unknown, + Male, + Female, +} + +impl Into for Gender { + fn into(self) -> String { + match self { + Gender::Unknown => "Unknown".to_string(), + Gender::Male => "Male".to_string(), + Gender::Female => "Female".to_string(), + } + } +} +impl From for Gender { + fn from(value: String) -> Self { + match value.as_str() { + "Male" => Self::Male, + "Female" => Self::Female, + _ => Self::Unknown, + } + } +} + +#[cfg(test)] +mod tests { + use std::{fs::File, path::Path}; + + use insta::{assert_snapshot, glob}; + use kube::core::{conversion::ConversionReview, response::StatusSummary}; + + use super::Person; + + #[test] + fn pass() { + glob!("../fixtures/inputs/pass/", "*.json", |path| { + let (request, response) = run_for_file(path); + + let formatted = serde_json::to_string_pretty(&response) + .expect("Failed to serialize ConversionResponse"); + assert_snapshot!(formatted); + + let response = response + .response + .expect("ConversionReview had no response!"); + + assert_eq!( + response.result.status, + Some(StatusSummary::Success), + "File {path:?} should be converted successfully" + ); + assert_eq!(request.request.unwrap().uid, response.uid); + }) + } + + #[test] + fn fail() { + glob!("../fixtures/inputs/fail/", "*.json", |path| { + let (request, response) = run_for_file(path); + + let formatted = serde_json::to_string_pretty(&response) + .expect("Failed to serialize ConversionResponse"); + assert_snapshot!(formatted); + + let response = response + .response + .expect("ConversionReview had no response!"); + + assert_eq!( + response.result.status, + Some(StatusSummary::Failure), + "File {path:?} should *not* be converted successfully" + ); + if let Some(request) = &request.request { + assert_eq!(request.uid, response.uid); + } + }) + } + + fn run_for_file(path: &Path) -> (ConversionReview, ConversionReview) { + let request: ConversionReview = + serde_json::from_reader(File::open(path).expect("failed to open test file")) + .expect("failed to parse ConversionReview from test file"); + let response = Person::try_convert(request.clone()); + + (request, response) + } +} From 35f1a8f74f52267f3631a83c45362341150192a7 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Tue, 17 Jun 2025 17:37:59 +0200 Subject: [PATCH 02/33] formatting --- .../src/codegen/container/struct/k8s.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 521d3ce9d..2e87a3f84 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -187,7 +187,7 @@ impl Struct { let object = match api_version { #(#api_versions => { - let object = #serde_json_path::from_value(value) + let object = #serde_json_path::from_value(value) .map_err(|source| #parse_object_error::Deserialize { source })?; Self::#variant_idents(object) From 41776eb13454b74b7a239251acbdfabe49b76382 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Mon, 23 Jun 2025 10:33:09 +0200 Subject: [PATCH 03/33] Move tests into dedicated folder --- ...ests__tests__fail@wrong_kind.json.snap.new | 33 ------------------- .../src/{tests.rs => tests/mod.rs} | 4 +-- ...sts__tests__fail@request_missing.json.snap | 2 +- ...sts__fail@unkown_current_version.json.snap | 2 +- ...sts__fail@unkown_desired_version.json.snap | 2 +- ...__fail@unparseable_missing_field.json.snap | 2 +- ..._tests__pass@persons_to_v1alpha1.json.snap | 2 +- ...tests__tests__pass@persons_to_v3.json.snap | 2 +- 8 files changed, 8 insertions(+), 41 deletions(-) delete mode 100644 crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@wrong_kind.json.snap.new rename crates/stackable-versioned/src/{tests.rs => tests/mod.rs} (96%) rename crates/stackable-versioned/src/{ => tests}/snapshots/stackable_versioned__tests__tests__fail@request_missing.json.snap (89%) rename crates/stackable-versioned/src/{ => tests}/snapshots/stackable_versioned__tests__tests__fail@unkown_current_version.json.snap (91%) rename crates/stackable-versioned/src/{ => tests}/snapshots/stackable_versioned__tests__tests__fail@unkown_desired_version.json.snap (90%) rename crates/stackable-versioned/src/{ => tests}/snapshots/stackable_versioned__tests__tests__fail@unparseable_missing_field.json.snap (91%) rename crates/stackable-versioned/src/{ => tests}/snapshots/stackable_versioned__tests__tests__pass@persons_to_v1alpha1.json.snap (96%) rename crates/stackable-versioned/src/{ => tests}/snapshots/stackable_versioned__tests__tests__pass@persons_to_v3.json.snap (97%) diff --git a/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@wrong_kind.json.snap.new b/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@wrong_kind.json.snap.new deleted file mode 100644 index 1afa10a64..000000000 --- a/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@wrong_kind.json.snap.new +++ /dev/null @@ -1,33 +0,0 @@ ---- -source: crates/stackable-versioned/src/tests.rs -assertion_line: 117 -expression: formatted -input_file: crates/stackable-versioned/fixtures/inputs/fail/wrong_kind.json ---- -{ - "apiVersion": "apiextensions.k8s.io/v1", - "kind": "ConversionReview", - "response": { - "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", - "result": { - "status": "Success" - }, - "convertedObjects": [ - { - "apiVersion": "test.stackable.tech/v3", - "kind": "Person", - "metadata": { - "name": "sbernauer", - "namespace": "default", - "uid": "d41e2019-5de3-409c-a7b2-0799ecb95e4b" - }, - "spec": { - "firstName": "", - "gender": "Unknown", - "lastName": "", - "username": "sbernauer" - } - } - ] - } -} diff --git a/crates/stackable-versioned/src/tests.rs b/crates/stackable-versioned/src/tests/mod.rs similarity index 96% rename from crates/stackable-versioned/src/tests.rs rename to crates/stackable-versioned/src/tests/mod.rs index 9e2516b97..a03101897 100644 --- a/crates/stackable-versioned/src/tests.rs +++ b/crates/stackable-versioned/src/tests/mod.rs @@ -87,7 +87,7 @@ mod tests { #[test] fn pass() { - glob!("../fixtures/inputs/pass/", "*.json", |path| { + glob!("../../fixtures/inputs/pass/", "*.json", |path| { let (request, response) = run_for_file(path); let formatted = serde_json::to_string_pretty(&response) @@ -109,7 +109,7 @@ mod tests { #[test] fn fail() { - glob!("../fixtures/inputs/fail/", "*.json", |path| { + glob!("../../fixtures/inputs/fail/", "*.json", |path| { let (request, response) = run_for_file(path); let formatted = serde_json::to_string_pretty(&response) diff --git a/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@request_missing.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@request_missing.json.snap similarity index 89% rename from crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@request_missing.json.snap rename to crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@request_missing.json.snap index 1e3c4016a..fc0696d80 100644 --- a/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@request_missing.json.snap +++ b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@request_missing.json.snap @@ -1,5 +1,5 @@ --- -source: crates/stackable-versioned/src/tests.rs +source: crates/stackable-versioned/src/tests/mod.rs expression: formatted input_file: crates/stackable-versioned/fixtures/inputs/fail/request_missing.json --- diff --git a/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@unkown_current_version.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@unkown_current_version.json.snap similarity index 91% rename from crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@unkown_current_version.json.snap rename to crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@unkown_current_version.json.snap index 77a7e15ce..758e01037 100644 --- a/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@unkown_current_version.json.snap +++ b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@unkown_current_version.json.snap @@ -1,5 +1,5 @@ --- -source: crates/stackable-versioned/src/tests.rs +source: crates/stackable-versioned/src/tests/mod.rs expression: formatted input_file: crates/stackable-versioned/fixtures/inputs/fail/unkown_current_version.json --- diff --git a/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@unkown_desired_version.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@unkown_desired_version.json.snap similarity index 90% rename from crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@unkown_desired_version.json.snap rename to crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@unkown_desired_version.json.snap index 9a99786ae..9bc5c161b 100644 --- a/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@unkown_desired_version.json.snap +++ b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@unkown_desired_version.json.snap @@ -1,5 +1,5 @@ --- -source: crates/stackable-versioned/src/tests.rs +source: crates/stackable-versioned/src/tests/mod.rs expression: formatted input_file: crates/stackable-versioned/fixtures/inputs/fail/unkown_desired_version.json --- diff --git a/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@unparseable_missing_field.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@unparseable_missing_field.json.snap similarity index 91% rename from crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@unparseable_missing_field.json.snap rename to crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@unparseable_missing_field.json.snap index 4697cab9c..abd7c721a 100644 --- a/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__fail@unparseable_missing_field.json.snap +++ b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@unparseable_missing_field.json.snap @@ -1,5 +1,5 @@ --- -source: crates/stackable-versioned/src/tests.rs +source: crates/stackable-versioned/src/tests/mod.rs expression: formatted input_file: crates/stackable-versioned/fixtures/inputs/fail/unparseable_missing_field.json --- diff --git a/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__pass@persons_to_v1alpha1.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__pass@persons_to_v1alpha1.json.snap similarity index 96% rename from crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__pass@persons_to_v1alpha1.json.snap rename to crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__pass@persons_to_v1alpha1.json.snap index 0f0099b09..717977035 100644 --- a/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__pass@persons_to_v1alpha1.json.snap +++ b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__pass@persons_to_v1alpha1.json.snap @@ -1,5 +1,5 @@ --- -source: crates/stackable-versioned/src/tests.rs +source: crates/stackable-versioned/src/tests/mod.rs expression: formatted input_file: crates/stackable-versioned/fixtures/inputs/pass/persons_to_v1alpha1.json --- diff --git a/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__pass@persons_to_v3.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__pass@persons_to_v3.json.snap similarity index 97% rename from crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__pass@persons_to_v3.json.snap rename to crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__pass@persons_to_v3.json.snap index 348394e86..e7d5b2a26 100644 --- a/crates/stackable-versioned/src/snapshots/stackable_versioned__tests__tests__pass@persons_to_v3.json.snap +++ b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__pass@persons_to_v3.json.snap @@ -1,5 +1,5 @@ --- -source: crates/stackable-versioned/src/tests.rs +source: crates/stackable-versioned/src/tests/mod.rs expression: formatted input_file: crates/stackable-versioned/fixtures/inputs/pass/persons_to_v3.json --- From ca11c44bc888259001c6d218b88942214a7b893b Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Mon, 23 Jun 2025 10:35:14 +0200 Subject: [PATCH 04/33] move fixtures --- .../{ => src/tests}/fixtures/inputs/fail/request_missing.json | 0 .../tests}/fixtures/inputs/fail/unkown_current_version.json | 0 .../tests}/fixtures/inputs/fail/unkown_desired_version.json | 0 .../fixtures/inputs/fail/unparseable_missing_field.json | 0 .../{ => src/tests}/fixtures/inputs/fail/wrong_kind.json | 0 .../tests}/fixtures/inputs/pass/persons_to_v1alpha1.json | 0 .../{ => src/tests}/fixtures/inputs/pass/persons_to_v3.json | 0 crates/stackable-versioned/src/tests/mod.rs | 4 ++-- 8 files changed, 2 insertions(+), 2 deletions(-) rename crates/stackable-versioned/{ => src/tests}/fixtures/inputs/fail/request_missing.json (100%) rename crates/stackable-versioned/{ => src/tests}/fixtures/inputs/fail/unkown_current_version.json (100%) rename crates/stackable-versioned/{ => src/tests}/fixtures/inputs/fail/unkown_desired_version.json (100%) rename crates/stackable-versioned/{ => src/tests}/fixtures/inputs/fail/unparseable_missing_field.json (100%) rename crates/stackable-versioned/{ => src/tests}/fixtures/inputs/fail/wrong_kind.json (100%) rename crates/stackable-versioned/{ => src/tests}/fixtures/inputs/pass/persons_to_v1alpha1.json (100%) rename crates/stackable-versioned/{ => src/tests}/fixtures/inputs/pass/persons_to_v3.json (100%) diff --git a/crates/stackable-versioned/fixtures/inputs/fail/request_missing.json b/crates/stackable-versioned/src/tests/fixtures/inputs/fail/request_missing.json similarity index 100% rename from crates/stackable-versioned/fixtures/inputs/fail/request_missing.json rename to crates/stackable-versioned/src/tests/fixtures/inputs/fail/request_missing.json diff --git a/crates/stackable-versioned/fixtures/inputs/fail/unkown_current_version.json b/crates/stackable-versioned/src/tests/fixtures/inputs/fail/unkown_current_version.json similarity index 100% rename from crates/stackable-versioned/fixtures/inputs/fail/unkown_current_version.json rename to crates/stackable-versioned/src/tests/fixtures/inputs/fail/unkown_current_version.json diff --git a/crates/stackable-versioned/fixtures/inputs/fail/unkown_desired_version.json b/crates/stackable-versioned/src/tests/fixtures/inputs/fail/unkown_desired_version.json similarity index 100% rename from crates/stackable-versioned/fixtures/inputs/fail/unkown_desired_version.json rename to crates/stackable-versioned/src/tests/fixtures/inputs/fail/unkown_desired_version.json diff --git a/crates/stackable-versioned/fixtures/inputs/fail/unparseable_missing_field.json b/crates/stackable-versioned/src/tests/fixtures/inputs/fail/unparseable_missing_field.json similarity index 100% rename from crates/stackable-versioned/fixtures/inputs/fail/unparseable_missing_field.json rename to crates/stackable-versioned/src/tests/fixtures/inputs/fail/unparseable_missing_field.json diff --git a/crates/stackable-versioned/fixtures/inputs/fail/wrong_kind.json b/crates/stackable-versioned/src/tests/fixtures/inputs/fail/wrong_kind.json similarity index 100% rename from crates/stackable-versioned/fixtures/inputs/fail/wrong_kind.json rename to crates/stackable-versioned/src/tests/fixtures/inputs/fail/wrong_kind.json diff --git a/crates/stackable-versioned/fixtures/inputs/pass/persons_to_v1alpha1.json b/crates/stackable-versioned/src/tests/fixtures/inputs/pass/persons_to_v1alpha1.json similarity index 100% rename from crates/stackable-versioned/fixtures/inputs/pass/persons_to_v1alpha1.json rename to crates/stackable-versioned/src/tests/fixtures/inputs/pass/persons_to_v1alpha1.json diff --git a/crates/stackable-versioned/fixtures/inputs/pass/persons_to_v3.json b/crates/stackable-versioned/src/tests/fixtures/inputs/pass/persons_to_v3.json similarity index 100% rename from crates/stackable-versioned/fixtures/inputs/pass/persons_to_v3.json rename to crates/stackable-versioned/src/tests/fixtures/inputs/pass/persons_to_v3.json diff --git a/crates/stackable-versioned/src/tests/mod.rs b/crates/stackable-versioned/src/tests/mod.rs index a03101897..228efe44c 100644 --- a/crates/stackable-versioned/src/tests/mod.rs +++ b/crates/stackable-versioned/src/tests/mod.rs @@ -87,7 +87,7 @@ mod tests { #[test] fn pass() { - glob!("../../fixtures/inputs/pass/", "*.json", |path| { + glob!("./fixtures/inputs/pass/", "*.json", |path| { let (request, response) = run_for_file(path); let formatted = serde_json::to_string_pretty(&response) @@ -109,7 +109,7 @@ mod tests { #[test] fn fail() { - glob!("../../fixtures/inputs/fail/", "*.json", |path| { + glob!("./fixtures/inputs/fail/", "*.json", |path| { let (request, response) = run_for_file(path); let formatted = serde_json::to_string_pretty(&response) From db2f65cf77a42b427f23f9be30dbedc50e72c22f Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Mon, 23 Jun 2025 11:16:20 +0200 Subject: [PATCH 05/33] Check Kind of send object --- .../src/codegen/container/struct/k8s.rs | 23 +++- ..._macros__snapshot_tests__k8s@basic.rs.snap | 61 +++++++-- ...hot_tests__k8s@conversion_tracking.rs.snap | 61 +++++++-- ...napshot_tests__k8s@crate_overrides.rs.snap | 61 +++++++-- ...macros__snapshot_tests__k8s@module.rs.snap | 122 ++++++++++++++---- ...napshot_tests__k8s@module_preserve.rs.snap | 122 ++++++++++++++---- ...__snapshot_tests__k8s@renamed_kind.rs.snap | 61 +++++++-- ...os__snapshot_tests__k8s@shortnames.rs.snap | 41 +++++- crates/stackable-versioned/src/k8s.rs | 16 ++- ...d__tests__tests__fail@wrong_kind.json.snap | 19 +++ 10 files changed, 481 insertions(+), 106 deletions(-) create mode 100644 crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@wrong_kind.json.snap 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 2e87a3f84..93346ab47 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -181,9 +181,9 @@ impl Struct { fn from_json_value(value: #serde_json_path::Value) -> ::std::result::Result { let api_version = value .get("apiVersion") - .ok_or_else(|| #parse_object_error::FieldNotPresent)? + .ok_or_else(|| #parse_object_error::FieldMissing{ field: "apiVersion".to_string() })? .as_str() - .ok_or_else(|| #parse_object_error::FieldNotStr)?; + .ok_or_else(|| #parse_object_error::FieldNotStr{ field: "apiVersion".to_string() })?; let object = match api_version { #(#api_versions => { @@ -321,6 +321,7 @@ impl Struct { let versioned_path = &*kubernetes_arguments.crates.versioned; let kube_core_path = &*kubernetes_arguments.crates.kube_core; + let parse_object_error = quote! { #versioned_path::ParseObjectError }; let convert_object_error = quote! { #versioned_path::ConvertObjectError }; // Generate conversion paths and the match arms for these paths @@ -431,6 +432,24 @@ impl Struct { let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { + let object_kind = object + .get("kind") + .ok_or_else(|| #convert_object_error::Parse { + source: #parse_object_error::FieldMissing{ field: "kind".to_string() } + })? + .as_str() + .ok_or_else(|| #convert_object_error::Parse { + source: #parse_object_error::FieldNotStr{ field: "kind".to_string() } + })?; + if object_kind != stringify!(#struct_ident) { + return Err(#convert_object_error::Parse { + source: #parse_object_error::WrongObjectKind{ + kind: object_kind.to_string(), + supported_kind: stringify!(#struct_ident).to_string(), + } + }) + } + // This clone is required because in the noop case we move the object into // the converted objects vec. let current_object = Self::from_json_value(object.clone()) 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 24b00a58d..80de747ee 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 @@ -202,12 +202,33 @@ impl Foo { > { let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { + let object_kind = object + .get("kind") + .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::FieldMissing { + field: "kind".to_string(), + }, + })? + .as_str() + .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "kind".to_string(), + }, + })?; + if object_kind != stringify!(Foo) { + return Err(::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::WrongObjectKind { + kind: object_kind.to_string(), + supported_kind: stringify!(Foo).to_string(), + }, + }); + } let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; match (current_object, desired_api_version) { - (Self::V1Alpha1(__sv_foo), "v1beta1") => { + (Self::V1Alpha1(__sv_foo), "stackable.tech/v1beta1") => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Beta1(v1beta1::Foo { metadata: __sv_foo.metadata, @@ -221,7 +242,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(__sv_foo), "v1") => { + (Self::V1Alpha1(__sv_foo), "stackable.tech/v1") => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let converted: v1::FooSpec = converted.into(); let desired_object = Self::V1(v1::Foo { @@ -236,7 +257,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Beta1(__sv_foo), "v1alpha1") => { + (Self::V1Beta1(__sv_foo), "stackable.tech/v1alpha1") => { let converted: v1alpha1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Alpha1(v1alpha1::Foo { metadata: __sv_foo.metadata, @@ -250,7 +271,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Beta1(__sv_foo), "v1") => { + (Self::V1Beta1(__sv_foo), "stackable.tech/v1") => { let converted: v1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1(v1::Foo { metadata: __sv_foo.metadata, @@ -264,7 +285,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foo), "v1alpha1") => { + (Self::V1(__sv_foo), "stackable.tech/v1alpha1") => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let converted: v1alpha1::FooSpec = converted.into(); let desired_object = Self::V1Alpha1(v1alpha1::Foo { @@ -279,7 +300,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foo), "v1beta1") => { + (Self::V1(__sv_foo), "stackable.tech/v1beta1") => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Beta1(v1beta1::Foo { metadata: __sv_foo.metadata, @@ -293,7 +314,19 @@ impl Foo { })?; converted_objects.push(desired_object); } - _ => converted_objects.push(object), + (Self::V1Alpha1(_), "stackable.tech/v1alpha1") => { + converted_objects.push(object) + } + (Self::V1Beta1(_), "stackable.tech/v1beta1") => { + converted_objects.push(object) + } + (Self::V1(_), "stackable.tech/v1") => converted_objects.push(object), + (_, unknown_desired_api_version) => { + return ::std::result::Result::Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { + unknown_desired_api_version: unknown_desired_api_version + .to_string(), + }); + } } } ::std::result::Result::Ok(converted_objects) @@ -303,25 +336,29 @@ impl Foo { ) -> ::std::result::Result { let api_version = value .get("apiVersion") - .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotPresent)? + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { + field: "apiVersion".to_string(), + })? .as_str() - .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr)?; + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "apiVersion".to_string(), + })?; let object = match api_version { - "stackable.tech/v1alpha1" | "v1alpha1" => { + "stackable.tech/v1alpha1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } - "stackable.tech/v1beta1" | "v1beta1" => { + "stackable.tech/v1beta1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Beta1(object) } - "stackable.tech/v1" | "v1" => { + "stackable.tech/v1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, 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 9b72f1188..1946c3be3 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 @@ -172,12 +172,33 @@ impl Foo { > { let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { + let object_kind = object + .get("kind") + .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::FieldMissing { + field: "kind".to_string(), + }, + })? + .as_str() + .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "kind".to_string(), + }, + })?; + if object_kind != stringify!(Foo) { + return Err(::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::WrongObjectKind { + kind: object_kind.to_string(), + supported_kind: stringify!(Foo).to_string(), + }, + }); + } let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; match (current_object, desired_api_version) { - (Self::V1Alpha1(__sv_foo), "v1beta1") => { + (Self::V1Alpha1(__sv_foo), "stackable.tech/v1beta1") => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Beta1(v1beta1::Foo { metadata: __sv_foo.metadata, @@ -191,7 +212,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(__sv_foo), "v1") => { + (Self::V1Alpha1(__sv_foo), "stackable.tech/v1") => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let converted: v1::FooSpec = converted.into(); let desired_object = Self::V1(v1::Foo { @@ -206,7 +227,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Beta1(__sv_foo), "v1alpha1") => { + (Self::V1Beta1(__sv_foo), "stackable.tech/v1alpha1") => { let converted: v1alpha1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Alpha1(v1alpha1::Foo { metadata: __sv_foo.metadata, @@ -220,7 +241,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Beta1(__sv_foo), "v1") => { + (Self::V1Beta1(__sv_foo), "stackable.tech/v1") => { let converted: v1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1(v1::Foo { metadata: __sv_foo.metadata, @@ -234,7 +255,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foo), "v1alpha1") => { + (Self::V1(__sv_foo), "stackable.tech/v1alpha1") => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let converted: v1alpha1::FooSpec = converted.into(); let desired_object = Self::V1Alpha1(v1alpha1::Foo { @@ -249,7 +270,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foo), "v1beta1") => { + (Self::V1(__sv_foo), "stackable.tech/v1beta1") => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Beta1(v1beta1::Foo { metadata: __sv_foo.metadata, @@ -263,7 +284,19 @@ impl Foo { })?; converted_objects.push(desired_object); } - _ => converted_objects.push(object), + (Self::V1Alpha1(_), "stackable.tech/v1alpha1") => { + converted_objects.push(object) + } + (Self::V1Beta1(_), "stackable.tech/v1beta1") => { + converted_objects.push(object) + } + (Self::V1(_), "stackable.tech/v1") => converted_objects.push(object), + (_, unknown_desired_api_version) => { + return ::std::result::Result::Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { + unknown_desired_api_version: unknown_desired_api_version + .to_string(), + }); + } } } ::std::result::Result::Ok(converted_objects) @@ -273,25 +306,29 @@ impl Foo { ) -> ::std::result::Result { let api_version = value .get("apiVersion") - .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotPresent)? + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { + field: "apiVersion".to_string(), + })? .as_str() - .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr)?; + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "apiVersion".to_string(), + })?; let object = match api_version { - "stackable.tech/v1alpha1" | "v1alpha1" => { + "stackable.tech/v1alpha1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } - "stackable.tech/v1beta1" | "v1beta1" => { + "stackable.tech/v1beta1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Beta1(object) } - "stackable.tech/v1" | "v1" => { + "stackable.tech/v1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, 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 3853ad39f..0f3c86acd 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 @@ -193,12 +193,33 @@ impl Foo { > { let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { + let object_kind = object + .get("kind") + .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::FieldMissing { + field: "kind".to_string(), + }, + })? + .as_str() + .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "kind".to_string(), + }, + })?; + if object_kind != stringify!(Foo) { + return Err(::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::WrongObjectKind { + kind: object_kind.to_string(), + supported_kind: stringify!(Foo).to_string(), + }, + }); + } let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; match (current_object, desired_api_version) { - (Self::V1Alpha1(__sv_foo), "v1beta1") => { + (Self::V1Alpha1(__sv_foo), "foo.example.org/v1beta1") => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Beta1(v1beta1::Foo { metadata: __sv_foo.metadata, @@ -211,7 +232,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(__sv_foo), "v1") => { + (Self::V1Alpha1(__sv_foo), "foo.example.org/v1") => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let converted: v1::FooSpec = converted.into(); let desired_object = Self::V1(v1::Foo { @@ -225,7 +246,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Beta1(__sv_foo), "v1alpha1") => { + (Self::V1Beta1(__sv_foo), "foo.example.org/v1alpha1") => { let converted: v1alpha1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Alpha1(v1alpha1::Foo { metadata: __sv_foo.metadata, @@ -238,7 +259,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Beta1(__sv_foo), "v1") => { + (Self::V1Beta1(__sv_foo), "foo.example.org/v1") => { let converted: v1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1(v1::Foo { metadata: __sv_foo.metadata, @@ -251,7 +272,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foo), "v1alpha1") => { + (Self::V1(__sv_foo), "foo.example.org/v1alpha1") => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let converted: v1alpha1::FooSpec = converted.into(); let desired_object = Self::V1Alpha1(v1alpha1::Foo { @@ -265,7 +286,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foo), "v1beta1") => { + (Self::V1(__sv_foo), "foo.example.org/v1beta1") => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Beta1(v1beta1::Foo { metadata: __sv_foo.metadata, @@ -278,7 +299,19 @@ impl Foo { })?; converted_objects.push(desired_object); } - _ => converted_objects.push(object), + (Self::V1Alpha1(_), "foo.example.org/v1alpha1") => { + converted_objects.push(object) + } + (Self::V1Beta1(_), "foo.example.org/v1beta1") => { + converted_objects.push(object) + } + (Self::V1(_), "foo.example.org/v1") => converted_objects.push(object), + (_, unknown_desired_api_version) => { + return ::std::result::Result::Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { + unknown_desired_api_version: unknown_desired_api_version + .to_string(), + }); + } } } ::std::result::Result::Ok(converted_objects) @@ -288,25 +321,29 @@ impl Foo { ) -> ::std::result::Result { let api_version = value .get("apiVersion") - .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotPresent)? + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { + field: "apiVersion".to_string(), + })? .as_str() - .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr)?; + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "apiVersion".to_string(), + })?; let object = match api_version { - "foo.example.org/v1alpha1" | "v1alpha1" => { + "foo.example.org/v1alpha1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } - "foo.example.org/v1beta1" | "v1beta1" => { + "foo.example.org/v1beta1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Beta1(object) } - "foo.example.org/v1" | "v1" => { + "foo.example.org/v1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, 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 d63333e70..b766238a7 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 @@ -365,12 +365,33 @@ impl Foo { > { let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { + let object_kind = object + .get("kind") + .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::FieldMissing { + field: "kind".to_string(), + }, + })? + .as_str() + .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "kind".to_string(), + }, + })?; + if object_kind != stringify!(Foo) { + return Err(::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::WrongObjectKind { + kind: object_kind.to_string(), + supported_kind: stringify!(Foo).to_string(), + }, + }); + } let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; match (current_object, desired_api_version) { - (Self::V1Alpha1(__sv_foo), "v1") => { + (Self::V1Alpha1(__sv_foo), "foo.example.org/v1") => { let converted: v1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1(v1::Foo { metadata: __sv_foo.metadata, @@ -383,7 +404,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(__sv_foo), "v2alpha1") => { + (Self::V1Alpha1(__sv_foo), "foo.example.org/v2alpha1") => { let converted: v1::FooSpec = __sv_foo.spec.into(); let converted: v2alpha1::FooSpec = converted.into(); let desired_object = Self::V2Alpha1(v2alpha1::Foo { @@ -397,7 +418,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foo), "v1alpha1") => { + (Self::V1(__sv_foo), "foo.example.org/v1alpha1") => { let converted: v1alpha1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Alpha1(v1alpha1::Foo { metadata: __sv_foo.metadata, @@ -410,7 +431,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foo), "v2alpha1") => { + (Self::V1(__sv_foo), "foo.example.org/v2alpha1") => { let converted: v2alpha1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V2Alpha1(v2alpha1::Foo { metadata: __sv_foo.metadata, @@ -423,7 +444,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V2Alpha1(__sv_foo), "v1alpha1") => { + (Self::V2Alpha1(__sv_foo), "foo.example.org/v1alpha1") => { let converted: v1::FooSpec = __sv_foo.spec.into(); let converted: v1alpha1::FooSpec = converted.into(); let desired_object = Self::V1Alpha1(v1alpha1::Foo { @@ -437,7 +458,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V2Alpha1(__sv_foo), "v1") => { + (Self::V2Alpha1(__sv_foo), "foo.example.org/v1") => { let converted: v1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1(v1::Foo { metadata: __sv_foo.metadata, @@ -450,7 +471,19 @@ impl Foo { })?; converted_objects.push(desired_object); } - _ => converted_objects.push(object), + (Self::V1Alpha1(_), "foo.example.org/v1alpha1") => { + converted_objects.push(object) + } + (Self::V1(_), "foo.example.org/v1") => converted_objects.push(object), + (Self::V2Alpha1(_), "foo.example.org/v2alpha1") => { + converted_objects.push(object) + } + (_, unknown_desired_api_version) => { + return ::std::result::Result::Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { + unknown_desired_api_version: unknown_desired_api_version + .to_string(), + }); + } } } ::std::result::Result::Ok(converted_objects) @@ -460,25 +493,29 @@ impl Foo { ) -> ::std::result::Result { let api_version = value .get("apiVersion") - .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotPresent)? + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { + field: "apiVersion".to_string(), + })? .as_str() - .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr)?; + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "apiVersion".to_string(), + })?; let object = match api_version { - "foo.example.org/v1alpha1" | "v1alpha1" => { + "foo.example.org/v1alpha1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } - "foo.example.org/v1" | "v1" => { + "foo.example.org/v1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1(object) } - "foo.example.org/v2alpha1" | "v2alpha1" => { + "foo.example.org/v2alpha1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, @@ -618,12 +655,33 @@ impl Bar { > { let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { + let object_kind = object + .get("kind") + .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::FieldMissing { + field: "kind".to_string(), + }, + })? + .as_str() + .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "kind".to_string(), + }, + })?; + if object_kind != stringify!(Bar) { + return Err(::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::WrongObjectKind { + kind: object_kind.to_string(), + supported_kind: stringify!(Bar).to_string(), + }, + }); + } let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; match (current_object, desired_api_version) { - (Self::V1Alpha1(__sv_bar), "v1") => { + (Self::V1Alpha1(__sv_bar), "bar.example.org/v1") => { let converted: v1::BarSpec = __sv_bar.spec.into(); let desired_object = Self::V1(v1::Bar { metadata: __sv_bar.metadata, @@ -636,7 +694,7 @@ impl Bar { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(__sv_bar), "v2alpha1") => { + (Self::V1Alpha1(__sv_bar), "bar.example.org/v2alpha1") => { let converted: v1::BarSpec = __sv_bar.spec.into(); let converted: v2alpha1::BarSpec = converted.into(); let desired_object = Self::V2Alpha1(v2alpha1::Bar { @@ -650,7 +708,7 @@ impl Bar { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_bar), "v1alpha1") => { + (Self::V1(__sv_bar), "bar.example.org/v1alpha1") => { let converted: v1alpha1::BarSpec = __sv_bar.spec.into(); let desired_object = Self::V1Alpha1(v1alpha1::Bar { metadata: __sv_bar.metadata, @@ -663,7 +721,7 @@ impl Bar { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_bar), "v2alpha1") => { + (Self::V1(__sv_bar), "bar.example.org/v2alpha1") => { let converted: v2alpha1::BarSpec = __sv_bar.spec.into(); let desired_object = Self::V2Alpha1(v2alpha1::Bar { metadata: __sv_bar.metadata, @@ -676,7 +734,7 @@ impl Bar { })?; converted_objects.push(desired_object); } - (Self::V2Alpha1(__sv_bar), "v1alpha1") => { + (Self::V2Alpha1(__sv_bar), "bar.example.org/v1alpha1") => { let converted: v1::BarSpec = __sv_bar.spec.into(); let converted: v1alpha1::BarSpec = converted.into(); let desired_object = Self::V1Alpha1(v1alpha1::Bar { @@ -690,7 +748,7 @@ impl Bar { })?; converted_objects.push(desired_object); } - (Self::V2Alpha1(__sv_bar), "v1") => { + (Self::V2Alpha1(__sv_bar), "bar.example.org/v1") => { let converted: v1::BarSpec = __sv_bar.spec.into(); let desired_object = Self::V1(v1::Bar { metadata: __sv_bar.metadata, @@ -703,7 +761,19 @@ impl Bar { })?; converted_objects.push(desired_object); } - _ => converted_objects.push(object), + (Self::V1Alpha1(_), "bar.example.org/v1alpha1") => { + converted_objects.push(object) + } + (Self::V1(_), "bar.example.org/v1") => converted_objects.push(object), + (Self::V2Alpha1(_), "bar.example.org/v2alpha1") => { + converted_objects.push(object) + } + (_, unknown_desired_api_version) => { + return ::std::result::Result::Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { + unknown_desired_api_version: unknown_desired_api_version + .to_string(), + }); + } } } ::std::result::Result::Ok(converted_objects) @@ -713,25 +783,29 @@ impl Bar { ) -> ::std::result::Result { let api_version = value .get("apiVersion") - .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotPresent)? + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { + field: "apiVersion".to_string(), + })? .as_str() - .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr)?; + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "apiVersion".to_string(), + })?; let object = match api_version { - "bar.example.org/v1alpha1" | "v1alpha1" => { + "bar.example.org/v1alpha1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } - "bar.example.org/v1" | "v1" => { + "bar.example.org/v1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1(object) } - "bar.example.org/v2alpha1" | "v2alpha1" => { + "bar.example.org/v2alpha1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, 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 6a74e8b0c..045a8cd8a 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 @@ -346,12 +346,33 @@ pub(crate) mod versioned { > { let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { + let object_kind = object + .get("kind") + .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::FieldMissing { + field: "kind".to_string(), + }, + })? + .as_str() + .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "kind".to_string(), + }, + })?; + if object_kind != stringify!(Foo) { + return Err(::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::WrongObjectKind { + kind: object_kind.to_string(), + supported_kind: stringify!(Foo).to_string(), + }, + }); + } let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; match (current_object, desired_api_version) { - (Self::V1Alpha1(__sv_foo), "v1") => { + (Self::V1Alpha1(__sv_foo), "foo.example.org/v1") => { let converted: v1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1(v1::Foo { metadata: __sv_foo.metadata, @@ -364,7 +385,7 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(__sv_foo), "v2alpha1") => { + (Self::V1Alpha1(__sv_foo), "foo.example.org/v2alpha1") => { let converted: v1::FooSpec = __sv_foo.spec.into(); let converted: v2alpha1::FooSpec = converted.into(); let desired_object = Self::V2Alpha1(v2alpha1::Foo { @@ -378,7 +399,7 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foo), "v1alpha1") => { + (Self::V1(__sv_foo), "foo.example.org/v1alpha1") => { let converted: v1alpha1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Alpha1(v1alpha1::Foo { metadata: __sv_foo.metadata, @@ -391,7 +412,7 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foo), "v2alpha1") => { + (Self::V1(__sv_foo), "foo.example.org/v2alpha1") => { let converted: v2alpha1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V2Alpha1(v2alpha1::Foo { metadata: __sv_foo.metadata, @@ -404,7 +425,7 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V2Alpha1(__sv_foo), "v1alpha1") => { + (Self::V2Alpha1(__sv_foo), "foo.example.org/v1alpha1") => { let converted: v1::FooSpec = __sv_foo.spec.into(); let converted: v1alpha1::FooSpec = converted.into(); let desired_object = Self::V1Alpha1(v1alpha1::Foo { @@ -418,7 +439,7 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V2Alpha1(__sv_foo), "v1") => { + (Self::V2Alpha1(__sv_foo), "foo.example.org/v1") => { let converted: v1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1(v1::Foo { metadata: __sv_foo.metadata, @@ -431,7 +452,19 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - _ => converted_objects.push(object), + (Self::V1Alpha1(_), "foo.example.org/v1alpha1") => { + converted_objects.push(object) + } + (Self::V1(_), "foo.example.org/v1") => converted_objects.push(object), + (Self::V2Alpha1(_), "foo.example.org/v2alpha1") => { + converted_objects.push(object) + } + (_, unknown_desired_api_version) => { + return ::std::result::Result::Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { + unknown_desired_api_version: unknown_desired_api_version + .to_string(), + }); + } } } ::std::result::Result::Ok(converted_objects) @@ -441,25 +474,29 @@ pub(crate) mod versioned { ) -> ::std::result::Result { let api_version = value .get("apiVersion") - .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotPresent)? + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { + field: "apiVersion".to_string(), + })? .as_str() - .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr)?; + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "apiVersion".to_string(), + })?; let object = match api_version { - "foo.example.org/v1alpha1" | "v1alpha1" => { + "foo.example.org/v1alpha1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } - "foo.example.org/v1" | "v1" => { + "foo.example.org/v1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1(object) } - "foo.example.org/v2alpha1" | "v2alpha1" => { + "foo.example.org/v2alpha1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, @@ -594,12 +631,33 @@ pub(crate) mod versioned { > { let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { + let object_kind = object + .get("kind") + .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::FieldMissing { + field: "kind".to_string(), + }, + })? + .as_str() + .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "kind".to_string(), + }, + })?; + if object_kind != stringify!(Bar) { + return Err(::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::WrongObjectKind { + kind: object_kind.to_string(), + supported_kind: stringify!(Bar).to_string(), + }, + }); + } let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; match (current_object, desired_api_version) { - (Self::V1Alpha1(__sv_bar), "v1") => { + (Self::V1Alpha1(__sv_bar), "bar.example.org/v1") => { let converted: v1::BarSpec = __sv_bar.spec.into(); let desired_object = Self::V1(v1::Bar { metadata: __sv_bar.metadata, @@ -612,7 +670,7 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(__sv_bar), "v2alpha1") => { + (Self::V1Alpha1(__sv_bar), "bar.example.org/v2alpha1") => { let converted: v1::BarSpec = __sv_bar.spec.into(); let converted: v2alpha1::BarSpec = converted.into(); let desired_object = Self::V2Alpha1(v2alpha1::Bar { @@ -626,7 +684,7 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_bar), "v1alpha1") => { + (Self::V1(__sv_bar), "bar.example.org/v1alpha1") => { let converted: v1alpha1::BarSpec = __sv_bar.spec.into(); let desired_object = Self::V1Alpha1(v1alpha1::Bar { metadata: __sv_bar.metadata, @@ -639,7 +697,7 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_bar), "v2alpha1") => { + (Self::V1(__sv_bar), "bar.example.org/v2alpha1") => { let converted: v2alpha1::BarSpec = __sv_bar.spec.into(); let desired_object = Self::V2Alpha1(v2alpha1::Bar { metadata: __sv_bar.metadata, @@ -652,7 +710,7 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V2Alpha1(__sv_bar), "v1alpha1") => { + (Self::V2Alpha1(__sv_bar), "bar.example.org/v1alpha1") => { let converted: v1::BarSpec = __sv_bar.spec.into(); let converted: v1alpha1::BarSpec = converted.into(); let desired_object = Self::V1Alpha1(v1alpha1::Bar { @@ -666,7 +724,7 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V2Alpha1(__sv_bar), "v1") => { + (Self::V2Alpha1(__sv_bar), "bar.example.org/v1") => { let converted: v1::BarSpec = __sv_bar.spec.into(); let desired_object = Self::V1(v1::Bar { metadata: __sv_bar.metadata, @@ -679,7 +737,19 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - _ => converted_objects.push(object), + (Self::V1Alpha1(_), "bar.example.org/v1alpha1") => { + converted_objects.push(object) + } + (Self::V1(_), "bar.example.org/v1") => converted_objects.push(object), + (Self::V2Alpha1(_), "bar.example.org/v2alpha1") => { + converted_objects.push(object) + } + (_, unknown_desired_api_version) => { + return ::std::result::Result::Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { + unknown_desired_api_version: unknown_desired_api_version + .to_string(), + }); + } } } ::std::result::Result::Ok(converted_objects) @@ -689,25 +759,29 @@ pub(crate) mod versioned { ) -> ::std::result::Result { let api_version = value .get("apiVersion") - .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotPresent)? + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { + field: "apiVersion".to_string(), + })? .as_str() - .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr)?; + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "apiVersion".to_string(), + })?; let object = match api_version { - "bar.example.org/v1alpha1" | "v1alpha1" => { + "bar.example.org/v1alpha1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } - "bar.example.org/v1" | "v1" => { + "bar.example.org/v1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1(object) } - "bar.example.org/v2alpha1" | "v2alpha1" => { + "bar.example.org/v2alpha1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, 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 d284f43c1..b444e0f03 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 @@ -178,12 +178,33 @@ impl FooBar { > { let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { + let object_kind = object + .get("kind") + .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::FieldMissing { + field: "kind".to_string(), + }, + })? + .as_str() + .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "kind".to_string(), + }, + })?; + if object_kind != stringify!(FooBar) { + return Err(::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::WrongObjectKind { + kind: object_kind.to_string(), + supported_kind: stringify!(FooBar).to_string(), + }, + }); + } let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; match (current_object, desired_api_version) { - (Self::V1Alpha1(__sv_foobar), "v1beta1") => { + (Self::V1Alpha1(__sv_foobar), "stackable.tech/v1beta1") => { let converted: v1beta1::FooSpec = __sv_foobar.spec.into(); let desired_object = Self::V1Beta1(v1beta1::FooBar { metadata: __sv_foobar.metadata, @@ -196,7 +217,7 @@ impl FooBar { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(__sv_foobar), "v1") => { + (Self::V1Alpha1(__sv_foobar), "stackable.tech/v1") => { let converted: v1beta1::FooSpec = __sv_foobar.spec.into(); let converted: v1::FooSpec = converted.into(); let desired_object = Self::V1(v1::FooBar { @@ -210,7 +231,7 @@ impl FooBar { })?; converted_objects.push(desired_object); } - (Self::V1Beta1(__sv_foobar), "v1alpha1") => { + (Self::V1Beta1(__sv_foobar), "stackable.tech/v1alpha1") => { let converted: v1alpha1::FooSpec = __sv_foobar.spec.into(); let desired_object = Self::V1Alpha1(v1alpha1::FooBar { metadata: __sv_foobar.metadata, @@ -223,7 +244,7 @@ impl FooBar { })?; converted_objects.push(desired_object); } - (Self::V1Beta1(__sv_foobar), "v1") => { + (Self::V1Beta1(__sv_foobar), "stackable.tech/v1") => { let converted: v1::FooSpec = __sv_foobar.spec.into(); let desired_object = Self::V1(v1::FooBar { metadata: __sv_foobar.metadata, @@ -236,7 +257,7 @@ impl FooBar { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foobar), "v1alpha1") => { + (Self::V1(__sv_foobar), "stackable.tech/v1alpha1") => { let converted: v1beta1::FooSpec = __sv_foobar.spec.into(); let converted: v1alpha1::FooSpec = converted.into(); let desired_object = Self::V1Alpha1(v1alpha1::FooBar { @@ -250,7 +271,7 @@ impl FooBar { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foobar), "v1beta1") => { + (Self::V1(__sv_foobar), "stackable.tech/v1beta1") => { let converted: v1beta1::FooSpec = __sv_foobar.spec.into(); let desired_object = Self::V1Beta1(v1beta1::FooBar { metadata: __sv_foobar.metadata, @@ -263,7 +284,19 @@ impl FooBar { })?; converted_objects.push(desired_object); } - _ => converted_objects.push(object), + (Self::V1Alpha1(_), "stackable.tech/v1alpha1") => { + converted_objects.push(object) + } + (Self::V1Beta1(_), "stackable.tech/v1beta1") => { + converted_objects.push(object) + } + (Self::V1(_), "stackable.tech/v1") => converted_objects.push(object), + (_, unknown_desired_api_version) => { + return ::std::result::Result::Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { + unknown_desired_api_version: unknown_desired_api_version + .to_string(), + }); + } } } ::std::result::Result::Ok(converted_objects) @@ -273,25 +306,29 @@ impl FooBar { ) -> ::std::result::Result { let api_version = value .get("apiVersion") - .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotPresent)? + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { + field: "apiVersion".to_string(), + })? .as_str() - .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr)?; + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "apiVersion".to_string(), + })?; let object = match api_version { - "stackable.tech/v1alpha1" | "v1alpha1" => { + "stackable.tech/v1alpha1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } - "stackable.tech/v1beta1" | "v1beta1" => { + "stackable.tech/v1beta1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Beta1(object) } - "stackable.tech/v1" | "v1" => { + "stackable.tech/v1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, 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 94e14e24d..801072618 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 @@ -107,12 +107,41 @@ impl Foo { > { let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { + let object_kind = object + .get("kind") + .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::FieldMissing { + field: "kind".to_string(), + }, + })? + .as_str() + .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "kind".to_string(), + }, + })?; + if object_kind != stringify!(Foo) { + return Err(::stackable_versioned::ConvertObjectError::Parse { + source: ::stackable_versioned::ParseObjectError::WrongObjectKind { + kind: object_kind.to_string(), + supported_kind: stringify!(Foo).to_string(), + }, + }); + } let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; match (current_object, desired_api_version) { - _ => converted_objects.push(object), + (Self::V1Alpha1(_), "stackable.tech/v1alpha1") => { + converted_objects.push(object) + } + (_, unknown_desired_api_version) => { + return ::std::result::Result::Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { + unknown_desired_api_version: unknown_desired_api_version + .to_string(), + }); + } } } ::std::result::Result::Ok(converted_objects) @@ -122,11 +151,15 @@ impl Foo { ) -> ::std::result::Result { let api_version = value .get("apiVersion") - .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotPresent)? + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { + field: "apiVersion".to_string(), + })? .as_str() - .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr)?; + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "apiVersion".to_string(), + })?; let object = match api_version { - "stackable.tech/v1alpha1" | "v1alpha1" => { + "stackable.tech/v1alpha1" => { let object = ::serde_json::from_value(value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, diff --git a/crates/stackable-versioned/src/k8s.rs b/crates/stackable-versioned/src/k8s.rs index 25eed324a..2076dc536 100644 --- a/crates/stackable-versioned/src/k8s.rs +++ b/crates/stackable-versioned/src/k8s.rs @@ -47,17 +47,25 @@ fn raw_object_schema(_: &mut schemars::r#gen::SchemaGenerator) -> Schema { /// This error indicates that parsing an object from a conversion review failed. #[derive(Debug, Snafu)] pub enum ParseObjectError { - #[snafu(display(r#"failed to find "apiVersion" field"#))] - FieldNotPresent, + #[snafu(display("the field {field:?} is missing"))] + FieldMissing { field: String }, - #[snafu(display(r#"the "apiVersion" field must be a string"#))] - FieldNotStr, + #[snafu(display(r#"the field {field:?} must be a string"#))] + FieldNotStr { field: String }, #[snafu(display("encountered unknown object API version {api_version:?}"))] UnknownApiVersion { api_version: String }, #[snafu(display("failed to deserialize object from JSON"))] Deserialize { source: serde_json::Error }, + + #[snafu(display( + "wrong object kind {kind:?}. The conversion can only convert objects of kind {supported_kind:?}" + ))] + WrongObjectKind { + kind: String, + supported_kind: String, + }, } /// This error indicates that converting an object from a conversion review to the desired diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@wrong_kind.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@wrong_kind.json.snap new file mode 100644 index 000000000..463853db3 --- /dev/null +++ b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@wrong_kind.json.snap @@ -0,0 +1,19 @@ +--- +source: crates/stackable-versioned/src/tests/mod.rs +expression: formatted +input_file: crates/stackable-versioned/src/tests/fixtures/inputs/fail/wrong_kind.json +--- +{ + "apiVersion": "apiextensions.k8s.io/v1", + "kind": "ConversionReview", + "response": { + "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", + "result": { + "status": "Failure", + "code": 400, + "message": "failed to parse object: wrong object kind \"SomeOtherResource\". The conversion can only convert objects of kind \"Person\"", + "reason": "failed to parse object: wrong object kind \"SomeOtherResource\". The conversion can only convert objects of kind \"Person\"" + }, + "convertedObjects": [] + } +} From a80857d68b3c3c5a19e6c223e27a770d2da051da Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Mon, 23 Jun 2025 11:17:54 +0200 Subject: [PATCH 06/33] Add comment --- .../src/codegen/container/struct/k8s.rs | 3 +++ 1 file changed, 3 insertions(+) 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 93346ab47..58aaf8fbb 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -441,6 +441,9 @@ impl Struct { .ok_or_else(|| #convert_object_error::Parse { source: #parse_object_error::FieldNotStr{ field: "kind".to_string() } })?; + // Note(@sbernauer): One could argue we don't need to check the send kind, but + // IMHO this is a nice sanity check. If for *some* reason a wrong kind ends up + // at a conversion, the problem might be very hard to spot without this. if object_kind != stringify!(#struct_ident) { return Err(#convert_object_error::Parse { source: #parse_object_error::WrongObjectKind{ From a42d5797a06e2abc86b1943824f489bde1b77982 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Mon, 23 Jun 2025 11:24:40 +0200 Subject: [PATCH 07/33] changelog --- crates/stackable-versioned/CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/stackable-versioned/CHANGELOG.md b/crates/stackable-versioned/CHANGELOG.md index 524169ad3..19cd80581 100644 --- a/crates/stackable-versioned/CHANGELOG.md +++ b/crates/stackable-versioned/CHANGELOG.md @@ -6,7 +6,7 @@ All notable changes to this project will be documented in this file. ### Added -- Add support for CRD conversions via ConversionReviews ([#1050]). +- Add support for CRD conversions via ConversionReviews ([#1050], [#1061]). - Add new `try_convert` function to convert objects received via a ConversionReview. - Add new `enable_tracing` option to `#[versioned(k8s(options(...)))]`. - Implement basic ground work for downgrading custom resources ([#1033]). @@ -50,6 +50,7 @@ All notable changes to this project will be documented in this file. [#1041]: https://github.com/stackabletech/operator-rs/pull/1041 [#1046]: https://github.com/stackabletech/operator-rs/pull/1046 [#1050]: https://github.com/stackabletech/operator-rs/pull/1050 +[#1061]: https://github.com/stackabletech/operator-rs/pull/1061 ## [0.7.1] - 2025-04-02 From f88e0adbacfea55aec01e91326b2f95369836fef Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Mon, 23 Jun 2025 11:46:40 +0200 Subject: [PATCH 08/33] clippy --- crates/stackable-versioned/src/tests/mod.rs | 125 +++++++++--------- ...ned__tests__fail@request_missing.json.snap | 19 +++ ...sts__fail@unkown_current_version.json.snap | 19 +++ ...sts__fail@unkown_desired_version.json.snap | 19 +++ ...__fail@unparseable_missing_field.json.snap | 19 +++ ...ersioned__tests__fail@wrong_kind.json.snap | 19 +++ ..._tests__pass@persons_to_v1alpha1.json.snap | 61 +++++++++ ...ioned__tests__pass@persons_to_v3.json.snap | 76 +++++++++++ 8 files changed, 293 insertions(+), 64 deletions(-) create mode 100644 crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@request_missing.json.snap create mode 100644 crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unkown_current_version.json.snap create mode 100644 crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unkown_desired_version.json.snap create mode 100644 crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unparseable_missing_field.json.snap create mode 100644 crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@wrong_kind.json.snap create mode 100644 crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__pass@persons_to_v1alpha1.json.snap create mode 100644 crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__pass@persons_to_v3.json.snap diff --git a/crates/stackable-versioned/src/tests/mod.rs b/crates/stackable-versioned/src/tests/mod.rs index 228efe44c..a40193d37 100644 --- a/crates/stackable-versioned/src/tests/mod.rs +++ b/crates/stackable-versioned/src/tests/mod.rs @@ -1,4 +1,10 @@ -use kube::CustomResource; +use std::{fs::File, path::Path}; + +use insta::{assert_snapshot, glob}; +use kube::{ + CustomResource, + core::{conversion::ConversionReview, response::StatusSummary}, +}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use stackable_versioned_macros::versioned; @@ -57,15 +63,16 @@ pub enum Gender { Female, } -impl Into for Gender { - fn into(self) -> String { - match self { +impl From for String { + fn from(value: Gender) -> Self { + match value { Gender::Unknown => "Unknown".to_string(), Gender::Male => "Male".to_string(), Gender::Female => "Female".to_string(), } } } + impl From for Gender { fn from(value: String) -> Self { match value.as_str() { @@ -76,67 +83,57 @@ impl From for Gender { } } -#[cfg(test)] -mod tests { - use std::{fs::File, path::Path}; - - use insta::{assert_snapshot, glob}; - use kube::core::{conversion::ConversionReview, response::StatusSummary}; - - use super::Person; - - #[test] - fn pass() { - glob!("./fixtures/inputs/pass/", "*.json", |path| { - let (request, response) = run_for_file(path); - - let formatted = serde_json::to_string_pretty(&response) - .expect("Failed to serialize ConversionResponse"); - assert_snapshot!(formatted); - - let response = response - .response - .expect("ConversionReview had no response!"); - - assert_eq!( - response.result.status, - Some(StatusSummary::Success), - "File {path:?} should be converted successfully" - ); - assert_eq!(request.request.unwrap().uid, response.uid); - }) - } +#[test] +fn pass() { + glob!("./fixtures/inputs/pass/", "*.json", |path| { + let (request, response) = run_for_file(path); + + let formatted = serde_json::to_string_pretty(&response) + .expect("Failed to serialize ConversionResponse"); + assert_snapshot!(formatted); + + let response = response + .response + .expect("ConversionReview had no response!"); + + assert_eq!( + response.result.status, + Some(StatusSummary::Success), + "File {path:?} should be converted successfully" + ); + assert_eq!(request.request.unwrap().uid, response.uid); + }) +} - #[test] - fn fail() { - glob!("./fixtures/inputs/fail/", "*.json", |path| { - let (request, response) = run_for_file(path); - - let formatted = serde_json::to_string_pretty(&response) - .expect("Failed to serialize ConversionResponse"); - assert_snapshot!(formatted); - - let response = response - .response - .expect("ConversionReview had no response!"); - - assert_eq!( - response.result.status, - Some(StatusSummary::Failure), - "File {path:?} should *not* be converted successfully" - ); - if let Some(request) = &request.request { - assert_eq!(request.uid, response.uid); - } - }) - } +#[test] +fn fail() { + glob!("./fixtures/inputs/fail/", "*.json", |path| { + let (request, response) = run_for_file(path); + + let formatted = serde_json::to_string_pretty(&response) + .expect("Failed to serialize ConversionResponse"); + assert_snapshot!(formatted); + + let response = response + .response + .expect("ConversionReview had no response!"); + + assert_eq!( + response.result.status, + Some(StatusSummary::Failure), + "File {path:?} should *not* be converted successfully" + ); + if let Some(request) = &request.request { + assert_eq!(request.uid, response.uid); + } + }) +} - fn run_for_file(path: &Path) -> (ConversionReview, ConversionReview) { - let request: ConversionReview = - serde_json::from_reader(File::open(path).expect("failed to open test file")) - .expect("failed to parse ConversionReview from test file"); - let response = Person::try_convert(request.clone()); +fn run_for_file(path: &Path) -> (ConversionReview, ConversionReview) { + let request: ConversionReview = + serde_json::from_reader(File::open(path).expect("failed to open test file")) + .expect("failed to parse ConversionReview from test file"); + let response = Person::try_convert(request.clone()); - (request, response) - } + (request, response) } diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@request_missing.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@request_missing.json.snap new file mode 100644 index 000000000..797a889d5 --- /dev/null +++ b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@request_missing.json.snap @@ -0,0 +1,19 @@ +--- +source: crates/stackable-versioned/src/tests/mod.rs +expression: formatted +input_file: crates/stackable-versioned/src/tests/fixtures/inputs/fail/request_missing.json +--- +{ + "apiVersion": "apiextensions.k8s.io/v1", + "kind": "ConversionReview", + "response": { + "uid": "", + "result": { + "status": "Failure", + "code": 400, + "message": "request missing in ConversionReview", + "reason": "request missing in ConversionReview" + }, + "convertedObjects": [] + } +} diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unkown_current_version.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unkown_current_version.json.snap new file mode 100644 index 000000000..e54c19736 --- /dev/null +++ b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unkown_current_version.json.snap @@ -0,0 +1,19 @@ +--- +source: crates/stackable-versioned/src/tests/mod.rs +expression: formatted +input_file: crates/stackable-versioned/src/tests/fixtures/inputs/fail/unkown_current_version.json +--- +{ + "apiVersion": "apiextensions.k8s.io/v1", + "kind": "ConversionReview", + "response": { + "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", + "result": { + "status": "Failure", + "code": 400, + "message": "failed to parse object: encountered unknown object API version \"test.stackable.tech/v99\"", + "reason": "failed to parse object: encountered unknown object API version \"test.stackable.tech/v99\"" + }, + "convertedObjects": [] + } +} diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unkown_desired_version.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unkown_desired_version.json.snap new file mode 100644 index 000000000..8d8ff4b84 --- /dev/null +++ b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unkown_desired_version.json.snap @@ -0,0 +1,19 @@ +--- +source: crates/stackable-versioned/src/tests/mod.rs +expression: formatted +input_file: crates/stackable-versioned/src/tests/fixtures/inputs/fail/unkown_desired_version.json +--- +{ + "apiVersion": "apiextensions.k8s.io/v1", + "kind": "ConversionReview", + "response": { + "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", + "result": { + "status": "Failure", + "code": 400, + "message": "unknown desired API version \"test.stackable.tech/v99\"", + "reason": "unknown desired API version \"test.stackable.tech/v99\"" + }, + "convertedObjects": [] + } +} diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unparseable_missing_field.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unparseable_missing_field.json.snap new file mode 100644 index 000000000..e77d508f4 --- /dev/null +++ b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unparseable_missing_field.json.snap @@ -0,0 +1,19 @@ +--- +source: crates/stackable-versioned/src/tests/mod.rs +expression: formatted +input_file: crates/stackable-versioned/src/tests/fixtures/inputs/fail/unparseable_missing_field.json +--- +{ + "apiVersion": "apiextensions.k8s.io/v1", + "kind": "ConversionReview", + "response": { + "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", + "result": { + "status": "Failure", + "code": 400, + "message": "failed to parse object: failed to deserialize object from JSON: missing field `username`", + "reason": "failed to parse object: failed to deserialize object from JSON: missing field `username`" + }, + "convertedObjects": [] + } +} diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@wrong_kind.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@wrong_kind.json.snap new file mode 100644 index 000000000..463853db3 --- /dev/null +++ b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@wrong_kind.json.snap @@ -0,0 +1,19 @@ +--- +source: crates/stackable-versioned/src/tests/mod.rs +expression: formatted +input_file: crates/stackable-versioned/src/tests/fixtures/inputs/fail/wrong_kind.json +--- +{ + "apiVersion": "apiextensions.k8s.io/v1", + "kind": "ConversionReview", + "response": { + "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", + "result": { + "status": "Failure", + "code": 400, + "message": "failed to parse object: wrong object kind \"SomeOtherResource\". The conversion can only convert objects of kind \"Person\"", + "reason": "failed to parse object: wrong object kind \"SomeOtherResource\". The conversion can only convert objects of kind \"Person\"" + }, + "convertedObjects": [] + } +} diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__pass@persons_to_v1alpha1.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__pass@persons_to_v1alpha1.json.snap new file mode 100644 index 000000000..c015c3558 --- /dev/null +++ b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__pass@persons_to_v1alpha1.json.snap @@ -0,0 +1,61 @@ +--- +source: crates/stackable-versioned/src/tests/mod.rs +expression: formatted +input_file: crates/stackable-versioned/src/tests/fixtures/inputs/pass/persons_to_v1alpha1.json +--- +{ + "apiVersion": "apiextensions.k8s.io/v1", + "kind": "ConversionReview", + "response": { + "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", + "result": { + "status": "Success" + }, + "convertedObjects": [ + { + "apiVersion": "test.stackable.tech/v1alpha1", + "kind": "Person", + "metadata": { + "name": "sbernauer", + "namespace": "default", + "uid": "d41e2019-5de3-409c-a7b2-0799ecb95e4b" + }, + "spec": { + "username": "sbernauer" + } + }, + { + "apiVersion": "test.stackable.tech/v1alpha1", + "kind": "Person", + "metadata": {}, + "spec": { + "username": "sbernauer" + } + }, + { + "apiVersion": "test.stackable.tech/v1alpha1", + "kind": "Person", + "metadata": {}, + "spec": { + "username": "sbernauer" + } + }, + { + "apiVersion": "test.stackable.tech/v1alpha1", + "kind": "Person", + "metadata": {}, + "spec": { + "username": "sbernauer" + } + }, + { + "apiVersion": "test.stackable.tech/v1alpha1", + "kind": "Person", + "metadata": {}, + "spec": { + "username": "sbernauer" + } + } + ] + } +} diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__pass@persons_to_v3.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__pass@persons_to_v3.json.snap new file mode 100644 index 000000000..43d687cc2 --- /dev/null +++ b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__pass@persons_to_v3.json.snap @@ -0,0 +1,76 @@ +--- +source: crates/stackable-versioned/src/tests/mod.rs +expression: formatted +input_file: crates/stackable-versioned/src/tests/fixtures/inputs/pass/persons_to_v3.json +--- +{ + "apiVersion": "apiextensions.k8s.io/v1", + "kind": "ConversionReview", + "response": { + "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", + "result": { + "status": "Success" + }, + "convertedObjects": [ + { + "apiVersion": "test.stackable.tech/v3", + "kind": "Person", + "metadata": { + "name": "sbernauer", + "namespace": "default", + "uid": "d41e2019-5de3-409c-a7b2-0799ecb95e4b" + }, + "spec": { + "firstName": "", + "gender": "Unknown", + "lastName": "", + "username": "sbernauer" + } + }, + { + "apiVersion": "test.stackable.tech/v3", + "kind": "Person", + "metadata": {}, + "spec": { + "firstName": "Sebastian", + "gender": "Unknown", + "lastName": "Bernauer", + "username": "sbernauer" + } + }, + { + "apiVersion": "test.stackable.tech/v3", + "kind": "Person", + "metadata": {}, + "spec": { + "firstName": "Sebastian", + "gender": "Unknown", + "lastName": "Bernauer", + "username": "sbernauer" + } + }, + { + "apiVersion": "test.stackable.tech/v3", + "kind": "Person", + "metadata": {}, + "spec": { + "firstName": "Sebastian", + "gender": "Male", + "lastName": "Bernauer", + "username": "sbernauer" + } + }, + { + "apiVersion": "test.stackable.tech/v3", + "kind": "Person", + "metadata": {}, + "spec": { + "firstName": "Sebastian", + "gender": "Male", + "lastName": "Bernauer", + "username": "sbernauer" + } + } + ] + } +} From 073c481056add821887ab41b3199310a45798858 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Mon, 23 Jun 2025 14:52:47 +0200 Subject: [PATCH 09/33] Move kind check to from_json_value --- .../src/codegen/container/struct/k8s.rs | 44 ++++----- ..._macros__snapshot_tests__k8s@basic.rs.snap | 46 ++++------ ...hot_tests__k8s@conversion_tracking.rs.snap | 46 ++++------ ...napshot_tests__k8s@crate_overrides.rs.snap | 46 ++++------ ...macros__snapshot_tests__k8s@module.rs.snap | 92 ++++++++----------- ...napshot_tests__k8s@module_preserve.rs.snap | 92 ++++++++----------- ...__snapshot_tests__k8s@renamed_kind.rs.snap | 46 ++++------ ...os__snapshot_tests__k8s@shortnames.rs.snap | 42 ++++----- crates/stackable-versioned/src/k8s.rs | 4 +- ...ersioned__tests__fail@wrong_kind.json.snap | 4 +- 10 files changed, 201 insertions(+), 261 deletions(-) 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 58aaf8fbb..3ff50a6fd 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -178,8 +178,24 @@ impl Struct { #convert_method - fn from_json_value(value: #serde_json_path::Value) -> ::std::result::Result { - let api_version = value + fn from_json_value(object: #serde_json_path::Value) -> ::std::result::Result { + let object_kind = object + .get("kind") + .ok_or_else(|| #parse_object_error::FieldMissing{ field: "kind".to_string() })? + .as_str() + .ok_or_else(|| #parse_object_error::FieldNotStr{ field: "kind".to_string() })?; + + // Note(@sbernauer): One could argue we don't need to check the kind, but this + // is a nice sanity check. If for *some* reason a unexpected kind ends up at a + // conversion, the problem might be very hard to spot without this. + if object_kind != stringify!(#enum_ident) { + return Err(#parse_object_error::UnexpectedObjectKind{ + kind: object_kind.to_string(), + supported_kind: stringify!(#enum_ident).to_string(), + }); + } + + let api_version = object .get("apiVersion") .ok_or_else(|| #parse_object_error::FieldMissing{ field: "apiVersion".to_string() })? .as_str() @@ -187,7 +203,7 @@ impl Struct { let object = match api_version { #(#api_versions => { - let object = #serde_json_path::from_value(value) + let object = #serde_json_path::from_value(object) .map_err(|source| #parse_object_error::Deserialize { source })?; Self::#variant_idents(object) @@ -321,7 +337,6 @@ impl Struct { let versioned_path = &*kubernetes_arguments.crates.versioned; let kube_core_path = &*kubernetes_arguments.crates.kube_core; - let parse_object_error = quote! { #versioned_path::ParseObjectError }; let convert_object_error = quote! { #versioned_path::ConvertObjectError }; // Generate conversion paths and the match arms for these paths @@ -432,27 +447,6 @@ impl Struct { let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let object_kind = object - .get("kind") - .ok_or_else(|| #convert_object_error::Parse { - source: #parse_object_error::FieldMissing{ field: "kind".to_string() } - })? - .as_str() - .ok_or_else(|| #convert_object_error::Parse { - source: #parse_object_error::FieldNotStr{ field: "kind".to_string() } - })?; - // Note(@sbernauer): One could argue we don't need to check the send kind, but - // IMHO this is a nice sanity check. If for *some* reason a wrong kind ends up - // at a conversion, the problem might be very hard to spot without this. - if object_kind != stringify!(#struct_ident) { - return Err(#convert_object_error::Parse { - source: #parse_object_error::WrongObjectKind{ - kind: object_kind.to_string(), - supported_kind: stringify!(#struct_ident).to_string(), - } - }) - } - // This clone is required because in the noop case we move the object into // the converted objects vec. let current_object = Self::from_json_value(object.clone()) 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 80de747ee..632590f30 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 @@ -202,27 +202,6 @@ impl Foo { > { let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let object_kind = object - .get("kind") - .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::FieldMissing { - field: "kind".to_string(), - }, - })? - .as_str() - .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "kind".to_string(), - }, - })?; - if object_kind != stringify!(Foo) { - return Err(::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::WrongObjectKind { - kind: object_kind.to_string(), - supported_kind: stringify!(Foo).to_string(), - }, - }); - } let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, @@ -332,9 +311,24 @@ impl Foo { ::std::result::Result::Ok(converted_objects) } fn from_json_value( - value: ::serde_json::Value, + object: ::serde_json::Value, ) -> ::std::result::Result { - let api_version = value + let object_kind = object + .get("kind") + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { + field: "kind".to_string(), + })? + .as_str() + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "kind".to_string(), + })?; + if object_kind != stringify!(Foo) { + return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { + kind: object_kind.to_string(), + supported_kind: stringify!(Foo).to_string(), + }); + } + let api_version = object .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "apiVersion".to_string(), @@ -345,21 +339,21 @@ impl Foo { })?; let object = match api_version { "stackable.tech/v1alpha1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } "stackable.tech/v1beta1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Beta1(object) } "stackable.tech/v1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; 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 1946c3be3..f9d43fcba 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 @@ -172,27 +172,6 @@ impl Foo { > { let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let object_kind = object - .get("kind") - .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::FieldMissing { - field: "kind".to_string(), - }, - })? - .as_str() - .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "kind".to_string(), - }, - })?; - if object_kind != stringify!(Foo) { - return Err(::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::WrongObjectKind { - kind: object_kind.to_string(), - supported_kind: stringify!(Foo).to_string(), - }, - }); - } let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, @@ -302,9 +281,24 @@ impl Foo { ::std::result::Result::Ok(converted_objects) } fn from_json_value( - value: ::serde_json::Value, + object: ::serde_json::Value, ) -> ::std::result::Result { - let api_version = value + let object_kind = object + .get("kind") + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { + field: "kind".to_string(), + })? + .as_str() + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "kind".to_string(), + })?; + if object_kind != stringify!(Foo) { + return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { + kind: object_kind.to_string(), + supported_kind: stringify!(Foo).to_string(), + }); + } + let api_version = object .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "apiVersion".to_string(), @@ -315,21 +309,21 @@ impl Foo { })?; let object = match api_version { "stackable.tech/v1alpha1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } "stackable.tech/v1beta1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Beta1(object) } "stackable.tech/v1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; 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 0f3c86acd..82dcfa7d1 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 @@ -193,27 +193,6 @@ impl Foo { > { let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let object_kind = object - .get("kind") - .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::FieldMissing { - field: "kind".to_string(), - }, - })? - .as_str() - .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "kind".to_string(), - }, - })?; - if object_kind != stringify!(Foo) { - return Err(::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::WrongObjectKind { - kind: object_kind.to_string(), - supported_kind: stringify!(Foo).to_string(), - }, - }); - } let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, @@ -317,9 +296,24 @@ impl Foo { ::std::result::Result::Ok(converted_objects) } fn from_json_value( - value: ::serde_json::Value, + object: ::serde_json::Value, ) -> ::std::result::Result { - let api_version = value + let object_kind = object + .get("kind") + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { + field: "kind".to_string(), + })? + .as_str() + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "kind".to_string(), + })?; + if object_kind != stringify!(Foo) { + return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { + kind: object_kind.to_string(), + supported_kind: stringify!(Foo).to_string(), + }); + } + let api_version = object .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "apiVersion".to_string(), @@ -330,21 +324,21 @@ impl Foo { })?; let object = match api_version { "foo.example.org/v1alpha1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } "foo.example.org/v1beta1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Beta1(object) } "foo.example.org/v1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; 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 b766238a7..94add4f0a 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 @@ -365,27 +365,6 @@ impl Foo { > { let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let object_kind = object - .get("kind") - .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::FieldMissing { - field: "kind".to_string(), - }, - })? - .as_str() - .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "kind".to_string(), - }, - })?; - if object_kind != stringify!(Foo) { - return Err(::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::WrongObjectKind { - kind: object_kind.to_string(), - supported_kind: stringify!(Foo).to_string(), - }, - }); - } let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, @@ -489,9 +468,24 @@ impl Foo { ::std::result::Result::Ok(converted_objects) } fn from_json_value( - value: ::serde_json::Value, + object: ::serde_json::Value, ) -> ::std::result::Result { - let api_version = value + let object_kind = object + .get("kind") + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { + field: "kind".to_string(), + })? + .as_str() + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "kind".to_string(), + })?; + if object_kind != stringify!(Foo) { + return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { + kind: object_kind.to_string(), + supported_kind: stringify!(Foo).to_string(), + }); + } + let api_version = object .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "apiVersion".to_string(), @@ -502,21 +496,21 @@ impl Foo { })?; let object = match api_version { "foo.example.org/v1alpha1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } "foo.example.org/v1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1(object) } "foo.example.org/v2alpha1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; @@ -655,27 +649,6 @@ impl Bar { > { let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let object_kind = object - .get("kind") - .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::FieldMissing { - field: "kind".to_string(), - }, - })? - .as_str() - .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "kind".to_string(), - }, - })?; - if object_kind != stringify!(Bar) { - return Err(::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::WrongObjectKind { - kind: object_kind.to_string(), - supported_kind: stringify!(Bar).to_string(), - }, - }); - } let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, @@ -779,9 +752,24 @@ impl Bar { ::std::result::Result::Ok(converted_objects) } fn from_json_value( - value: ::serde_json::Value, + object: ::serde_json::Value, ) -> ::std::result::Result { - let api_version = value + let object_kind = object + .get("kind") + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { + field: "kind".to_string(), + })? + .as_str() + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "kind".to_string(), + })?; + if object_kind != stringify!(Bar) { + return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { + kind: object_kind.to_string(), + supported_kind: stringify!(Bar).to_string(), + }); + } + let api_version = object .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "apiVersion".to_string(), @@ -792,21 +780,21 @@ impl Bar { })?; let object = match api_version { "bar.example.org/v1alpha1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } "bar.example.org/v1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1(object) } "bar.example.org/v2alpha1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; 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 045a8cd8a..50c879247 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 @@ -346,27 +346,6 @@ pub(crate) mod versioned { > { let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let object_kind = object - .get("kind") - .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::FieldMissing { - field: "kind".to_string(), - }, - })? - .as_str() - .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "kind".to_string(), - }, - })?; - if object_kind != stringify!(Foo) { - return Err(::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::WrongObjectKind { - kind: object_kind.to_string(), - supported_kind: stringify!(Foo).to_string(), - }, - }); - } let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, @@ -470,9 +449,24 @@ pub(crate) mod versioned { ::std::result::Result::Ok(converted_objects) } fn from_json_value( - value: ::serde_json::Value, + object: ::serde_json::Value, ) -> ::std::result::Result { - let api_version = value + let object_kind = object + .get("kind") + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { + field: "kind".to_string(), + })? + .as_str() + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "kind".to_string(), + })?; + if object_kind != stringify!(Foo) { + return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { + kind: object_kind.to_string(), + supported_kind: stringify!(Foo).to_string(), + }); + } + let api_version = object .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "apiVersion".to_string(), @@ -483,21 +477,21 @@ pub(crate) mod versioned { })?; let object = match api_version { "foo.example.org/v1alpha1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } "foo.example.org/v1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1(object) } "foo.example.org/v2alpha1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; @@ -631,27 +625,6 @@ pub(crate) mod versioned { > { let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let object_kind = object - .get("kind") - .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::FieldMissing { - field: "kind".to_string(), - }, - })? - .as_str() - .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "kind".to_string(), - }, - })?; - if object_kind != stringify!(Bar) { - return Err(::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::WrongObjectKind { - kind: object_kind.to_string(), - supported_kind: stringify!(Bar).to_string(), - }, - }); - } let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, @@ -755,9 +728,24 @@ pub(crate) mod versioned { ::std::result::Result::Ok(converted_objects) } fn from_json_value( - value: ::serde_json::Value, + object: ::serde_json::Value, ) -> ::std::result::Result { - let api_version = value + let object_kind = object + .get("kind") + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { + field: "kind".to_string(), + })? + .as_str() + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "kind".to_string(), + })?; + if object_kind != stringify!(Bar) { + return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { + kind: object_kind.to_string(), + supported_kind: stringify!(Bar).to_string(), + }); + } + let api_version = object .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "apiVersion".to_string(), @@ -768,21 +756,21 @@ pub(crate) mod versioned { })?; let object = match api_version { "bar.example.org/v1alpha1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } "bar.example.org/v1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1(object) } "bar.example.org/v2alpha1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; 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 b444e0f03..e1fd61079 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 @@ -178,27 +178,6 @@ impl FooBar { > { let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let object_kind = object - .get("kind") - .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::FieldMissing { - field: "kind".to_string(), - }, - })? - .as_str() - .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "kind".to_string(), - }, - })?; - if object_kind != stringify!(FooBar) { - return Err(::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::WrongObjectKind { - kind: object_kind.to_string(), - supported_kind: stringify!(FooBar).to_string(), - }, - }); - } let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, @@ -302,9 +281,24 @@ impl FooBar { ::std::result::Result::Ok(converted_objects) } fn from_json_value( - value: ::serde_json::Value, + object: ::serde_json::Value, ) -> ::std::result::Result { - let api_version = value + let object_kind = object + .get("kind") + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { + field: "kind".to_string(), + })? + .as_str() + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "kind".to_string(), + })?; + if object_kind != stringify!(FooBar) { + return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { + kind: object_kind.to_string(), + supported_kind: stringify!(FooBar).to_string(), + }); + } + let api_version = object .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "apiVersion".to_string(), @@ -315,21 +309,21 @@ impl FooBar { })?; let object = match api_version { "stackable.tech/v1alpha1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } "stackable.tech/v1beta1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Beta1(object) } "stackable.tech/v1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; 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 801072618..b1d019f85 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 @@ -107,27 +107,6 @@ impl Foo { > { let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let object_kind = object - .get("kind") - .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::FieldMissing { - field: "kind".to_string(), - }, - })? - .as_str() - .ok_or_else(|| ::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "kind".to_string(), - }, - })?; - if object_kind != stringify!(Foo) { - return Err(::stackable_versioned::ConvertObjectError::Parse { - source: ::stackable_versioned::ParseObjectError::WrongObjectKind { - kind: object_kind.to_string(), - supported_kind: stringify!(Foo).to_string(), - }, - }); - } let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, @@ -147,9 +126,24 @@ impl Foo { ::std::result::Result::Ok(converted_objects) } fn from_json_value( - value: ::serde_json::Value, + object: ::serde_json::Value, ) -> ::std::result::Result { - let api_version = value + let object_kind = object + .get("kind") + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { + field: "kind".to_string(), + })? + .as_str() + .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { + field: "kind".to_string(), + })?; + if object_kind != stringify!(Foo) { + return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { + kind: object_kind.to_string(), + supported_kind: stringify!(Foo).to_string(), + }); + } + let api_version = object .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "apiVersion".to_string(), @@ -160,7 +154,7 @@ impl Foo { })?; let object = match api_version { "stackable.tech/v1alpha1" => { - let object = ::serde_json::from_value(value) + let object = ::serde_json::from_value(object) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; diff --git a/crates/stackable-versioned/src/k8s.rs b/crates/stackable-versioned/src/k8s.rs index 2076dc536..d4f0152af 100644 --- a/crates/stackable-versioned/src/k8s.rs +++ b/crates/stackable-versioned/src/k8s.rs @@ -60,9 +60,9 @@ pub enum ParseObjectError { Deserialize { source: serde_json::Error }, #[snafu(display( - "wrong object kind {kind:?}. The conversion can only convert objects of kind {supported_kind:?}" + "unexpected object kind {kind:?}. The conversion can only convert objects of kind {supported_kind:?}" ))] - WrongObjectKind { + UnexpectedObjectKind { kind: String, supported_kind: String, }, diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@wrong_kind.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@wrong_kind.json.snap index 463853db3..019baa096 100644 --- a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@wrong_kind.json.snap +++ b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@wrong_kind.json.snap @@ -11,8 +11,8 @@ input_file: crates/stackable-versioned/src/tests/fixtures/inputs/fail/wrong_kind "result": { "status": "Failure", "code": 400, - "message": "failed to parse object: wrong object kind \"SomeOtherResource\". The conversion can only convert objects of kind \"Person\"", - "reason": "failed to parse object: wrong object kind \"SomeOtherResource\". The conversion can only convert objects of kind \"Person\"" + "message": "failed to parse object: unexpected object kind \"SomeOtherResource\". The conversion can only convert objects of kind \"Person\"", + "reason": "failed to parse object: unexpected object kind \"SomeOtherResource\". The conversion can only convert objects of kind \"Person\"" }, "convertedObjects": [] } From 548b300d5bfd16dcddae20435dda0f87681470a8 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Mon, 23 Jun 2025 17:09:08 +0200 Subject: [PATCH 10/33] Parse desired api version early --- .../src/codegen/container/struct/k8s.rs | 64 ++++++---- ..._macros__snapshot_tests__k8s@basic.rs.snap | 59 +++++---- ...hot_tests__k8s@conversion_tracking.rs.snap | 59 +++++---- ...napshot_tests__k8s@crate_overrides.rs.snap | 59 +++++---- ...macros__snapshot_tests__k8s@module.rs.snap | 114 ++++++++++------- ...napshot_tests__k8s@module_preserve.rs.snap | 118 +++++++++++------- ...__snapshot_tests__k8s@renamed_kind.rs.snap | 59 +++++---- ...os__snapshot_tests__k8s@shortnames.rs.snap | 37 ++++-- 8 files changed, 360 insertions(+), 209 deletions(-) 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 3ff50a6fd..4eddb6137 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -153,7 +153,8 @@ impl Struct { // Generate additional Kubernetes code, this is split out to reduce the complexity in this // function. let status_struct = self.generate_kubernetes_status_struct(kubernetes_arguments, is_nested); - let version_enum = self.generate_kubernetes_version_enum(tokens, vis, 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 parse_object_error = quote! { #versioned_path::ParseObjectError }; @@ -173,7 +174,7 @@ impl Struct { #k8s_openapi_path::apiextensions_apiserver::pkg::apis::apiextensions::v1::CustomResourceDefinition, #kube_core_path::crd::MergeError> { - #kube_core_path::crd::merge_crds(vec![#(#crd_fns),*], stored_apiversion.as_str()) + #kube_core_path::crd::merge_crds(vec![#(#crd_fns),*], stored_apiversion.as_version_str()) } #convert_method @@ -234,6 +235,7 @@ impl Struct { fn generate_kubernetes_version_enum( &self, + kubernetes_arguments: &KubernetesArguments, tokens: &KubernetesTokens, vis: &Visibility, is_nested: bool, @@ -244,9 +246,16 @@ impl Struct { // module (in standalone mode). let automatically_derived = is_nested.not().then(|| quote! {#[automatically_derived]}); + let versioned_path = &*kubernetes_arguments.crates.versioned; + let convert_object_error = quote! { #versioned_path::ConvertObjectError }; + // Get the per-version items to be able to iterate over them via quote let variant_strings = &tokens.variant_strings; let variant_idents = &tokens.variant_idents; + let api_versions = variant_strings + .iter() + .map(|version| format!("{group}/{version}", group = &kubernetes_arguments.group)) + .collect::>(); quote! { #automatically_derived @@ -257,17 +266,33 @@ impl Struct { #automatically_derived impl ::std::fmt::Display for #enum_ident { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::result::Result<(), ::std::fmt::Error> { - f.write_str(self.as_str()) + // The version (without the Kubernetes group) is probably more human-readable + f.write_str(self.as_version_str()) } } #automatically_derived impl #enum_ident { - pub fn as_str(&self) -> &str { + pub fn as_version_str(&self) -> &str { match self { #(#variant_idents => #variant_strings),* } } + + pub fn as_api_version_str(&self) -> &str { + match self { + #(#variant_idents => #api_versions),* + } + } + + pub fn try_from_api_version(api_version: &str) -> Result { + match api_version { + #(#api_versions => Ok(Self::#variant_idents)),*, + _ => Err(#convert_object_error::DesiredApiVersionUnknown { + unknown_desired_api_version: api_version.to_string(), + }), + } + } } } } @@ -331,6 +356,7 @@ impl Struct { let kubernetes_arguments = self.common.options.kubernetes_arguments.as_ref()?; let struct_ident = &self.common.idents.kubernetes; + let version_enum_ident = &self.common.idents.kubernetes_version; let kube_client_path = &*kubernetes_arguments.crates.kube_client; let serde_json_path = &*kubernetes_arguments.crates.serde_json; @@ -342,8 +368,7 @@ impl Struct { // Generate conversion paths and the match arms for these paths let conversion_match_arms = self.generate_kubernetes_conversion_match_arms(versions, kubernetes_arguments); - let noop_match_arms = - self.generate_kubernetes_noop_match_arms(versions, kubernetes_arguments); + let noop_match_arms = self.generate_kubernetes_noop_match_arms(versions); // TODO (@Techassi): Make this a feature, drop the option from the macro arguments // Generate tracing attributes and events if tracing is enabled @@ -393,11 +418,8 @@ impl Struct { } }; - // Extract the desired api version - let desired_api_version = request.desired_api_version.as_str(); - // Convert all objects into the desired version - let response = match Self::convert_objects(request.objects, desired_api_version) { + let response = match Self::convert_objects(request.objects, &request.desired_api_version) { ::std::result::Result::Ok(converted_objects) => { #successful_conversion_response_event @@ -444,6 +466,9 @@ impl Struct { ) -> ::std::result::Result<::std::vec::Vec<#serde_json_path::Value>, #convert_object_error> { + let desired_api_version = #version_enum_ident::try_from_api_version(desired_api_version)?; + // let desired_api_version: #version_enum_ident = desired_api_version.try_into()?; + let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { @@ -452,14 +477,11 @@ impl Struct { let current_object = Self::from_json_value(object.clone()) .map_err(|source| #convert_object_error::Parse { source })?; - match (current_object, desired_api_version) { + match (current_object, &desired_api_version) { #(#conversion_match_arms,)* + // We explicitly list the remaining no-op cases, so the compiler ensures we + // did not miss a conversion. #(#noop_match_arms,)* - (_, unknown_desired_api_version) => return ::std::result::Result::Err( - #convert_object_error::DesiredApiVersionUnknown{ - unknown_desired_api_version: unknown_desired_api_version.to_string() - } - ) } } @@ -476,6 +498,7 @@ impl Struct { let group = &kubernetes_arguments.group; let variant_data_ident = &self.common.idents.kubernetes_parameter; let struct_ident = &self.common.idents.kubernetes; + let version_enum_ident = &self.common.idents.kubernetes_version; let spec_ident = &self.common.idents.original; let versioned_path = &*kubernetes_arguments.crates.versioned; @@ -530,7 +553,7 @@ impl Struct { .then(|| quote! { status: #variant_data_ident.status, }); quote! { - (Self::#current_object_version_ident(#variant_data_ident), #desired_object_api_version_string) => { + (Self::#current_object_version_ident(#variant_data_ident), #version_enum_ident::#desired_object_variant_ident) => { #(#conversions)* let desired_object = Self::#desired_object_variant_ident(#desired_object_module_ident::#struct_ident { @@ -554,22 +577,19 @@ impl Struct { fn generate_kubernetes_noop_match_arms( &self, versions: &[VersionDefinition], - kubernetes_arguments: &KubernetesArguments, ) -> Vec { - let group = &kubernetes_arguments.group; + let version_enum_ident = &self.common.idents.kubernetes_version; versions .iter() .map(|version| { let version_ident = &version.idents.variant; - let version_string = version.inner.to_string(); - let api_version_string = format!("{group}/{version_string}"); quote! { // This is the case if the desired version matches the current object api version. // NOTE (@Techassi): I'm curious if this will ever happen? In theory the K8s // apiserver should never send such a conversion review. - (Self::#version_ident(_), #api_version_string) => converted_objects.push(object) + (Self::#version_ident(_), #version_enum_ident::#version_ident) => converted_objects.push(object) } }) .collect() 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 632590f30..7c10871c9 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 @@ -133,7 +133,7 @@ impl Foo { v1beta1::Foo as ::kube::core::CustomResourceExt > ::crd(), < v1::Foo as ::kube::core::CustomResourceExt > ::crd() ], - stored_apiversion.as_str(), + stored_apiversion.as_version_str(), ) } ///Tries to convert a list of objects of kind [`Foo`] to the desired API version @@ -161,10 +161,9 @@ impl Foo { .into_review(); } }; - let desired_api_version = request.desired_api_version.as_str(); let response = match Self::convert_objects( request.objects, - desired_api_version, + &request.desired_api_version, ) { ::std::result::Result::Ok(converted_objects) => { ::kube::core::conversion::ConversionResponse { @@ -200,14 +199,15 @@ impl Foo { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { + let desired_api_version = FooVersion::try_from_api_version(desired_api_version)?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; - match (current_object, desired_api_version) { - (Self::V1Alpha1(__sv_foo), "stackable.tech/v1beta1") => { + match (current_object, &desired_api_version) { + (Self::V1Alpha1(__sv_foo), FooVersion::V1Beta1) => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Beta1(v1beta1::Foo { metadata: __sv_foo.metadata, @@ -221,7 +221,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(__sv_foo), "stackable.tech/v1") => { + (Self::V1Alpha1(__sv_foo), FooVersion::V1) => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let converted: v1::FooSpec = converted.into(); let desired_object = Self::V1(v1::Foo { @@ -236,7 +236,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Beta1(__sv_foo), "stackable.tech/v1alpha1") => { + (Self::V1Beta1(__sv_foo), FooVersion::V1Alpha1) => { let converted: v1alpha1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Alpha1(v1alpha1::Foo { metadata: __sv_foo.metadata, @@ -250,7 +250,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Beta1(__sv_foo), "stackable.tech/v1") => { + (Self::V1Beta1(__sv_foo), FooVersion::V1) => { let converted: v1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1(v1::Foo { metadata: __sv_foo.metadata, @@ -264,7 +264,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foo), "stackable.tech/v1alpha1") => { + (Self::V1(__sv_foo), FooVersion::V1Alpha1) => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let converted: v1alpha1::FooSpec = converted.into(); let desired_object = Self::V1Alpha1(v1alpha1::Foo { @@ -279,7 +279,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foo), "stackable.tech/v1beta1") => { + (Self::V1(__sv_foo), FooVersion::V1Beta1) => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Beta1(v1beta1::Foo { metadata: __sv_foo.metadata, @@ -293,19 +293,11 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), "stackable.tech/v1alpha1") => { + (Self::V1Alpha1(_), FooVersion::V1Alpha1) => { converted_objects.push(object) } - (Self::V1Beta1(_), "stackable.tech/v1beta1") => { - converted_objects.push(object) - } - (Self::V1(_), "stackable.tech/v1") => converted_objects.push(object), - (_, unknown_desired_api_version) => { - return ::std::result::Result::Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { - unknown_desired_api_version: unknown_desired_api_version - .to_string(), - }); - } + (Self::V1Beta1(_), FooVersion::V1Beta1) => converted_objects.push(object), + (Self::V1(_), FooVersion::V1) => converted_objects.push(object), } } ::std::result::Result::Ok(converted_objects) @@ -389,16 +381,37 @@ impl ::std::fmt::Display for FooVersion { &self, f: &mut ::std::fmt::Formatter<'_>, ) -> ::std::result::Result<(), ::std::fmt::Error> { - f.write_str(self.as_str()) + f.write_str(self.as_version_str()) } } #[automatically_derived] impl FooVersion { - pub fn as_str(&self) -> &str { + pub fn as_version_str(&self) -> &str { match self { V1Alpha1 => "v1alpha1", V1Beta1 => "v1beta1", V1 => "v1", } } + pub fn as_api_version_str(&self) -> &str { + match self { + V1Alpha1 => "stackable.tech/v1alpha1", + V1Beta1 => "stackable.tech/v1beta1", + V1 => "stackable.tech/v1", + } + } + pub fn try_from_api_version( + api_version: &str, + ) -> Result { + match api_version { + "stackable.tech/v1alpha1" => Ok(Self::V1Alpha1), + "stackable.tech/v1beta1" => Ok(Self::V1Beta1), + "stackable.tech/v1" => Ok(Self::V1), + _ => { + Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { + unknown_desired_api_version: api_version.to_string(), + }) + } + } + } } 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 f9d43fcba..572cb391b 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 @@ -103,7 +103,7 @@ impl Foo { v1beta1::Foo as ::kube::core::CustomResourceExt > ::crd(), < v1::Foo as ::kube::core::CustomResourceExt > ::crd() ], - stored_apiversion.as_str(), + stored_apiversion.as_version_str(), ) } ///Tries to convert a list of objects of kind [`Foo`] to the desired API version @@ -131,10 +131,9 @@ impl Foo { .into_review(); } }; - let desired_api_version = request.desired_api_version.as_str(); let response = match Self::convert_objects( request.objects, - desired_api_version, + &request.desired_api_version, ) { ::std::result::Result::Ok(converted_objects) => { ::kube::core::conversion::ConversionResponse { @@ -170,14 +169,15 @@ impl Foo { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { + let desired_api_version = FooVersion::try_from_api_version(desired_api_version)?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; - match (current_object, desired_api_version) { - (Self::V1Alpha1(__sv_foo), "stackable.tech/v1beta1") => { + match (current_object, &desired_api_version) { + (Self::V1Alpha1(__sv_foo), FooVersion::V1Beta1) => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Beta1(v1beta1::Foo { metadata: __sv_foo.metadata, @@ -191,7 +191,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(__sv_foo), "stackable.tech/v1") => { + (Self::V1Alpha1(__sv_foo), FooVersion::V1) => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let converted: v1::FooSpec = converted.into(); let desired_object = Self::V1(v1::Foo { @@ -206,7 +206,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Beta1(__sv_foo), "stackable.tech/v1alpha1") => { + (Self::V1Beta1(__sv_foo), FooVersion::V1Alpha1) => { let converted: v1alpha1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Alpha1(v1alpha1::Foo { metadata: __sv_foo.metadata, @@ -220,7 +220,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Beta1(__sv_foo), "stackable.tech/v1") => { + (Self::V1Beta1(__sv_foo), FooVersion::V1) => { let converted: v1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1(v1::Foo { metadata: __sv_foo.metadata, @@ -234,7 +234,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foo), "stackable.tech/v1alpha1") => { + (Self::V1(__sv_foo), FooVersion::V1Alpha1) => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let converted: v1alpha1::FooSpec = converted.into(); let desired_object = Self::V1Alpha1(v1alpha1::Foo { @@ -249,7 +249,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foo), "stackable.tech/v1beta1") => { + (Self::V1(__sv_foo), FooVersion::V1Beta1) => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Beta1(v1beta1::Foo { metadata: __sv_foo.metadata, @@ -263,19 +263,11 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), "stackable.tech/v1alpha1") => { + (Self::V1Alpha1(_), FooVersion::V1Alpha1) => { converted_objects.push(object) } - (Self::V1Beta1(_), "stackable.tech/v1beta1") => { - converted_objects.push(object) - } - (Self::V1(_), "stackable.tech/v1") => converted_objects.push(object), - (_, unknown_desired_api_version) => { - return ::std::result::Result::Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { - unknown_desired_api_version: unknown_desired_api_version - .to_string(), - }); - } + (Self::V1Beta1(_), FooVersion::V1Beta1) => converted_objects.push(object), + (Self::V1(_), FooVersion::V1) => converted_objects.push(object), } } ::std::result::Result::Ok(converted_objects) @@ -359,18 +351,39 @@ impl ::std::fmt::Display for FooVersion { &self, f: &mut ::std::fmt::Formatter<'_>, ) -> ::std::result::Result<(), ::std::fmt::Error> { - f.write_str(self.as_str()) + f.write_str(self.as_version_str()) } } #[automatically_derived] impl FooVersion { - pub fn as_str(&self) -> &str { + pub fn as_version_str(&self) -> &str { match self { V1Alpha1 => "v1alpha1", V1Beta1 => "v1beta1", V1 => "v1", } } + pub fn as_api_version_str(&self) -> &str { + match self { + V1Alpha1 => "stackable.tech/v1alpha1", + V1Beta1 => "stackable.tech/v1beta1", + V1 => "stackable.tech/v1", + } + } + pub fn try_from_api_version( + api_version: &str, + ) -> Result { + match api_version { + "stackable.tech/v1alpha1" => Ok(Self::V1Alpha1), + "stackable.tech/v1beta1" => Ok(Self::V1Beta1), + "stackable.tech/v1" => Ok(Self::V1), + _ => { + Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { + unknown_desired_api_version: api_version.to_string(), + }) + } + } + } } #[automatically_derived] #[derive( 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 82dcfa7d1..23da00c91 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 @@ -124,7 +124,7 @@ impl Foo { v1beta1::Foo as ::kube::core::CustomResourceExt > ::crd(), < v1::Foo as ::kube::core::CustomResourceExt > ::crd() ], - stored_apiversion.as_str(), + stored_apiversion.as_version_str(), ) } ///Tries to convert a list of objects of kind [`Foo`] to the desired API version @@ -152,10 +152,9 @@ impl Foo { .into_review(); } }; - let desired_api_version = request.desired_api_version.as_str(); let response = match Self::convert_objects( request.objects, - desired_api_version, + &request.desired_api_version, ) { ::std::result::Result::Ok(converted_objects) => { ::kube::core::conversion::ConversionResponse { @@ -191,14 +190,15 @@ impl Foo { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { + let desired_api_version = FooVersion::try_from_api_version(desired_api_version)?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; - match (current_object, desired_api_version) { - (Self::V1Alpha1(__sv_foo), "foo.example.org/v1beta1") => { + match (current_object, &desired_api_version) { + (Self::V1Alpha1(__sv_foo), FooVersion::V1Beta1) => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Beta1(v1beta1::Foo { metadata: __sv_foo.metadata, @@ -211,7 +211,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(__sv_foo), "foo.example.org/v1") => { + (Self::V1Alpha1(__sv_foo), FooVersion::V1) => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let converted: v1::FooSpec = converted.into(); let desired_object = Self::V1(v1::Foo { @@ -225,7 +225,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Beta1(__sv_foo), "foo.example.org/v1alpha1") => { + (Self::V1Beta1(__sv_foo), FooVersion::V1Alpha1) => { let converted: v1alpha1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Alpha1(v1alpha1::Foo { metadata: __sv_foo.metadata, @@ -238,7 +238,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Beta1(__sv_foo), "foo.example.org/v1") => { + (Self::V1Beta1(__sv_foo), FooVersion::V1) => { let converted: v1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1(v1::Foo { metadata: __sv_foo.metadata, @@ -251,7 +251,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foo), "foo.example.org/v1alpha1") => { + (Self::V1(__sv_foo), FooVersion::V1Alpha1) => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let converted: v1alpha1::FooSpec = converted.into(); let desired_object = Self::V1Alpha1(v1alpha1::Foo { @@ -265,7 +265,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foo), "foo.example.org/v1beta1") => { + (Self::V1(__sv_foo), FooVersion::V1Beta1) => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Beta1(v1beta1::Foo { metadata: __sv_foo.metadata, @@ -278,19 +278,11 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), "foo.example.org/v1alpha1") => { + (Self::V1Alpha1(_), FooVersion::V1Alpha1) => { converted_objects.push(object) } - (Self::V1Beta1(_), "foo.example.org/v1beta1") => { - converted_objects.push(object) - } - (Self::V1(_), "foo.example.org/v1") => converted_objects.push(object), - (_, unknown_desired_api_version) => { - return ::std::result::Result::Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { - unknown_desired_api_version: unknown_desired_api_version - .to_string(), - }); - } + (Self::V1Beta1(_), FooVersion::V1Beta1) => converted_objects.push(object), + (Self::V1(_), FooVersion::V1) => converted_objects.push(object), } } ::std::result::Result::Ok(converted_objects) @@ -374,16 +366,37 @@ impl ::std::fmt::Display for FooVersion { &self, f: &mut ::std::fmt::Formatter<'_>, ) -> ::std::result::Result<(), ::std::fmt::Error> { - f.write_str(self.as_str()) + f.write_str(self.as_version_str()) } } #[automatically_derived] impl FooVersion { - pub fn as_str(&self) -> &str { + pub fn as_version_str(&self) -> &str { match self { V1Alpha1 => "v1alpha1", V1Beta1 => "v1beta1", V1 => "v1", } } + pub fn as_api_version_str(&self) -> &str { + match self { + V1Alpha1 => "foo.example.org/v1alpha1", + V1Beta1 => "foo.example.org/v1beta1", + V1 => "foo.example.org/v1", + } + } + pub fn try_from_api_version( + api_version: &str, + ) -> Result { + match api_version { + "foo.example.org/v1alpha1" => Ok(Self::V1Alpha1), + "foo.example.org/v1beta1" => Ok(Self::V1Beta1), + "foo.example.org/v1" => Ok(Self::V1), + _ => { + Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { + unknown_desired_api_version: api_version.to_string(), + }) + } + } + } } 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 94add4f0a..548fa7a3c 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 @@ -296,7 +296,7 @@ impl Foo { as ::kube::core::CustomResourceExt > ::crd(), < v2alpha1::Foo as ::kube::core::CustomResourceExt > ::crd() ], - stored_apiversion.as_str(), + stored_apiversion.as_version_str(), ) } ///Tries to convert a list of objects of kind [`Foo`] to the desired API version @@ -324,10 +324,9 @@ impl Foo { .into_review(); } }; - let desired_api_version = request.desired_api_version.as_str(); let response = match Self::convert_objects( request.objects, - desired_api_version, + &request.desired_api_version, ) { ::std::result::Result::Ok(converted_objects) => { ::kube::core::conversion::ConversionResponse { @@ -363,14 +362,15 @@ impl Foo { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { + let desired_api_version = FooVersion::try_from_api_version(desired_api_version)?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; - match (current_object, desired_api_version) { - (Self::V1Alpha1(__sv_foo), "foo.example.org/v1") => { + match (current_object, &desired_api_version) { + (Self::V1Alpha1(__sv_foo), FooVersion::V1) => { let converted: v1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1(v1::Foo { metadata: __sv_foo.metadata, @@ -383,7 +383,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(__sv_foo), "foo.example.org/v2alpha1") => { + (Self::V1Alpha1(__sv_foo), FooVersion::V2Alpha1) => { let converted: v1::FooSpec = __sv_foo.spec.into(); let converted: v2alpha1::FooSpec = converted.into(); let desired_object = Self::V2Alpha1(v2alpha1::Foo { @@ -397,7 +397,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foo), "foo.example.org/v1alpha1") => { + (Self::V1(__sv_foo), FooVersion::V1Alpha1) => { let converted: v1alpha1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Alpha1(v1alpha1::Foo { metadata: __sv_foo.metadata, @@ -410,7 +410,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foo), "foo.example.org/v2alpha1") => { + (Self::V1(__sv_foo), FooVersion::V2Alpha1) => { let converted: v2alpha1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V2Alpha1(v2alpha1::Foo { metadata: __sv_foo.metadata, @@ -423,7 +423,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V2Alpha1(__sv_foo), "foo.example.org/v1alpha1") => { + (Self::V2Alpha1(__sv_foo), FooVersion::V1Alpha1) => { let converted: v1::FooSpec = __sv_foo.spec.into(); let converted: v1alpha1::FooSpec = converted.into(); let desired_object = Self::V1Alpha1(v1alpha1::Foo { @@ -437,7 +437,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V2Alpha1(__sv_foo), "foo.example.org/v1") => { + (Self::V2Alpha1(__sv_foo), FooVersion::V1) => { let converted: v1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1(v1::Foo { metadata: __sv_foo.metadata, @@ -450,19 +450,13 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), "foo.example.org/v1alpha1") => { + (Self::V1Alpha1(_), FooVersion::V1Alpha1) => { converted_objects.push(object) } - (Self::V1(_), "foo.example.org/v1") => converted_objects.push(object), - (Self::V2Alpha1(_), "foo.example.org/v2alpha1") => { + (Self::V1(_), FooVersion::V1) => converted_objects.push(object), + (Self::V2Alpha1(_), FooVersion::V2Alpha1) => { converted_objects.push(object) } - (_, unknown_desired_api_version) => { - return ::std::result::Result::Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { - unknown_desired_api_version: unknown_desired_api_version - .to_string(), - }); - } } } ::std::result::Result::Ok(converted_objects) @@ -546,18 +540,39 @@ impl ::std::fmt::Display for FooVersion { &self, f: &mut ::std::fmt::Formatter<'_>, ) -> ::std::result::Result<(), ::std::fmt::Error> { - f.write_str(self.as_str()) + f.write_str(self.as_version_str()) } } #[automatically_derived] impl FooVersion { - pub fn as_str(&self) -> &str { + pub fn as_version_str(&self) -> &str { match self { V1Alpha1 => "v1alpha1", V1 => "v1", V2Alpha1 => "v2alpha1", } } + pub fn as_api_version_str(&self) -> &str { + match self { + V1Alpha1 => "foo.example.org/v1alpha1", + V1 => "foo.example.org/v1", + V2Alpha1 => "foo.example.org/v2alpha1", + } + } + pub fn try_from_api_version( + api_version: &str, + ) -> Result { + match api_version { + "foo.example.org/v1alpha1" => Ok(Self::V1Alpha1), + "foo.example.org/v1" => Ok(Self::V1), + "foo.example.org/v2alpha1" => Ok(Self::V2Alpha1), + _ => { + Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { + unknown_desired_api_version: api_version.to_string(), + }) + } + } + } } #[automatically_derived] pub(crate) enum Bar { @@ -580,7 +595,7 @@ impl Bar { as ::kube::core::CustomResourceExt > ::crd(), < v2alpha1::Bar as ::kube::core::CustomResourceExt > ::crd() ], - stored_apiversion.as_str(), + stored_apiversion.as_version_str(), ) } ///Tries to convert a list of objects of kind [`Bar`] to the desired API version @@ -608,10 +623,9 @@ impl Bar { .into_review(); } }; - let desired_api_version = request.desired_api_version.as_str(); let response = match Self::convert_objects( request.objects, - desired_api_version, + &request.desired_api_version, ) { ::std::result::Result::Ok(converted_objects) => { ::kube::core::conversion::ConversionResponse { @@ -647,14 +661,15 @@ impl Bar { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { + let desired_api_version = BarVersion::try_from_api_version(desired_api_version)?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; - match (current_object, desired_api_version) { - (Self::V1Alpha1(__sv_bar), "bar.example.org/v1") => { + match (current_object, &desired_api_version) { + (Self::V1Alpha1(__sv_bar), BarVersion::V1) => { let converted: v1::BarSpec = __sv_bar.spec.into(); let desired_object = Self::V1(v1::Bar { metadata: __sv_bar.metadata, @@ -667,7 +682,7 @@ impl Bar { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(__sv_bar), "bar.example.org/v2alpha1") => { + (Self::V1Alpha1(__sv_bar), BarVersion::V2Alpha1) => { let converted: v1::BarSpec = __sv_bar.spec.into(); let converted: v2alpha1::BarSpec = converted.into(); let desired_object = Self::V2Alpha1(v2alpha1::Bar { @@ -681,7 +696,7 @@ impl Bar { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_bar), "bar.example.org/v1alpha1") => { + (Self::V1(__sv_bar), BarVersion::V1Alpha1) => { let converted: v1alpha1::BarSpec = __sv_bar.spec.into(); let desired_object = Self::V1Alpha1(v1alpha1::Bar { metadata: __sv_bar.metadata, @@ -694,7 +709,7 @@ impl Bar { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_bar), "bar.example.org/v2alpha1") => { + (Self::V1(__sv_bar), BarVersion::V2Alpha1) => { let converted: v2alpha1::BarSpec = __sv_bar.spec.into(); let desired_object = Self::V2Alpha1(v2alpha1::Bar { metadata: __sv_bar.metadata, @@ -707,7 +722,7 @@ impl Bar { })?; converted_objects.push(desired_object); } - (Self::V2Alpha1(__sv_bar), "bar.example.org/v1alpha1") => { + (Self::V2Alpha1(__sv_bar), BarVersion::V1Alpha1) => { let converted: v1::BarSpec = __sv_bar.spec.into(); let converted: v1alpha1::BarSpec = converted.into(); let desired_object = Self::V1Alpha1(v1alpha1::Bar { @@ -721,7 +736,7 @@ impl Bar { })?; converted_objects.push(desired_object); } - (Self::V2Alpha1(__sv_bar), "bar.example.org/v1") => { + (Self::V2Alpha1(__sv_bar), BarVersion::V1) => { let converted: v1::BarSpec = __sv_bar.spec.into(); let desired_object = Self::V1(v1::Bar { metadata: __sv_bar.metadata, @@ -734,19 +749,13 @@ impl Bar { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), "bar.example.org/v1alpha1") => { + (Self::V1Alpha1(_), BarVersion::V1Alpha1) => { converted_objects.push(object) } - (Self::V1(_), "bar.example.org/v1") => converted_objects.push(object), - (Self::V2Alpha1(_), "bar.example.org/v2alpha1") => { + (Self::V1(_), BarVersion::V1) => converted_objects.push(object), + (Self::V2Alpha1(_), BarVersion::V2Alpha1) => { converted_objects.push(object) } - (_, unknown_desired_api_version) => { - return ::std::result::Result::Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { - unknown_desired_api_version: unknown_desired_api_version - .to_string(), - }); - } } } ::std::result::Result::Ok(converted_objects) @@ -830,16 +839,37 @@ impl ::std::fmt::Display for BarVersion { &self, f: &mut ::std::fmt::Formatter<'_>, ) -> ::std::result::Result<(), ::std::fmt::Error> { - f.write_str(self.as_str()) + f.write_str(self.as_version_str()) } } #[automatically_derived] impl BarVersion { - pub fn as_str(&self) -> &str { + pub fn as_version_str(&self) -> &str { match self { V1Alpha1 => "v1alpha1", V1 => "v1", V2Alpha1 => "v2alpha1", } } + pub fn as_api_version_str(&self) -> &str { + match self { + V1Alpha1 => "bar.example.org/v1alpha1", + V1 => "bar.example.org/v1", + V2Alpha1 => "bar.example.org/v2alpha1", + } + } + pub fn try_from_api_version( + api_version: &str, + ) -> Result { + match api_version { + "bar.example.org/v1alpha1" => Ok(Self::V1Alpha1), + "bar.example.org/v1" => Ok(Self::V1), + "bar.example.org/v2alpha1" => Ok(Self::V2Alpha1), + _ => { + Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { + unknown_desired_api_version: api_version.to_string(), + }) + } + } + } } 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 50c879247..0475670fc 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 @@ -277,7 +277,7 @@ pub(crate) mod versioned { v1::Foo as ::kube::core::CustomResourceExt > ::crd(), < v2alpha1::Foo as ::kube::core::CustomResourceExt > ::crd() ], - stored_apiversion.as_str(), + stored_apiversion.as_version_str(), ) } ///Tries to convert a list of objects of kind [`Foo`] to the desired API version @@ -305,10 +305,9 @@ pub(crate) mod versioned { .into_review(); } }; - let desired_api_version = request.desired_api_version.as_str(); let response = match Self::convert_objects( request.objects, - desired_api_version, + &request.desired_api_version, ) { ::std::result::Result::Ok(converted_objects) => { ::kube::core::conversion::ConversionResponse { @@ -344,14 +343,17 @@ pub(crate) mod versioned { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { + let desired_api_version = FooVersion::try_from_api_version( + desired_api_version, + )?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; - match (current_object, desired_api_version) { - (Self::V1Alpha1(__sv_foo), "foo.example.org/v1") => { + match (current_object, &desired_api_version) { + (Self::V1Alpha1(__sv_foo), FooVersion::V1) => { let converted: v1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1(v1::Foo { metadata: __sv_foo.metadata, @@ -364,7 +366,7 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(__sv_foo), "foo.example.org/v2alpha1") => { + (Self::V1Alpha1(__sv_foo), FooVersion::V2Alpha1) => { let converted: v1::FooSpec = __sv_foo.spec.into(); let converted: v2alpha1::FooSpec = converted.into(); let desired_object = Self::V2Alpha1(v2alpha1::Foo { @@ -378,7 +380,7 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foo), "foo.example.org/v1alpha1") => { + (Self::V1(__sv_foo), FooVersion::V1Alpha1) => { let converted: v1alpha1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Alpha1(v1alpha1::Foo { metadata: __sv_foo.metadata, @@ -391,7 +393,7 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foo), "foo.example.org/v2alpha1") => { + (Self::V1(__sv_foo), FooVersion::V2Alpha1) => { let converted: v2alpha1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V2Alpha1(v2alpha1::Foo { metadata: __sv_foo.metadata, @@ -404,7 +406,7 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V2Alpha1(__sv_foo), "foo.example.org/v1alpha1") => { + (Self::V2Alpha1(__sv_foo), FooVersion::V1Alpha1) => { let converted: v1::FooSpec = __sv_foo.spec.into(); let converted: v1alpha1::FooSpec = converted.into(); let desired_object = Self::V1Alpha1(v1alpha1::Foo { @@ -418,7 +420,7 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V2Alpha1(__sv_foo), "foo.example.org/v1") => { + (Self::V2Alpha1(__sv_foo), FooVersion::V1) => { let converted: v1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1(v1::Foo { metadata: __sv_foo.metadata, @@ -431,19 +433,13 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), "foo.example.org/v1alpha1") => { + (Self::V1Alpha1(_), FooVersion::V1Alpha1) => { converted_objects.push(object) } - (Self::V1(_), "foo.example.org/v1") => converted_objects.push(object), - (Self::V2Alpha1(_), "foo.example.org/v2alpha1") => { + (Self::V1(_), FooVersion::V1) => converted_objects.push(object), + (Self::V2Alpha1(_), FooVersion::V2Alpha1) => { converted_objects.push(object) } - (_, unknown_desired_api_version) => { - return ::std::result::Result::Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { - unknown_desired_api_version: unknown_desired_api_version - .to_string(), - }); - } } } ::std::result::Result::Ok(converted_objects) @@ -525,17 +521,38 @@ pub(crate) mod versioned { &self, f: &mut ::std::fmt::Formatter<'_>, ) -> ::std::result::Result<(), ::std::fmt::Error> { - f.write_str(self.as_str()) + f.write_str(self.as_version_str()) } } impl FooVersion { - pub fn as_str(&self) -> &str { + pub fn as_version_str(&self) -> &str { match self { V1Alpha1 => "v1alpha1", V1 => "v1", V2Alpha1 => "v2alpha1", } } + pub fn as_api_version_str(&self) -> &str { + match self { + V1Alpha1 => "foo.example.org/v1alpha1", + V1 => "foo.example.org/v1", + V2Alpha1 => "foo.example.org/v2alpha1", + } + } + pub fn try_from_api_version( + api_version: &str, + ) -> Result { + match api_version { + "foo.example.org/v1alpha1" => Ok(Self::V1Alpha1), + "foo.example.org/v1" => Ok(Self::V1), + "foo.example.org/v2alpha1" => Ok(Self::V2Alpha1), + _ => { + Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { + unknown_desired_api_version: api_version.to_string(), + }) + } + } + } } pub enum Bar { V1Alpha1(v1alpha1::Bar), @@ -556,7 +573,7 @@ pub(crate) mod versioned { v1::Bar as ::kube::core::CustomResourceExt > ::crd(), < v2alpha1::Bar as ::kube::core::CustomResourceExt > ::crd() ], - stored_apiversion.as_str(), + stored_apiversion.as_version_str(), ) } ///Tries to convert a list of objects of kind [`Bar`] to the desired API version @@ -584,10 +601,9 @@ pub(crate) mod versioned { .into_review(); } }; - let desired_api_version = request.desired_api_version.as_str(); let response = match Self::convert_objects( request.objects, - desired_api_version, + &request.desired_api_version, ) { ::std::result::Result::Ok(converted_objects) => { ::kube::core::conversion::ConversionResponse { @@ -623,14 +639,17 @@ pub(crate) mod versioned { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { + let desired_api_version = BarVersion::try_from_api_version( + desired_api_version, + )?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; - match (current_object, desired_api_version) { - (Self::V1Alpha1(__sv_bar), "bar.example.org/v1") => { + match (current_object, &desired_api_version) { + (Self::V1Alpha1(__sv_bar), BarVersion::V1) => { let converted: v1::BarSpec = __sv_bar.spec.into(); let desired_object = Self::V1(v1::Bar { metadata: __sv_bar.metadata, @@ -643,7 +662,7 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(__sv_bar), "bar.example.org/v2alpha1") => { + (Self::V1Alpha1(__sv_bar), BarVersion::V2Alpha1) => { let converted: v1::BarSpec = __sv_bar.spec.into(); let converted: v2alpha1::BarSpec = converted.into(); let desired_object = Self::V2Alpha1(v2alpha1::Bar { @@ -657,7 +676,7 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_bar), "bar.example.org/v1alpha1") => { + (Self::V1(__sv_bar), BarVersion::V1Alpha1) => { let converted: v1alpha1::BarSpec = __sv_bar.spec.into(); let desired_object = Self::V1Alpha1(v1alpha1::Bar { metadata: __sv_bar.metadata, @@ -670,7 +689,7 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_bar), "bar.example.org/v2alpha1") => { + (Self::V1(__sv_bar), BarVersion::V2Alpha1) => { let converted: v2alpha1::BarSpec = __sv_bar.spec.into(); let desired_object = Self::V2Alpha1(v2alpha1::Bar { metadata: __sv_bar.metadata, @@ -683,7 +702,7 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V2Alpha1(__sv_bar), "bar.example.org/v1alpha1") => { + (Self::V2Alpha1(__sv_bar), BarVersion::V1Alpha1) => { let converted: v1::BarSpec = __sv_bar.spec.into(); let converted: v1alpha1::BarSpec = converted.into(); let desired_object = Self::V1Alpha1(v1alpha1::Bar { @@ -697,7 +716,7 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V2Alpha1(__sv_bar), "bar.example.org/v1") => { + (Self::V2Alpha1(__sv_bar), BarVersion::V1) => { let converted: v1::BarSpec = __sv_bar.spec.into(); let desired_object = Self::V1(v1::Bar { metadata: __sv_bar.metadata, @@ -710,19 +729,13 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), "bar.example.org/v1alpha1") => { + (Self::V1Alpha1(_), BarVersion::V1Alpha1) => { converted_objects.push(object) } - (Self::V1(_), "bar.example.org/v1") => converted_objects.push(object), - (Self::V2Alpha1(_), "bar.example.org/v2alpha1") => { + (Self::V1(_), BarVersion::V1) => converted_objects.push(object), + (Self::V2Alpha1(_), BarVersion::V2Alpha1) => { converted_objects.push(object) } - (_, unknown_desired_api_version) => { - return ::std::result::Result::Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { - unknown_desired_api_version: unknown_desired_api_version - .to_string(), - }); - } } } ::std::result::Result::Ok(converted_objects) @@ -804,16 +817,37 @@ pub(crate) mod versioned { &self, f: &mut ::std::fmt::Formatter<'_>, ) -> ::std::result::Result<(), ::std::fmt::Error> { - f.write_str(self.as_str()) + f.write_str(self.as_version_str()) } } impl BarVersion { - pub fn as_str(&self) -> &str { + pub fn as_version_str(&self) -> &str { match self { V1Alpha1 => "v1alpha1", V1 => "v1", V2Alpha1 => "v2alpha1", } } + pub fn as_api_version_str(&self) -> &str { + match self { + V1Alpha1 => "bar.example.org/v1alpha1", + V1 => "bar.example.org/v1", + V2Alpha1 => "bar.example.org/v2alpha1", + } + } + pub fn try_from_api_version( + api_version: &str, + ) -> Result { + match api_version { + "bar.example.org/v1alpha1" => Ok(Self::V1Alpha1), + "bar.example.org/v1" => Ok(Self::V1), + "bar.example.org/v2alpha1" => Ok(Self::V2Alpha1), + _ => { + Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { + unknown_desired_api_version: api_version.to_string(), + }) + } + } + } } } 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 e1fd61079..edbffe026 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 @@ -109,7 +109,7 @@ impl FooBar { v1beta1::FooBar as ::kube::core::CustomResourceExt > ::crd(), < v1::FooBar as ::kube::core::CustomResourceExt > ::crd() ], - stored_apiversion.as_str(), + stored_apiversion.as_version_str(), ) } ///Tries to convert a list of objects of kind [`FooBar`] to the desired API version @@ -137,10 +137,9 @@ impl FooBar { .into_review(); } }; - let desired_api_version = request.desired_api_version.as_str(); let response = match Self::convert_objects( request.objects, - desired_api_version, + &request.desired_api_version, ) { ::std::result::Result::Ok(converted_objects) => { ::kube::core::conversion::ConversionResponse { @@ -176,14 +175,17 @@ impl FooBar { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { + let desired_api_version = FooBarVersion::try_from_api_version( + desired_api_version, + )?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; - match (current_object, desired_api_version) { - (Self::V1Alpha1(__sv_foobar), "stackable.tech/v1beta1") => { + match (current_object, &desired_api_version) { + (Self::V1Alpha1(__sv_foobar), FooBarVersion::V1Beta1) => { let converted: v1beta1::FooSpec = __sv_foobar.spec.into(); let desired_object = Self::V1Beta1(v1beta1::FooBar { metadata: __sv_foobar.metadata, @@ -196,7 +198,7 @@ impl FooBar { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(__sv_foobar), "stackable.tech/v1") => { + (Self::V1Alpha1(__sv_foobar), FooBarVersion::V1) => { let converted: v1beta1::FooSpec = __sv_foobar.spec.into(); let converted: v1::FooSpec = converted.into(); let desired_object = Self::V1(v1::FooBar { @@ -210,7 +212,7 @@ impl FooBar { })?; converted_objects.push(desired_object); } - (Self::V1Beta1(__sv_foobar), "stackable.tech/v1alpha1") => { + (Self::V1Beta1(__sv_foobar), FooBarVersion::V1Alpha1) => { let converted: v1alpha1::FooSpec = __sv_foobar.spec.into(); let desired_object = Self::V1Alpha1(v1alpha1::FooBar { metadata: __sv_foobar.metadata, @@ -223,7 +225,7 @@ impl FooBar { })?; converted_objects.push(desired_object); } - (Self::V1Beta1(__sv_foobar), "stackable.tech/v1") => { + (Self::V1Beta1(__sv_foobar), FooBarVersion::V1) => { let converted: v1::FooSpec = __sv_foobar.spec.into(); let desired_object = Self::V1(v1::FooBar { metadata: __sv_foobar.metadata, @@ -236,7 +238,7 @@ impl FooBar { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foobar), "stackable.tech/v1alpha1") => { + (Self::V1(__sv_foobar), FooBarVersion::V1Alpha1) => { let converted: v1beta1::FooSpec = __sv_foobar.spec.into(); let converted: v1alpha1::FooSpec = converted.into(); let desired_object = Self::V1Alpha1(v1alpha1::FooBar { @@ -250,7 +252,7 @@ impl FooBar { })?; converted_objects.push(desired_object); } - (Self::V1(__sv_foobar), "stackable.tech/v1beta1") => { + (Self::V1(__sv_foobar), FooBarVersion::V1Beta1) => { let converted: v1beta1::FooSpec = __sv_foobar.spec.into(); let desired_object = Self::V1Beta1(v1beta1::FooBar { metadata: __sv_foobar.metadata, @@ -263,19 +265,13 @@ impl FooBar { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), "stackable.tech/v1alpha1") => { + (Self::V1Alpha1(_), FooBarVersion::V1Alpha1) => { converted_objects.push(object) } - (Self::V1Beta1(_), "stackable.tech/v1beta1") => { + (Self::V1Beta1(_), FooBarVersion::V1Beta1) => { converted_objects.push(object) } - (Self::V1(_), "stackable.tech/v1") => converted_objects.push(object), - (_, unknown_desired_api_version) => { - return ::std::result::Result::Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { - unknown_desired_api_version: unknown_desired_api_version - .to_string(), - }); - } + (Self::V1(_), FooBarVersion::V1) => converted_objects.push(object), } } ::std::result::Result::Ok(converted_objects) @@ -359,16 +355,37 @@ impl ::std::fmt::Display for FooBarVersion { &self, f: &mut ::std::fmt::Formatter<'_>, ) -> ::std::result::Result<(), ::std::fmt::Error> { - f.write_str(self.as_str()) + f.write_str(self.as_version_str()) } } #[automatically_derived] impl FooBarVersion { - pub fn as_str(&self) -> &str { + pub fn as_version_str(&self) -> &str { match self { V1Alpha1 => "v1alpha1", V1Beta1 => "v1beta1", V1 => "v1", } } + pub fn as_api_version_str(&self) -> &str { + match self { + V1Alpha1 => "stackable.tech/v1alpha1", + V1Beta1 => "stackable.tech/v1beta1", + V1 => "stackable.tech/v1", + } + } + pub fn try_from_api_version( + api_version: &str, + ) -> Result { + match api_version { + "stackable.tech/v1alpha1" => Ok(Self::V1Alpha1), + "stackable.tech/v1beta1" => Ok(Self::V1Beta1), + "stackable.tech/v1" => Ok(Self::V1), + _ => { + Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { + unknown_desired_api_version: api_version.to_string(), + }) + } + } + } } 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 b1d019f85..dd30e1a0d 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 @@ -38,7 +38,7 @@ impl Foo { > { ::kube::core::crd::merge_crds( vec![< v1alpha1::Foo as ::kube::core::CustomResourceExt > ::crd()], - stored_apiversion.as_str(), + stored_apiversion.as_version_str(), ) } ///Tries to convert a list of objects of kind [`Foo`] to the desired API version @@ -66,10 +66,9 @@ impl Foo { .into_review(); } }; - let desired_api_version = request.desired_api_version.as_str(); let response = match Self::convert_objects( request.objects, - desired_api_version, + &request.desired_api_version, ) { ::std::result::Result::Ok(converted_objects) => { ::kube::core::conversion::ConversionResponse { @@ -105,22 +104,17 @@ impl Foo { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { + let desired_api_version = FooVersion::try_from_api_version(desired_api_version)?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { let current_object = Self::from_json_value(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; - match (current_object, desired_api_version) { - (Self::V1Alpha1(_), "stackable.tech/v1alpha1") => { + match (current_object, &desired_api_version) { + (Self::V1Alpha1(_), FooVersion::V1Alpha1) => { converted_objects.push(object) } - (_, unknown_desired_api_version) => { - return ::std::result::Result::Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { - unknown_desired_api_version: unknown_desired_api_version - .to_string(), - }); - } } } ::std::result::Result::Ok(converted_objects) @@ -186,14 +180,31 @@ impl ::std::fmt::Display for FooVersion { &self, f: &mut ::std::fmt::Formatter<'_>, ) -> ::std::result::Result<(), ::std::fmt::Error> { - f.write_str(self.as_str()) + f.write_str(self.as_version_str()) } } #[automatically_derived] impl FooVersion { - pub fn as_str(&self) -> &str { + pub fn as_version_str(&self) -> &str { match self { V1Alpha1 => "v1alpha1", } } + pub fn as_api_version_str(&self) -> &str { + match self { + V1Alpha1 => "stackable.tech/v1alpha1", + } + } + pub fn try_from_api_version( + api_version: &str, + ) -> Result { + match api_version { + "stackable.tech/v1alpha1" => Ok(Self::V1Alpha1), + _ => { + Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { + unknown_desired_api_version: api_version.to_string(), + }) + } + } + } } From 95a10ae8e576bc06ed1774ebac16cac63ccbc04d Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Tue, 24 Jun 2025 09:03:23 +0200 Subject: [PATCH 11/33] Remove leftover comment --- .../src/codegen/container/struct/k8s.rs | 1 - 1 file changed, 1 deletion(-) 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 4eddb6137..4a4d7ac3f 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -467,7 +467,6 @@ impl Struct { -> ::std::result::Result<::std::vec::Vec<#serde_json_path::Value>, #convert_object_error> { let desired_api_version = #version_enum_ident::try_from_api_version(desired_api_version)?; - // let desired_api_version: #version_enum_ident = desired_api_version.try_into()?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); From 9acd9120e77811ce1a2f76db1fad46f8e094e47a Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Tue, 24 Jun 2025 09:10:40 +0200 Subject: [PATCH 12/33] Update crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs Co-authored-by: Nick <10092581+NickLarsenNZ@users.noreply.github.com> --- .../src/codegen/container/struct/k8s.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) 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 4a4d7ac3f..eaa11b752 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -186,9 +186,11 @@ impl Struct { .as_str() .ok_or_else(|| #parse_object_error::FieldNotStr{ field: "kind".to_string() })?; - // Note(@sbernauer): One could argue we don't need to check the kind, but this - // is a nice sanity check. If for *some* reason a unexpected kind ends up at a - // conversion, the problem might be very hard to spot without this. + // Note(@sbernauer): The kind must be checked here, because it is + // possible for the wrong object to be deserialized. + // Checking here stops us assuming the kind is correct and + // accidentally updating upgrade/downgrade information in the + // status in a later step. if object_kind != stringify!(#enum_ident) { return Err(#parse_object_error::UnexpectedObjectKind{ kind: object_kind.to_string(), From 129d6b4a1bd921b65587ae53adeaba940d44cca3 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Tue, 24 Jun 2025 10:51:21 +0200 Subject: [PATCH 13/33] Update crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs Co-authored-by: Techassi --- .../src/codegen/container/struct/k8s.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 eaa11b752..85c16d7c4 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -516,7 +516,7 @@ impl Struct { let desired_object_version = path.last().expect("the path always contains at least one element"); let desired_object_api_version_string = format!( "{group}/{desired_object_version}", - desired_object_version= desired_object_version.inner + desired_object_version = desired_object_version.inner ); let desired_object_variant_ident = &desired_object_version.idents.variant; let desired_object_module_ident = &desired_object_version.idents.module; From 58b330b17b766cd727cc89dc62e53c1908d3d9c3 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Tue, 24 Jun 2025 11:16:04 +0200 Subject: [PATCH 14/33] Avoid stringify! --- .../src/codegen/container/struct/k8s.rs | 5 +++-- ...le_versioned_macros__snapshot_tests__k8s@basic.rs.snap | 4 ++-- ...acros__snapshot_tests__k8s@conversion_tracking.rs.snap | 4 ++-- ...ed_macros__snapshot_tests__k8s@crate_overrides.rs.snap | 4 ++-- ...e_versioned_macros__snapshot_tests__k8s@module.rs.snap | 8 ++++---- ...ed_macros__snapshot_tests__k8s@module_preserve.rs.snap | 8 ++++---- ...ioned_macros__snapshot_tests__k8s@renamed_kind.rs.snap | 4 ++-- ...rsioned_macros__snapshot_tests__k8s@shortnames.rs.snap | 4 ++-- 8 files changed, 21 insertions(+), 20 deletions(-) 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 85c16d7c4..8ec8bd7c7 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -129,6 +129,7 @@ impl Struct { let variant_data_ident = &self.common.idents.kubernetes_parameter; let version_enum_ident = &self.common.idents.kubernetes_version; let enum_ident = &self.common.idents.kubernetes; + let enum_ident_string = enum_ident.to_string(); // Only add the #[automatically_derived] attribute if this impl is used outside of a // module (in standalone mode). @@ -191,10 +192,10 @@ impl Struct { // Checking here stops us assuming the kind is correct and // accidentally updating upgrade/downgrade information in the // status in a later step. - if object_kind != stringify!(#enum_ident) { + if object_kind != #enum_ident_string { return Err(#parse_object_error::UnexpectedObjectKind{ kind: object_kind.to_string(), - supported_kind: stringify!(#enum_ident).to_string(), + supported_kind: #enum_ident_string.to_string(), }); } 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 7c10871c9..7f41b9002 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 @@ -314,10 +314,10 @@ impl Foo { .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { field: "kind".to_string(), })?; - if object_kind != stringify!(Foo) { + if object_kind != "Foo" { return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { kind: object_kind.to_string(), - supported_kind: stringify!(Foo).to_string(), + supported_kind: "Foo".to_string(), }); } let api_version = object 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 572cb391b..8cdf80c7b 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 @@ -284,10 +284,10 @@ impl Foo { .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { field: "kind".to_string(), })?; - if object_kind != stringify!(Foo) { + if object_kind != "Foo" { return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { kind: object_kind.to_string(), - supported_kind: stringify!(Foo).to_string(), + supported_kind: "Foo".to_string(), }); } let api_version = object 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 23da00c91..18e0f9dae 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 @@ -299,10 +299,10 @@ impl Foo { .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { field: "kind".to_string(), })?; - if object_kind != stringify!(Foo) { + if object_kind != "Foo" { return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { kind: object_kind.to_string(), - supported_kind: stringify!(Foo).to_string(), + supported_kind: "Foo".to_string(), }); } let api_version = object 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 548fa7a3c..773b737bf 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 @@ -473,10 +473,10 @@ impl Foo { .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { field: "kind".to_string(), })?; - if object_kind != stringify!(Foo) { + if object_kind != "Foo" { return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { kind: object_kind.to_string(), - supported_kind: stringify!(Foo).to_string(), + supported_kind: "Foo".to_string(), }); } let api_version = object @@ -772,10 +772,10 @@ impl Bar { .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { field: "kind".to_string(), })?; - if object_kind != stringify!(Bar) { + if object_kind != "Bar" { return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { kind: object_kind.to_string(), - supported_kind: stringify!(Bar).to_string(), + supported_kind: "Bar".to_string(), }); } let api_version = object 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 0475670fc..02ad2aaaf 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 @@ -456,10 +456,10 @@ pub(crate) mod versioned { .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { field: "kind".to_string(), })?; - if object_kind != stringify!(Foo) { + if object_kind != "Foo" { return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { kind: object_kind.to_string(), - supported_kind: stringify!(Foo).to_string(), + supported_kind: "Foo".to_string(), }); } let api_version = object @@ -752,10 +752,10 @@ pub(crate) mod versioned { .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { field: "kind".to_string(), })?; - if object_kind != stringify!(Bar) { + if object_kind != "Bar" { return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { kind: object_kind.to_string(), - supported_kind: stringify!(Bar).to_string(), + supported_kind: "Bar".to_string(), }); } let api_version = object 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 edbffe026..7c3c6db01 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 @@ -288,10 +288,10 @@ impl FooBar { .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { field: "kind".to_string(), })?; - if object_kind != stringify!(FooBar) { + if object_kind != "FooBar" { return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { kind: object_kind.to_string(), - supported_kind: stringify!(FooBar).to_string(), + supported_kind: "FooBar".to_string(), }); } let api_version = object 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 dd30e1a0d..4c3c8e768 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 @@ -131,10 +131,10 @@ impl Foo { .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { field: "kind".to_string(), })?; - if object_kind != stringify!(Foo) { + if object_kind != "Foo" { return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { kind: object_kind.to_string(), - supported_kind: stringify!(Foo).to_string(), + supported_kind: "Foo".to_string(), }); } let api_version = object From d5a3109cf06a15120d3a354b8e650a740d4a103f Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Tue, 24 Jun 2025 11:19:02 +0200 Subject: [PATCH 15/33] adopt unexpected kind error message --- .../src/codegen/container/struct/k8s.rs | 4 ++-- crates/stackable-versioned/src/k8s.rs | 9 ++------- ...stackable_versioned__tests__fail@wrong_kind.json.snap | 4 ++-- 3 files changed, 6 insertions(+), 11 deletions(-) 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 8ec8bd7c7..2b9336377 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -193,9 +193,9 @@ impl Struct { // accidentally updating upgrade/downgrade information in the // status in a later step. if object_kind != #enum_ident_string { - return Err(#parse_object_error::UnexpectedObjectKind{ + return Err(#parse_object_error::UnexpectedKind{ kind: object_kind.to_string(), - supported_kind: #enum_ident_string.to_string(), + expected: #enum_ident_string.to_string(), }); } diff --git a/crates/stackable-versioned/src/k8s.rs b/crates/stackable-versioned/src/k8s.rs index d4f0152af..3430bb13d 100644 --- a/crates/stackable-versioned/src/k8s.rs +++ b/crates/stackable-versioned/src/k8s.rs @@ -59,13 +59,8 @@ pub enum ParseObjectError { #[snafu(display("failed to deserialize object from JSON"))] Deserialize { source: serde_json::Error }, - #[snafu(display( - "unexpected object kind {kind:?}. The conversion can only convert objects of kind {supported_kind:?}" - ))] - UnexpectedObjectKind { - kind: String, - supported_kind: String, - }, + #[snafu(display("unexpected object kind {kind:?}, expected {expected:?}"))] + UnexpectedKind { kind: String, expected: String }, } /// This error indicates that converting an object from a conversion review to the desired diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@wrong_kind.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@wrong_kind.json.snap index 019baa096..9a836aa66 100644 --- a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@wrong_kind.json.snap +++ b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@wrong_kind.json.snap @@ -11,8 +11,8 @@ input_file: crates/stackable-versioned/src/tests/fixtures/inputs/fail/wrong_kind "result": { "status": "Failure", "code": 400, - "message": "failed to parse object: unexpected object kind \"SomeOtherResource\". The conversion can only convert objects of kind \"Person\"", - "reason": "failed to parse object: unexpected object kind \"SomeOtherResource\". The conversion can only convert objects of kind \"Person\"" + "message": "failed to parse object: unexpected object kind \"SomeOtherResource\", expected \"Person\"", + "reason": "failed to parse object: unexpected object kind \"SomeOtherResource\", expected \"Person\"" }, "convertedObjects": [] } From 4364c539840a0ccee37c1c47501b4378ec4ba861 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Tue, 24 Jun 2025 11:41:13 +0200 Subject: [PATCH 16/33] Add ParseApiVersionError variant --- .../src/codegen/container/struct/k8s.rs | 11 +++--- ..._macros__snapshot_tests__k8s@basic.rs.snap | 15 ++++---- ...hot_tests__k8s@conversion_tracking.rs.snap | 15 ++++---- ...napshot_tests__k8s@crate_overrides.rs.snap | 15 ++++---- ...macros__snapshot_tests__k8s@module.rs.snap | 30 +++++++++------- ...napshot_tests__k8s@module_preserve.rs.snap | 34 +++++++++++-------- ...__snapshot_tests__k8s@renamed_kind.rs.snap | 17 ++++++---- ...os__snapshot_tests__k8s@shortnames.rs.snap | 15 ++++---- crates/stackable-versioned/src/k8s.rs | 16 +++++++-- ...sts__fail@unkown_desired_version.json.snap | 4 +-- 10 files changed, 105 insertions(+), 67 deletions(-) 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 2b9336377..5bdb51b15 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -250,7 +250,7 @@ impl Struct { let automatically_derived = is_nested.not().then(|| quote! {#[automatically_derived]}); let versioned_path = &*kubernetes_arguments.crates.versioned; - let convert_object_error = quote! { #versioned_path::ConvertObjectError }; + let parse_api_version_error = quote! { #versioned_path::ParseApiVersionError }; // Get the per-version items to be able to iterate over them via quote let variant_strings = &tokens.variant_strings; @@ -288,11 +288,11 @@ impl Struct { } } - pub fn try_from_api_version(api_version: &str) -> Result { + pub fn try_from_api_version(api_version: &str) -> Result { match api_version { #(#api_versions => Ok(Self::#variant_idents)),*, - _ => Err(#convert_object_error::DesiredApiVersionUnknown { - unknown_desired_api_version: api_version.to_string(), + _ => Err(#parse_api_version_error::UnknownVersion { + api_version: api_version.to_string(), }), } } @@ -469,7 +469,8 @@ impl Struct { ) -> ::std::result::Result<::std::vec::Vec<#serde_json_path::Value>, #convert_object_error> { - let desired_api_version = #version_enum_ident::try_from_api_version(desired_api_version)?; + let desired_api_version = #version_enum_ident::try_from_api_version(desired_api_version) + .map_err(|source| #convert_object_error::ParseDesiredApiVersion { source })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); 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 7f41b9002..3be0184bc 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 @@ -199,7 +199,10 @@ impl Foo { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { - let desired_api_version = FooVersion::try_from_api_version(desired_api_version)?; + let desired_api_version = FooVersion::try_from_api_version(desired_api_version) + .map_err(|source| ::stackable_versioned::ConvertObjectError::ParseDesiredApiVersion { + source, + })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { let current_object = Self::from_json_value(object.clone()) @@ -315,9 +318,9 @@ impl Foo { field: "kind".to_string(), })?; if object_kind != "Foo" { - return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { + return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { kind: object_kind.to_string(), - supported_kind: "Foo".to_string(), + expected: "Foo".to_string(), }); } let api_version = object @@ -402,14 +405,14 @@ impl FooVersion { } pub fn try_from_api_version( api_version: &str, - ) -> Result { + ) -> Result { match api_version { "stackable.tech/v1alpha1" => Ok(Self::V1Alpha1), "stackable.tech/v1beta1" => Ok(Self::V1Beta1), "stackable.tech/v1" => Ok(Self::V1), _ => { - Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { - unknown_desired_api_version: api_version.to_string(), + Err(::stackable_versioned::ParseApiVersionError::UnknownVersion { + api_version: api_version.to_string(), }) } } 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 8cdf80c7b..1b58df29b 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 @@ -169,7 +169,10 @@ impl Foo { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { - let desired_api_version = FooVersion::try_from_api_version(desired_api_version)?; + let desired_api_version = FooVersion::try_from_api_version(desired_api_version) + .map_err(|source| ::stackable_versioned::ConvertObjectError::ParseDesiredApiVersion { + source, + })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { let current_object = Self::from_json_value(object.clone()) @@ -285,9 +288,9 @@ impl Foo { field: "kind".to_string(), })?; if object_kind != "Foo" { - return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { + return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { kind: object_kind.to_string(), - supported_kind: "Foo".to_string(), + expected: "Foo".to_string(), }); } let api_version = object @@ -372,14 +375,14 @@ impl FooVersion { } pub fn try_from_api_version( api_version: &str, - ) -> Result { + ) -> Result { match api_version { "stackable.tech/v1alpha1" => Ok(Self::V1Alpha1), "stackable.tech/v1beta1" => Ok(Self::V1Beta1), "stackable.tech/v1" => Ok(Self::V1), _ => { - Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { - unknown_desired_api_version: api_version.to_string(), + Err(::stackable_versioned::ParseApiVersionError::UnknownVersion { + api_version: api_version.to_string(), }) } } 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 18e0f9dae..f8f6b530e 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 @@ -190,7 +190,10 @@ impl Foo { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { - let desired_api_version = FooVersion::try_from_api_version(desired_api_version)?; + let desired_api_version = FooVersion::try_from_api_version(desired_api_version) + .map_err(|source| ::stackable_versioned::ConvertObjectError::ParseDesiredApiVersion { + source, + })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { let current_object = Self::from_json_value(object.clone()) @@ -300,9 +303,9 @@ impl Foo { field: "kind".to_string(), })?; if object_kind != "Foo" { - return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { + return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { kind: object_kind.to_string(), - supported_kind: "Foo".to_string(), + expected: "Foo".to_string(), }); } let api_version = object @@ -387,14 +390,14 @@ impl FooVersion { } pub fn try_from_api_version( api_version: &str, - ) -> Result { + ) -> Result { match api_version { "foo.example.org/v1alpha1" => Ok(Self::V1Alpha1), "foo.example.org/v1beta1" => Ok(Self::V1Beta1), "foo.example.org/v1" => Ok(Self::V1), _ => { - Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { - unknown_desired_api_version: api_version.to_string(), + Err(::stackable_versioned::ParseApiVersionError::UnknownVersion { + api_version: api_version.to_string(), }) } } 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 773b737bf..0c2aa8827 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 @@ -362,7 +362,10 @@ impl Foo { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { - let desired_api_version = FooVersion::try_from_api_version(desired_api_version)?; + let desired_api_version = FooVersion::try_from_api_version(desired_api_version) + .map_err(|source| ::stackable_versioned::ConvertObjectError::ParseDesiredApiVersion { + source, + })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { let current_object = Self::from_json_value(object.clone()) @@ -474,9 +477,9 @@ impl Foo { field: "kind".to_string(), })?; if object_kind != "Foo" { - return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { + return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { kind: object_kind.to_string(), - supported_kind: "Foo".to_string(), + expected: "Foo".to_string(), }); } let api_version = object @@ -561,14 +564,14 @@ impl FooVersion { } pub fn try_from_api_version( api_version: &str, - ) -> Result { + ) -> Result { match api_version { "foo.example.org/v1alpha1" => Ok(Self::V1Alpha1), "foo.example.org/v1" => Ok(Self::V1), "foo.example.org/v2alpha1" => Ok(Self::V2Alpha1), _ => { - Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { - unknown_desired_api_version: api_version.to_string(), + Err(::stackable_versioned::ParseApiVersionError::UnknownVersion { + api_version: api_version.to_string(), }) } } @@ -661,7 +664,10 @@ impl Bar { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { - let desired_api_version = BarVersion::try_from_api_version(desired_api_version)?; + let desired_api_version = BarVersion::try_from_api_version(desired_api_version) + .map_err(|source| ::stackable_versioned::ConvertObjectError::ParseDesiredApiVersion { + source, + })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { let current_object = Self::from_json_value(object.clone()) @@ -773,9 +779,9 @@ impl Bar { field: "kind".to_string(), })?; if object_kind != "Bar" { - return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { + return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { kind: object_kind.to_string(), - supported_kind: "Bar".to_string(), + expected: "Bar".to_string(), }); } let api_version = object @@ -860,14 +866,14 @@ impl BarVersion { } pub fn try_from_api_version( api_version: &str, - ) -> Result { + ) -> Result { match api_version { "bar.example.org/v1alpha1" => Ok(Self::V1Alpha1), "bar.example.org/v1" => Ok(Self::V1), "bar.example.org/v2alpha1" => Ok(Self::V2Alpha1), _ => { - Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { - unknown_desired_api_version: api_version.to_string(), + Err(::stackable_versioned::ParseApiVersionError::UnknownVersion { + api_version: api_version.to_string(), }) } } 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 02ad2aaaf..22e8a0653 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 @@ -344,8 +344,11 @@ pub(crate) mod versioned { ::stackable_versioned::ConvertObjectError, > { let desired_api_version = FooVersion::try_from_api_version( - desired_api_version, - )?; + desired_api_version, + ) + .map_err(|source| ::stackable_versioned::ConvertObjectError::ParseDesiredApiVersion { + source, + })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { let current_object = Self::from_json_value(object.clone()) @@ -457,9 +460,9 @@ pub(crate) mod versioned { field: "kind".to_string(), })?; if object_kind != "Foo" { - return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { + return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { kind: object_kind.to_string(), - supported_kind: "Foo".to_string(), + expected: "Foo".to_string(), }); } let api_version = object @@ -541,14 +544,14 @@ pub(crate) mod versioned { } pub fn try_from_api_version( api_version: &str, - ) -> Result { + ) -> Result { match api_version { "foo.example.org/v1alpha1" => Ok(Self::V1Alpha1), "foo.example.org/v1" => Ok(Self::V1), "foo.example.org/v2alpha1" => Ok(Self::V2Alpha1), _ => { - Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { - unknown_desired_api_version: api_version.to_string(), + Err(::stackable_versioned::ParseApiVersionError::UnknownVersion { + api_version: api_version.to_string(), }) } } @@ -640,8 +643,11 @@ pub(crate) mod versioned { ::stackable_versioned::ConvertObjectError, > { let desired_api_version = BarVersion::try_from_api_version( - desired_api_version, - )?; + desired_api_version, + ) + .map_err(|source| ::stackable_versioned::ConvertObjectError::ParseDesiredApiVersion { + source, + })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { let current_object = Self::from_json_value(object.clone()) @@ -753,9 +759,9 @@ pub(crate) mod versioned { field: "kind".to_string(), })?; if object_kind != "Bar" { - return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { + return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { kind: object_kind.to_string(), - supported_kind: "Bar".to_string(), + expected: "Bar".to_string(), }); } let api_version = object @@ -837,14 +843,14 @@ pub(crate) mod versioned { } pub fn try_from_api_version( api_version: &str, - ) -> Result { + ) -> Result { match api_version { "bar.example.org/v1alpha1" => Ok(Self::V1Alpha1), "bar.example.org/v1" => Ok(Self::V1), "bar.example.org/v2alpha1" => Ok(Self::V2Alpha1), _ => { - Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { - unknown_desired_api_version: api_version.to_string(), + Err(::stackable_versioned::ParseApiVersionError::UnknownVersion { + api_version: api_version.to_string(), }) } } 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 7c3c6db01..9f67e5d28 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 @@ -176,8 +176,11 @@ impl FooBar { ::stackable_versioned::ConvertObjectError, > { let desired_api_version = FooBarVersion::try_from_api_version( - desired_api_version, - )?; + desired_api_version, + ) + .map_err(|source| ::stackable_versioned::ConvertObjectError::ParseDesiredApiVersion { + source, + })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { let current_object = Self::from_json_value(object.clone()) @@ -289,9 +292,9 @@ impl FooBar { field: "kind".to_string(), })?; if object_kind != "FooBar" { - return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { + return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { kind: object_kind.to_string(), - supported_kind: "FooBar".to_string(), + expected: "FooBar".to_string(), }); } let api_version = object @@ -376,14 +379,14 @@ impl FooBarVersion { } pub fn try_from_api_version( api_version: &str, - ) -> Result { + ) -> Result { match api_version { "stackable.tech/v1alpha1" => Ok(Self::V1Alpha1), "stackable.tech/v1beta1" => Ok(Self::V1Beta1), "stackable.tech/v1" => Ok(Self::V1), _ => { - Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { - unknown_desired_api_version: api_version.to_string(), + Err(::stackable_versioned::ParseApiVersionError::UnknownVersion { + api_version: api_version.to_string(), }) } } 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 4c3c8e768..89e761d67 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 @@ -104,7 +104,10 @@ impl Foo { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { - let desired_api_version = FooVersion::try_from_api_version(desired_api_version)?; + let desired_api_version = FooVersion::try_from_api_version(desired_api_version) + .map_err(|source| ::stackable_versioned::ConvertObjectError::ParseDesiredApiVersion { + source, + })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { let current_object = Self::from_json_value(object.clone()) @@ -132,9 +135,9 @@ impl Foo { field: "kind".to_string(), })?; if object_kind != "Foo" { - return Err(::stackable_versioned::ParseObjectError::UnexpectedObjectKind { + return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { kind: object_kind.to_string(), - supported_kind: "Foo".to_string(), + expected: "Foo".to_string(), }); } let api_version = object @@ -197,12 +200,12 @@ impl FooVersion { } pub fn try_from_api_version( api_version: &str, - ) -> Result { + ) -> Result { match api_version { "stackable.tech/v1alpha1" => Ok(Self::V1Alpha1), _ => { - Err(::stackable_versioned::ConvertObjectError::DesiredApiVersionUnknown { - unknown_desired_api_version: api_version.to_string(), + Err(::stackable_versioned::ParseApiVersionError::UnknownVersion { + api_version: api_version.to_string(), }) } } diff --git a/crates/stackable-versioned/src/k8s.rs b/crates/stackable-versioned/src/k8s.rs index 3430bb13d..d42c189b2 100644 --- a/crates/stackable-versioned/src/k8s.rs +++ b/crates/stackable-versioned/src/k8s.rs @@ -73,8 +73,8 @@ pub enum ConvertObjectError { #[snafu(display("failed to serialize object into json"))] Serialize { source: serde_json::Error }, - #[snafu(display("unknown desired API version {unknown_desired_api_version:?}"))] - DesiredApiVersionUnknown { unknown_desired_api_version: String }, + #[snafu(display("failed to parse desired API version"))] + ParseDesiredApiVersion { source: ParseApiVersionError }, } impl ConvertObjectError { @@ -95,8 +95,18 @@ impl ConvertObjectError { match self { ConvertObjectError::Parse { .. } => 400, ConvertObjectError::Serialize { .. } => 500, + // This is likely the clients fault, as it is requesting a unsupported version - ConvertObjectError::DesiredApiVersionUnknown { .. } => 400, + ConvertObjectError::ParseDesiredApiVersion { + source: ParseApiVersionError::UnknownVersion { .. }, + .. + } => 400, } } } + +#[derive(Debug, Snafu)] +pub enum ParseApiVersionError { + #[snafu(display("unknown apiVersion {api_version:?}"))] + UnknownVersion { api_version: String }, +} diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unkown_desired_version.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unkown_desired_version.json.snap index 8d8ff4b84..09fb7a600 100644 --- a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unkown_desired_version.json.snap +++ b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unkown_desired_version.json.snap @@ -11,8 +11,8 @@ input_file: crates/stackable-versioned/src/tests/fixtures/inputs/fail/unkown_des "result": { "status": "Failure", "code": 400, - "message": "unknown desired API version \"test.stackable.tech/v99\"", - "reason": "unknown desired API version \"test.stackable.tech/v99\"" + "message": "failed to parse desired API version: unknown apiVersion \"test.stackable.tech/v99\"", + "reason": "failed to parse desired API version: unknown apiVersion \"test.stackable.tech/v99\"" }, "convertedObjects": [] } From 30b36dcc5eae7a5c9f57d71a93a583ce3f5bc88f Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Tue, 24 Jun 2025 11:51:47 +0200 Subject: [PATCH 17/33] Update crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs Co-authored-by: Techassi --- .../src/codegen/container/struct/k8s.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 5bdb51b15..246db1945 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -183,9 +183,9 @@ impl Struct { fn from_json_value(object: #serde_json_path::Value) -> ::std::result::Result { let object_kind = object .get("kind") - .ok_or_else(|| #parse_object_error::FieldMissing{ field: "kind".to_string() })? + .ok_or_else(|| #parse_object_error::FieldMissing{ field: "kind".to_owned() })? .as_str() - .ok_or_else(|| #parse_object_error::FieldNotStr{ field: "kind".to_string() })?; + .ok_or_else(|| #parse_object_error::FieldNotStr{ field: "kind".to_owned() })?; // Note(@sbernauer): The kind must be checked here, because it is // possible for the wrong object to be deserialized. From 9fb395c5adf872325a622244fca243b4088f93ec Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Tue, 24 Jun 2025 11:52:21 +0200 Subject: [PATCH 18/33] Apply suggestions from code review Co-authored-by: Techassi --- .../src/codegen/container/struct/k8s.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 246db1945..36cbe1cac 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -201,9 +201,9 @@ impl Struct { let api_version = object .get("apiVersion") - .ok_or_else(|| #parse_object_error::FieldMissing{ field: "apiVersion".to_string() })? + .ok_or_else(|| #parse_object_error::FieldMissing{ field: "apiVersion".to_owned() })? .as_str() - .ok_or_else(|| #parse_object_error::FieldNotStr{ field: "apiVersion".to_string() })?; + .ok_or_else(|| #parse_object_error::FieldNotStr{ field: "apiVersion".to_owned() })?; let object = match api_version { #(#api_versions => { From 4a79d529f14a8d269735784ace40504e3fa109ca Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Tue, 24 Jun 2025 11:52:58 +0200 Subject: [PATCH 19/33] Update crates/stackable-versioned/src/k8s.rs Co-authored-by: Techassi --- crates/stackable-versioned/src/k8s.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/stackable-versioned/src/k8s.rs b/crates/stackable-versioned/src/k8s.rs index d42c189b2..0402e7c3f 100644 --- a/crates/stackable-versioned/src/k8s.rs +++ b/crates/stackable-versioned/src/k8s.rs @@ -50,7 +50,7 @@ pub enum ParseObjectError { #[snafu(display("the field {field:?} is missing"))] FieldMissing { field: String }, - #[snafu(display(r#"the field {field:?} must be a string"#))] + #[snafu(display("the field {field:?} must be a string"))] FieldNotStr { field: String }, #[snafu(display("encountered unknown object API version {api_version:?}"))] From 8f77619156818822d06f6fc50bfb3b38c97bbb09 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Tue, 24 Jun 2025 12:09:41 +0200 Subject: [PATCH 20/33] Move into tests folder --- .../src/codegen/container/struct/k8s.rs | 9 ++- ..._macros__snapshot_tests__k8s@basic.rs.snap | 14 ++-- ...hot_tests__k8s@conversion_tracking.rs.snap | 14 ++-- ...napshot_tests__k8s@crate_overrides.rs.snap | 14 ++-- ...macros__snapshot_tests__k8s@module.rs.snap | 28 +++---- ...napshot_tests__k8s@module_preserve.rs.snap | 28 +++---- ...__snapshot_tests__k8s@renamed_kind.rs.snap | 14 ++-- ...os__snapshot_tests__k8s@shortnames.rs.snap | 14 ++-- crates/stackable-versioned/src/k8s.rs | 13 ++-- crates/stackable-versioned/src/lib.rs | 3 - ...ned__tests__fail@request_missing.json.snap | 19 ----- ...sts__fail@unkown_current_version.json.snap | 19 ----- ...sts__fail@unkown_desired_version.json.snap | 19 ----- ...ioned__tests__pass@persons_to_v3.json.snap | 76 ------------------- ...sts__fail@unkown_desired_version.json.snap | 19 ----- ...__fail@unparseable_missing_field.json.snap | 19 ----- ...d__tests__tests__fail@wrong_kind.json.snap | 19 ----- ..._tests__pass@persons_to_v1alpha1.json.snap | 61 --------------- .../fixtures/inputs/fail/request_missing.json | 0 .../inputs/fail/unkown_current_version.json | 0 .../inputs/fail/unkown_desired_version.json | 0 .../fail/unparseable_missing_field.json | 0 .../fixtures/inputs/fail/wrong_kind.json | 0 .../inputs/pass/persons_to_v1alpha1.json | 0 .../fixtures/inputs/pass/persons_to_v3.json | 0 .../mod.rs => tests/integration_test.rs} | 4 +- ...tion_test__fail@request_missing.json.snap} | 4 +- ...st__fail@unkown_current_version.json.snap} | 4 +- ...est__fail@unkown_desired_version.json.snap | 19 +++++ ..._fail@unparseable_missing_field.json.snap} | 4 +- ...tegration_test__fail@wrong_kind.json.snap} | 4 +- ..._test__pass@persons_to_v1alpha1.json.snap} | 4 +- ...ration_test__pass@persons_to_v3.json.snap} | 4 +- 33 files changed, 108 insertions(+), 341 deletions(-) delete mode 100644 crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@request_missing.json.snap delete mode 100644 crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unkown_current_version.json.snap delete mode 100644 crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unkown_desired_version.json.snap delete mode 100644 crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__pass@persons_to_v3.json.snap delete mode 100644 crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@unkown_desired_version.json.snap delete mode 100644 crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@unparseable_missing_field.json.snap delete mode 100644 crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@wrong_kind.json.snap delete mode 100644 crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__pass@persons_to_v1alpha1.json.snap rename crates/stackable-versioned/{src => }/tests/fixtures/inputs/fail/request_missing.json (100%) rename crates/stackable-versioned/{src => }/tests/fixtures/inputs/fail/unkown_current_version.json (100%) rename crates/stackable-versioned/{src => }/tests/fixtures/inputs/fail/unkown_desired_version.json (100%) rename crates/stackable-versioned/{src => }/tests/fixtures/inputs/fail/unparseable_missing_field.json (100%) rename crates/stackable-versioned/{src => }/tests/fixtures/inputs/fail/wrong_kind.json (100%) rename crates/stackable-versioned/{src => }/tests/fixtures/inputs/pass/persons_to_v1alpha1.json (100%) rename crates/stackable-versioned/{src => }/tests/fixtures/inputs/pass/persons_to_v3.json (100%) rename crates/stackable-versioned/{src/tests/mod.rs => tests/integration_test.rs} (96%) rename crates/stackable-versioned/{src/tests/snapshots/stackable_versioned__tests__tests__fail@request_missing.json.snap => tests/snapshots/integration_test__fail@request_missing.json.snap} (70%) rename crates/stackable-versioned/{src/tests/snapshots/stackable_versioned__tests__tests__fail@unkown_current_version.json.snap => tests/snapshots/integration_test__fail@unkown_current_version.json.snap} (76%) create mode 100644 crates/stackable-versioned/tests/snapshots/integration_test__fail@unkown_desired_version.json.snap rename crates/stackable-versioned/{src/tests/snapshots/stackable_versioned__tests__fail@unparseable_missing_field.json.snap => tests/snapshots/integration_test__fail@unparseable_missing_field.json.snap} (75%) rename crates/stackable-versioned/{src/tests/snapshots/stackable_versioned__tests__fail@wrong_kind.json.snap => tests/snapshots/integration_test__fail@wrong_kind.json.snap} (77%) rename crates/stackable-versioned/{src/tests/snapshots/stackable_versioned__tests__pass@persons_to_v1alpha1.json.snap => tests/snapshots/integration_test__pass@persons_to_v1alpha1.json.snap} (89%) rename crates/stackable-versioned/{src/tests/snapshots/stackable_versioned__tests__tests__pass@persons_to_v3.json.snap => tests/snapshots/integration_test__pass@persons_to_v3.json.snap} (92%) 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 36cbe1cac..26d6178bf 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -250,7 +250,8 @@ impl Struct { let automatically_derived = is_nested.not().then(|| quote! {#[automatically_derived]}); let versioned_path = &*kubernetes_arguments.crates.versioned; - let parse_api_version_error = quote! { #versioned_path::ParseApiVersionError }; + let unknown_desired_api_version_error = + quote! { #versioned_path::UnknownDesiredApiVersionError }; // Get the per-version items to be able to iterate over them via quote let variant_strings = &tokens.variant_strings; @@ -288,11 +289,11 @@ impl Struct { } } - pub fn try_from_api_version(api_version: &str) -> Result { + pub fn try_from_api_version(api_version: &str) -> Result { match api_version { #(#api_versions => Ok(Self::#variant_idents)),*, - _ => Err(#parse_api_version_error::UnknownVersion { - api_version: api_version.to_string(), + _ => Err(#unknown_desired_api_version_error { + api_version: api_version.to_owned(), }), } } 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 3be0184bc..36fa3ba38 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 @@ -311,11 +311,11 @@ impl Foo { let object_kind = object .get("kind") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { - field: "kind".to_string(), + field: "kind".to_owned(), })? .as_str() .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "kind".to_string(), + field: "kind".to_owned(), })?; if object_kind != "Foo" { return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { @@ -326,11 +326,11 @@ impl Foo { let api_version = object .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { - field: "apiVersion".to_string(), + field: "apiVersion".to_owned(), })? .as_str() .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "apiVersion".to_string(), + field: "apiVersion".to_owned(), })?; let object = match api_version { "stackable.tech/v1alpha1" => { @@ -405,14 +405,14 @@ impl FooVersion { } pub fn try_from_api_version( api_version: &str, - ) -> Result { + ) -> Result { match api_version { "stackable.tech/v1alpha1" => Ok(Self::V1Alpha1), "stackable.tech/v1beta1" => Ok(Self::V1Beta1), "stackable.tech/v1" => Ok(Self::V1), _ => { - Err(::stackable_versioned::ParseApiVersionError::UnknownVersion { - api_version: api_version.to_string(), + Err(::stackable_versioned::UnknownDesiredApiVersionError { + api_version: api_version.to_owned(), }) } } 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 1b58df29b..b871e3856 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 @@ -281,11 +281,11 @@ impl Foo { let object_kind = object .get("kind") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { - field: "kind".to_string(), + field: "kind".to_owned(), })? .as_str() .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "kind".to_string(), + field: "kind".to_owned(), })?; if object_kind != "Foo" { return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { @@ -296,11 +296,11 @@ impl Foo { let api_version = object .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { - field: "apiVersion".to_string(), + field: "apiVersion".to_owned(), })? .as_str() .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "apiVersion".to_string(), + field: "apiVersion".to_owned(), })?; let object = match api_version { "stackable.tech/v1alpha1" => { @@ -375,14 +375,14 @@ impl FooVersion { } pub fn try_from_api_version( api_version: &str, - ) -> Result { + ) -> Result { match api_version { "stackable.tech/v1alpha1" => Ok(Self::V1Alpha1), "stackable.tech/v1beta1" => Ok(Self::V1Beta1), "stackable.tech/v1" => Ok(Self::V1), _ => { - Err(::stackable_versioned::ParseApiVersionError::UnknownVersion { - api_version: api_version.to_string(), + Err(::stackable_versioned::UnknownDesiredApiVersionError { + api_version: api_version.to_owned(), }) } } 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 f8f6b530e..08e7364cc 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 @@ -296,11 +296,11 @@ impl Foo { let object_kind = object .get("kind") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { - field: "kind".to_string(), + field: "kind".to_owned(), })? .as_str() .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "kind".to_string(), + field: "kind".to_owned(), })?; if object_kind != "Foo" { return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { @@ -311,11 +311,11 @@ impl Foo { let api_version = object .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { - field: "apiVersion".to_string(), + field: "apiVersion".to_owned(), })? .as_str() .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "apiVersion".to_string(), + field: "apiVersion".to_owned(), })?; let object = match api_version { "foo.example.org/v1alpha1" => { @@ -390,14 +390,14 @@ impl FooVersion { } pub fn try_from_api_version( api_version: &str, - ) -> Result { + ) -> Result { match api_version { "foo.example.org/v1alpha1" => Ok(Self::V1Alpha1), "foo.example.org/v1beta1" => Ok(Self::V1Beta1), "foo.example.org/v1" => Ok(Self::V1), _ => { - Err(::stackable_versioned::ParseApiVersionError::UnknownVersion { - api_version: api_version.to_string(), + Err(::stackable_versioned::UnknownDesiredApiVersionError { + api_version: api_version.to_owned(), }) } } 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 0c2aa8827..cbc28426a 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 @@ -470,11 +470,11 @@ impl Foo { let object_kind = object .get("kind") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { - field: "kind".to_string(), + field: "kind".to_owned(), })? .as_str() .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "kind".to_string(), + field: "kind".to_owned(), })?; if object_kind != "Foo" { return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { @@ -485,11 +485,11 @@ impl Foo { let api_version = object .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { - field: "apiVersion".to_string(), + field: "apiVersion".to_owned(), })? .as_str() .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "apiVersion".to_string(), + field: "apiVersion".to_owned(), })?; let object = match api_version { "foo.example.org/v1alpha1" => { @@ -564,14 +564,14 @@ impl FooVersion { } pub fn try_from_api_version( api_version: &str, - ) -> Result { + ) -> Result { match api_version { "foo.example.org/v1alpha1" => Ok(Self::V1Alpha1), "foo.example.org/v1" => Ok(Self::V1), "foo.example.org/v2alpha1" => Ok(Self::V2Alpha1), _ => { - Err(::stackable_versioned::ParseApiVersionError::UnknownVersion { - api_version: api_version.to_string(), + Err(::stackable_versioned::UnknownDesiredApiVersionError { + api_version: api_version.to_owned(), }) } } @@ -772,11 +772,11 @@ impl Bar { let object_kind = object .get("kind") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { - field: "kind".to_string(), + field: "kind".to_owned(), })? .as_str() .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "kind".to_string(), + field: "kind".to_owned(), })?; if object_kind != "Bar" { return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { @@ -787,11 +787,11 @@ impl Bar { let api_version = object .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { - field: "apiVersion".to_string(), + field: "apiVersion".to_owned(), })? .as_str() .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "apiVersion".to_string(), + field: "apiVersion".to_owned(), })?; let object = match api_version { "bar.example.org/v1alpha1" => { @@ -866,14 +866,14 @@ impl BarVersion { } pub fn try_from_api_version( api_version: &str, - ) -> Result { + ) -> Result { match api_version { "bar.example.org/v1alpha1" => Ok(Self::V1Alpha1), "bar.example.org/v1" => Ok(Self::V1), "bar.example.org/v2alpha1" => Ok(Self::V2Alpha1), _ => { - Err(::stackable_versioned::ParseApiVersionError::UnknownVersion { - api_version: api_version.to_string(), + Err(::stackable_versioned::UnknownDesiredApiVersionError { + api_version: api_version.to_owned(), }) } } 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 22e8a0653..3c5bf624b 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 @@ -453,11 +453,11 @@ pub(crate) mod versioned { let object_kind = object .get("kind") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { - field: "kind".to_string(), + field: "kind".to_owned(), })? .as_str() .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "kind".to_string(), + field: "kind".to_owned(), })?; if object_kind != "Foo" { return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { @@ -468,11 +468,11 @@ pub(crate) mod versioned { let api_version = object .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { - field: "apiVersion".to_string(), + field: "apiVersion".to_owned(), })? .as_str() .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "apiVersion".to_string(), + field: "apiVersion".to_owned(), })?; let object = match api_version { "foo.example.org/v1alpha1" => { @@ -544,14 +544,14 @@ pub(crate) mod versioned { } pub fn try_from_api_version( api_version: &str, - ) -> Result { + ) -> Result { match api_version { "foo.example.org/v1alpha1" => Ok(Self::V1Alpha1), "foo.example.org/v1" => Ok(Self::V1), "foo.example.org/v2alpha1" => Ok(Self::V2Alpha1), _ => { - Err(::stackable_versioned::ParseApiVersionError::UnknownVersion { - api_version: api_version.to_string(), + Err(::stackable_versioned::UnknownDesiredApiVersionError { + api_version: api_version.to_owned(), }) } } @@ -752,11 +752,11 @@ pub(crate) mod versioned { let object_kind = object .get("kind") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { - field: "kind".to_string(), + field: "kind".to_owned(), })? .as_str() .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "kind".to_string(), + field: "kind".to_owned(), })?; if object_kind != "Bar" { return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { @@ -767,11 +767,11 @@ pub(crate) mod versioned { let api_version = object .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { - field: "apiVersion".to_string(), + field: "apiVersion".to_owned(), })? .as_str() .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "apiVersion".to_string(), + field: "apiVersion".to_owned(), })?; let object = match api_version { "bar.example.org/v1alpha1" => { @@ -843,14 +843,14 @@ pub(crate) mod versioned { } pub fn try_from_api_version( api_version: &str, - ) -> Result { + ) -> Result { match api_version { "bar.example.org/v1alpha1" => Ok(Self::V1Alpha1), "bar.example.org/v1" => Ok(Self::V1), "bar.example.org/v2alpha1" => Ok(Self::V2Alpha1), _ => { - Err(::stackable_versioned::ParseApiVersionError::UnknownVersion { - api_version: api_version.to_string(), + Err(::stackable_versioned::UnknownDesiredApiVersionError { + api_version: api_version.to_owned(), }) } } 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 9f67e5d28..4ccba9680 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 @@ -285,11 +285,11 @@ impl FooBar { let object_kind = object .get("kind") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { - field: "kind".to_string(), + field: "kind".to_owned(), })? .as_str() .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "kind".to_string(), + field: "kind".to_owned(), })?; if object_kind != "FooBar" { return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { @@ -300,11 +300,11 @@ impl FooBar { let api_version = object .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { - field: "apiVersion".to_string(), + field: "apiVersion".to_owned(), })? .as_str() .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "apiVersion".to_string(), + field: "apiVersion".to_owned(), })?; let object = match api_version { "stackable.tech/v1alpha1" => { @@ -379,14 +379,14 @@ impl FooBarVersion { } pub fn try_from_api_version( api_version: &str, - ) -> Result { + ) -> Result { match api_version { "stackable.tech/v1alpha1" => Ok(Self::V1Alpha1), "stackable.tech/v1beta1" => Ok(Self::V1Beta1), "stackable.tech/v1" => Ok(Self::V1), _ => { - Err(::stackable_versioned::ParseApiVersionError::UnknownVersion { - api_version: api_version.to_string(), + Err(::stackable_versioned::UnknownDesiredApiVersionError { + api_version: api_version.to_owned(), }) } } 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 89e761d67..bafe700cb 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 @@ -128,11 +128,11 @@ impl Foo { let object_kind = object .get("kind") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { - field: "kind".to_string(), + field: "kind".to_owned(), })? .as_str() .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "kind".to_string(), + field: "kind".to_owned(), })?; if object_kind != "Foo" { return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { @@ -143,11 +143,11 @@ impl Foo { let api_version = object .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { - field: "apiVersion".to_string(), + field: "apiVersion".to_owned(), })? .as_str() .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldNotStr { - field: "apiVersion".to_string(), + field: "apiVersion".to_owned(), })?; let object = match api_version { "stackable.tech/v1alpha1" => { @@ -200,12 +200,12 @@ impl FooVersion { } pub fn try_from_api_version( api_version: &str, - ) -> Result { + ) -> Result { match api_version { "stackable.tech/v1alpha1" => Ok(Self::V1Alpha1), _ => { - Err(::stackable_versioned::ParseApiVersionError::UnknownVersion { - api_version: api_version.to_string(), + Err(::stackable_versioned::UnknownDesiredApiVersionError { + api_version: api_version.to_owned(), }) } } diff --git a/crates/stackable-versioned/src/k8s.rs b/crates/stackable-versioned/src/k8s.rs index 0402e7c3f..f55182fa8 100644 --- a/crates/stackable-versioned/src/k8s.rs +++ b/crates/stackable-versioned/src/k8s.rs @@ -74,7 +74,9 @@ pub enum ConvertObjectError { Serialize { source: serde_json::Error }, #[snafu(display("failed to parse desired API version"))] - ParseDesiredApiVersion { source: ParseApiVersionError }, + ParseDesiredApiVersion { + source: UnknownDesiredApiVersionError, + }, } impl ConvertObjectError { @@ -98,15 +100,14 @@ impl ConvertObjectError { // This is likely the clients fault, as it is requesting a unsupported version ConvertObjectError::ParseDesiredApiVersion { - source: ParseApiVersionError::UnknownVersion { .. }, - .. + source: UnknownDesiredApiVersionError { .. }, } => 400, } } } #[derive(Debug, Snafu)] -pub enum ParseApiVersionError { - #[snafu(display("unknown apiVersion {api_version:?}"))] - UnknownVersion { api_version: String }, +#[snafu(display("unknown API version {api_version:?}"))] +pub struct UnknownDesiredApiVersionError { + pub api_version: String, } diff --git a/crates/stackable-versioned/src/lib.rs b/crates/stackable-versioned/src/lib.rs index 0c3da4448..5538eae65 100644 --- a/crates/stackable-versioned/src/lib.rs +++ b/crates/stackable-versioned/src/lib.rs @@ -17,6 +17,3 @@ pub use stackable_versioned_macros::versioned; mod k8s; #[cfg(feature = "k8s")] pub use k8s::*; - -#[cfg(test)] -mod tests; diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@request_missing.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@request_missing.json.snap deleted file mode 100644 index 797a889d5..000000000 --- a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@request_missing.json.snap +++ /dev/null @@ -1,19 +0,0 @@ ---- -source: crates/stackable-versioned/src/tests/mod.rs -expression: formatted -input_file: crates/stackable-versioned/src/tests/fixtures/inputs/fail/request_missing.json ---- -{ - "apiVersion": "apiextensions.k8s.io/v1", - "kind": "ConversionReview", - "response": { - "uid": "", - "result": { - "status": "Failure", - "code": 400, - "message": "request missing in ConversionReview", - "reason": "request missing in ConversionReview" - }, - "convertedObjects": [] - } -} diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unkown_current_version.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unkown_current_version.json.snap deleted file mode 100644 index e54c19736..000000000 --- a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unkown_current_version.json.snap +++ /dev/null @@ -1,19 +0,0 @@ ---- -source: crates/stackable-versioned/src/tests/mod.rs -expression: formatted -input_file: crates/stackable-versioned/src/tests/fixtures/inputs/fail/unkown_current_version.json ---- -{ - "apiVersion": "apiextensions.k8s.io/v1", - "kind": "ConversionReview", - "response": { - "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", - "result": { - "status": "Failure", - "code": 400, - "message": "failed to parse object: encountered unknown object API version \"test.stackable.tech/v99\"", - "reason": "failed to parse object: encountered unknown object API version \"test.stackable.tech/v99\"" - }, - "convertedObjects": [] - } -} diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unkown_desired_version.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unkown_desired_version.json.snap deleted file mode 100644 index 09fb7a600..000000000 --- a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unkown_desired_version.json.snap +++ /dev/null @@ -1,19 +0,0 @@ ---- -source: crates/stackable-versioned/src/tests/mod.rs -expression: formatted -input_file: crates/stackable-versioned/src/tests/fixtures/inputs/fail/unkown_desired_version.json ---- -{ - "apiVersion": "apiextensions.k8s.io/v1", - "kind": "ConversionReview", - "response": { - "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", - "result": { - "status": "Failure", - "code": 400, - "message": "failed to parse desired API version: unknown apiVersion \"test.stackable.tech/v99\"", - "reason": "failed to parse desired API version: unknown apiVersion \"test.stackable.tech/v99\"" - }, - "convertedObjects": [] - } -} diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__pass@persons_to_v3.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__pass@persons_to_v3.json.snap deleted file mode 100644 index 43d687cc2..000000000 --- a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__pass@persons_to_v3.json.snap +++ /dev/null @@ -1,76 +0,0 @@ ---- -source: crates/stackable-versioned/src/tests/mod.rs -expression: formatted -input_file: crates/stackable-versioned/src/tests/fixtures/inputs/pass/persons_to_v3.json ---- -{ - "apiVersion": "apiextensions.k8s.io/v1", - "kind": "ConversionReview", - "response": { - "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", - "result": { - "status": "Success" - }, - "convertedObjects": [ - { - "apiVersion": "test.stackable.tech/v3", - "kind": "Person", - "metadata": { - "name": "sbernauer", - "namespace": "default", - "uid": "d41e2019-5de3-409c-a7b2-0799ecb95e4b" - }, - "spec": { - "firstName": "", - "gender": "Unknown", - "lastName": "", - "username": "sbernauer" - } - }, - { - "apiVersion": "test.stackable.tech/v3", - "kind": "Person", - "metadata": {}, - "spec": { - "firstName": "Sebastian", - "gender": "Unknown", - "lastName": "Bernauer", - "username": "sbernauer" - } - }, - { - "apiVersion": "test.stackable.tech/v3", - "kind": "Person", - "metadata": {}, - "spec": { - "firstName": "Sebastian", - "gender": "Unknown", - "lastName": "Bernauer", - "username": "sbernauer" - } - }, - { - "apiVersion": "test.stackable.tech/v3", - "kind": "Person", - "metadata": {}, - "spec": { - "firstName": "Sebastian", - "gender": "Male", - "lastName": "Bernauer", - "username": "sbernauer" - } - }, - { - "apiVersion": "test.stackable.tech/v3", - "kind": "Person", - "metadata": {}, - "spec": { - "firstName": "Sebastian", - "gender": "Male", - "lastName": "Bernauer", - "username": "sbernauer" - } - } - ] - } -} diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@unkown_desired_version.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@unkown_desired_version.json.snap deleted file mode 100644 index 9bc5c161b..000000000 --- a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@unkown_desired_version.json.snap +++ /dev/null @@ -1,19 +0,0 @@ ---- -source: crates/stackable-versioned/src/tests/mod.rs -expression: formatted -input_file: crates/stackable-versioned/fixtures/inputs/fail/unkown_desired_version.json ---- -{ - "apiVersion": "apiextensions.k8s.io/v1", - "kind": "ConversionReview", - "response": { - "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", - "result": { - "status": "Failure", - "code": 400, - "message": "unknown desired API version \"test.stackable.tech/v99\"", - "reason": "unknown desired API version \"test.stackable.tech/v99\"" - }, - "convertedObjects": [] - } -} diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@unparseable_missing_field.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@unparseable_missing_field.json.snap deleted file mode 100644 index abd7c721a..000000000 --- a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@unparseable_missing_field.json.snap +++ /dev/null @@ -1,19 +0,0 @@ ---- -source: crates/stackable-versioned/src/tests/mod.rs -expression: formatted -input_file: crates/stackable-versioned/fixtures/inputs/fail/unparseable_missing_field.json ---- -{ - "apiVersion": "apiextensions.k8s.io/v1", - "kind": "ConversionReview", - "response": { - "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", - "result": { - "status": "Failure", - "code": 400, - "message": "failed to parse object: failed to deserialize object from JSON: missing field `username`", - "reason": "failed to parse object: failed to deserialize object from JSON: missing field `username`" - }, - "convertedObjects": [] - } -} diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@wrong_kind.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@wrong_kind.json.snap deleted file mode 100644 index 463853db3..000000000 --- a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@wrong_kind.json.snap +++ /dev/null @@ -1,19 +0,0 @@ ---- -source: crates/stackable-versioned/src/tests/mod.rs -expression: formatted -input_file: crates/stackable-versioned/src/tests/fixtures/inputs/fail/wrong_kind.json ---- -{ - "apiVersion": "apiextensions.k8s.io/v1", - "kind": "ConversionReview", - "response": { - "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", - "result": { - "status": "Failure", - "code": 400, - "message": "failed to parse object: wrong object kind \"SomeOtherResource\". The conversion can only convert objects of kind \"Person\"", - "reason": "failed to parse object: wrong object kind \"SomeOtherResource\". The conversion can only convert objects of kind \"Person\"" - }, - "convertedObjects": [] - } -} diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__pass@persons_to_v1alpha1.json.snap b/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__pass@persons_to_v1alpha1.json.snap deleted file mode 100644 index 717977035..000000000 --- a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__pass@persons_to_v1alpha1.json.snap +++ /dev/null @@ -1,61 +0,0 @@ ---- -source: crates/stackable-versioned/src/tests/mod.rs -expression: formatted -input_file: crates/stackable-versioned/fixtures/inputs/pass/persons_to_v1alpha1.json ---- -{ - "apiVersion": "apiextensions.k8s.io/v1", - "kind": "ConversionReview", - "response": { - "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", - "result": { - "status": "Success" - }, - "convertedObjects": [ - { - "apiVersion": "test.stackable.tech/v1alpha1", - "kind": "Person", - "metadata": { - "name": "sbernauer", - "namespace": "default", - "uid": "d41e2019-5de3-409c-a7b2-0799ecb95e4b" - }, - "spec": { - "username": "sbernauer" - } - }, - { - "apiVersion": "test.stackable.tech/v1alpha1", - "kind": "Person", - "metadata": {}, - "spec": { - "username": "sbernauer" - } - }, - { - "apiVersion": "test.stackable.tech/v1alpha1", - "kind": "Person", - "metadata": {}, - "spec": { - "username": "sbernauer" - } - }, - { - "apiVersion": "test.stackable.tech/v1alpha1", - "kind": "Person", - "metadata": {}, - "spec": { - "username": "sbernauer" - } - }, - { - "apiVersion": "test.stackable.tech/v1alpha1", - "kind": "Person", - "metadata": {}, - "spec": { - "username": "sbernauer" - } - } - ] - } -} diff --git a/crates/stackable-versioned/src/tests/fixtures/inputs/fail/request_missing.json b/crates/stackable-versioned/tests/fixtures/inputs/fail/request_missing.json similarity index 100% rename from crates/stackable-versioned/src/tests/fixtures/inputs/fail/request_missing.json rename to crates/stackable-versioned/tests/fixtures/inputs/fail/request_missing.json diff --git a/crates/stackable-versioned/src/tests/fixtures/inputs/fail/unkown_current_version.json b/crates/stackable-versioned/tests/fixtures/inputs/fail/unkown_current_version.json similarity index 100% rename from crates/stackable-versioned/src/tests/fixtures/inputs/fail/unkown_current_version.json rename to crates/stackable-versioned/tests/fixtures/inputs/fail/unkown_current_version.json diff --git a/crates/stackable-versioned/src/tests/fixtures/inputs/fail/unkown_desired_version.json b/crates/stackable-versioned/tests/fixtures/inputs/fail/unkown_desired_version.json similarity index 100% rename from crates/stackable-versioned/src/tests/fixtures/inputs/fail/unkown_desired_version.json rename to crates/stackable-versioned/tests/fixtures/inputs/fail/unkown_desired_version.json diff --git a/crates/stackable-versioned/src/tests/fixtures/inputs/fail/unparseable_missing_field.json b/crates/stackable-versioned/tests/fixtures/inputs/fail/unparseable_missing_field.json similarity index 100% rename from crates/stackable-versioned/src/tests/fixtures/inputs/fail/unparseable_missing_field.json rename to crates/stackable-versioned/tests/fixtures/inputs/fail/unparseable_missing_field.json diff --git a/crates/stackable-versioned/src/tests/fixtures/inputs/fail/wrong_kind.json b/crates/stackable-versioned/tests/fixtures/inputs/fail/wrong_kind.json similarity index 100% rename from crates/stackable-versioned/src/tests/fixtures/inputs/fail/wrong_kind.json rename to crates/stackable-versioned/tests/fixtures/inputs/fail/wrong_kind.json diff --git a/crates/stackable-versioned/src/tests/fixtures/inputs/pass/persons_to_v1alpha1.json b/crates/stackable-versioned/tests/fixtures/inputs/pass/persons_to_v1alpha1.json similarity index 100% rename from crates/stackable-versioned/src/tests/fixtures/inputs/pass/persons_to_v1alpha1.json rename to crates/stackable-versioned/tests/fixtures/inputs/pass/persons_to_v1alpha1.json diff --git a/crates/stackable-versioned/src/tests/fixtures/inputs/pass/persons_to_v3.json b/crates/stackable-versioned/tests/fixtures/inputs/pass/persons_to_v3.json similarity index 100% rename from crates/stackable-versioned/src/tests/fixtures/inputs/pass/persons_to_v3.json rename to crates/stackable-versioned/tests/fixtures/inputs/pass/persons_to_v3.json diff --git a/crates/stackable-versioned/src/tests/mod.rs b/crates/stackable-versioned/tests/integration_test.rs similarity index 96% rename from crates/stackable-versioned/src/tests/mod.rs rename to crates/stackable-versioned/tests/integration_test.rs index a40193d37..eb48a5cf3 100644 --- a/crates/stackable-versioned/src/tests/mod.rs +++ b/crates/stackable-versioned/tests/integration_test.rs @@ -7,10 +7,10 @@ use kube::{ }; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use stackable_versioned_macros::versioned; +use stackable_versioned::versioned; #[versioned( - k8s(group = "test.stackable.tech", crates(versioned = "crate")), + k8s(group = "test.stackable.tech",), version(name = "v1alpha1"), version(name = "v1alpha2"), version(name = "v1beta1"), diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@request_missing.json.snap b/crates/stackable-versioned/tests/snapshots/integration_test__fail@request_missing.json.snap similarity index 70% rename from crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@request_missing.json.snap rename to crates/stackable-versioned/tests/snapshots/integration_test__fail@request_missing.json.snap index fc0696d80..657a1cd28 100644 --- a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@request_missing.json.snap +++ b/crates/stackable-versioned/tests/snapshots/integration_test__fail@request_missing.json.snap @@ -1,7 +1,7 @@ --- -source: crates/stackable-versioned/src/tests/mod.rs +source: crates/stackable-versioned/tests/integration_test.rs expression: formatted -input_file: crates/stackable-versioned/fixtures/inputs/fail/request_missing.json +input_file: crates/stackable-versioned/tests/fixtures/inputs/fail/request_missing.json --- { "apiVersion": "apiextensions.k8s.io/v1", diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@unkown_current_version.json.snap b/crates/stackable-versioned/tests/snapshots/integration_test__fail@unkown_current_version.json.snap similarity index 76% rename from crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@unkown_current_version.json.snap rename to crates/stackable-versioned/tests/snapshots/integration_test__fail@unkown_current_version.json.snap index 758e01037..b04c8e9f1 100644 --- a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__fail@unkown_current_version.json.snap +++ b/crates/stackable-versioned/tests/snapshots/integration_test__fail@unkown_current_version.json.snap @@ -1,7 +1,7 @@ --- -source: crates/stackable-versioned/src/tests/mod.rs +source: crates/stackable-versioned/tests/integration_test.rs expression: formatted -input_file: crates/stackable-versioned/fixtures/inputs/fail/unkown_current_version.json +input_file: crates/stackable-versioned/tests/fixtures/inputs/fail/unkown_current_version.json --- { "apiVersion": "apiextensions.k8s.io/v1", diff --git a/crates/stackable-versioned/tests/snapshots/integration_test__fail@unkown_desired_version.json.snap b/crates/stackable-versioned/tests/snapshots/integration_test__fail@unkown_desired_version.json.snap new file mode 100644 index 000000000..e822af3aa --- /dev/null +++ b/crates/stackable-versioned/tests/snapshots/integration_test__fail@unkown_desired_version.json.snap @@ -0,0 +1,19 @@ +--- +source: crates/stackable-versioned/tests/integration_test.rs +expression: formatted +input_file: crates/stackable-versioned/tests/fixtures/inputs/fail/unkown_desired_version.json +--- +{ + "apiVersion": "apiextensions.k8s.io/v1", + "kind": "ConversionReview", + "response": { + "uid": "c4e55572-ee1f-4e94-9097-28936985d45f", + "result": { + "status": "Failure", + "code": 400, + "message": "failed to parse desired API version: unknown API version \"test.stackable.tech/v99\"", + "reason": "failed to parse desired API version: unknown API version \"test.stackable.tech/v99\"" + }, + "convertedObjects": [] + } +} diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unparseable_missing_field.json.snap b/crates/stackable-versioned/tests/snapshots/integration_test__fail@unparseable_missing_field.json.snap similarity index 75% rename from crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unparseable_missing_field.json.snap rename to crates/stackable-versioned/tests/snapshots/integration_test__fail@unparseable_missing_field.json.snap index e77d508f4..82c24c462 100644 --- a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@unparseable_missing_field.json.snap +++ b/crates/stackable-versioned/tests/snapshots/integration_test__fail@unparseable_missing_field.json.snap @@ -1,7 +1,7 @@ --- -source: crates/stackable-versioned/src/tests/mod.rs +source: crates/stackable-versioned/tests/integration_test.rs expression: formatted -input_file: crates/stackable-versioned/src/tests/fixtures/inputs/fail/unparseable_missing_field.json +input_file: crates/stackable-versioned/tests/fixtures/inputs/fail/unparseable_missing_field.json --- { "apiVersion": "apiextensions.k8s.io/v1", diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@wrong_kind.json.snap b/crates/stackable-versioned/tests/snapshots/integration_test__fail@wrong_kind.json.snap similarity index 77% rename from crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@wrong_kind.json.snap rename to crates/stackable-versioned/tests/snapshots/integration_test__fail@wrong_kind.json.snap index 9a836aa66..d6b19d8ab 100644 --- a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__fail@wrong_kind.json.snap +++ b/crates/stackable-versioned/tests/snapshots/integration_test__fail@wrong_kind.json.snap @@ -1,7 +1,7 @@ --- -source: crates/stackable-versioned/src/tests/mod.rs +source: crates/stackable-versioned/tests/integration_test.rs expression: formatted -input_file: crates/stackable-versioned/src/tests/fixtures/inputs/fail/wrong_kind.json +input_file: crates/stackable-versioned/tests/fixtures/inputs/fail/wrong_kind.json --- { "apiVersion": "apiextensions.k8s.io/v1", diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__pass@persons_to_v1alpha1.json.snap b/crates/stackable-versioned/tests/snapshots/integration_test__pass@persons_to_v1alpha1.json.snap similarity index 89% rename from crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__pass@persons_to_v1alpha1.json.snap rename to crates/stackable-versioned/tests/snapshots/integration_test__pass@persons_to_v1alpha1.json.snap index c015c3558..f9e9e06ec 100644 --- a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__pass@persons_to_v1alpha1.json.snap +++ b/crates/stackable-versioned/tests/snapshots/integration_test__pass@persons_to_v1alpha1.json.snap @@ -1,7 +1,7 @@ --- -source: crates/stackable-versioned/src/tests/mod.rs +source: crates/stackable-versioned/tests/integration_test.rs expression: formatted -input_file: crates/stackable-versioned/src/tests/fixtures/inputs/pass/persons_to_v1alpha1.json +input_file: crates/stackable-versioned/tests/fixtures/inputs/pass/persons_to_v1alpha1.json --- { "apiVersion": "apiextensions.k8s.io/v1", diff --git a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__pass@persons_to_v3.json.snap b/crates/stackable-versioned/tests/snapshots/integration_test__pass@persons_to_v3.json.snap similarity index 92% rename from crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__pass@persons_to_v3.json.snap rename to crates/stackable-versioned/tests/snapshots/integration_test__pass@persons_to_v3.json.snap index e7d5b2a26..ed944f9cf 100644 --- a/crates/stackable-versioned/src/tests/snapshots/stackable_versioned__tests__tests__pass@persons_to_v3.json.snap +++ b/crates/stackable-versioned/tests/snapshots/integration_test__pass@persons_to_v3.json.snap @@ -1,7 +1,7 @@ --- -source: crates/stackable-versioned/src/tests/mod.rs +source: crates/stackable-versioned/tests/integration_test.rs expression: formatted -input_file: crates/stackable-versioned/fixtures/inputs/pass/persons_to_v3.json +input_file: crates/stackable-versioned/tests/fixtures/inputs/pass/persons_to_v3.json --- { "apiVersion": "apiextensions.k8s.io/v1", From cb3dbfe5a40dc0057feeeb2c026c8a1a7048cf35 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Tue, 24 Jun 2025 12:44:34 +0200 Subject: [PATCH 21/33] to_string -> to_owned --- .../src/codegen/container/struct/k8s.rs | 4 ++-- crates/stackable-versioned/tests/integration_test.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) 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 26d6178bf..c3d4a7127 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -194,8 +194,8 @@ impl Struct { // status in a later step. if object_kind != #enum_ident_string { return Err(#parse_object_error::UnexpectedKind{ - kind: object_kind.to_string(), - expected: #enum_ident_string.to_string(), + kind: object_kind.to_owned(), + expected: #enum_ident_string.to_owned(), }); } diff --git a/crates/stackable-versioned/tests/integration_test.rs b/crates/stackable-versioned/tests/integration_test.rs index eb48a5cf3..d2f9a42c3 100644 --- a/crates/stackable-versioned/tests/integration_test.rs +++ b/crates/stackable-versioned/tests/integration_test.rs @@ -66,9 +66,9 @@ pub enum Gender { impl From for String { fn from(value: Gender) -> Self { match value { - Gender::Unknown => "Unknown".to_string(), - Gender::Male => "Male".to_string(), - Gender::Female => "Female".to_string(), + Gender::Unknown => "Unknown".to_owned(), + Gender::Male => "Male".to_owned(), + Gender::Female => "Female".to_owned(), } } } From 119a845cb53ea76b7afd0e946f6b81b8e1378615 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Tue, 24 Jun 2025 15:16:48 +0200 Subject: [PATCH 22/33] Rename fn to try_from_json_object --- .../src/codegen/container/struct/k8s.rs | 10 ++--- ..._macros__snapshot_tests__k8s@basic.rs.snap | 20 +++++----- ...hot_tests__k8s@conversion_tracking.rs.snap | 20 +++++----- ...napshot_tests__k8s@crate_overrides.rs.snap | 20 +++++----- ...macros__snapshot_tests__k8s@module.rs.snap | 40 +++++++++---------- ...napshot_tests__k8s@module_preserve.rs.snap | 40 +++++++++---------- ...__snapshot_tests__k8s@renamed_kind.rs.snap | 20 +++++----- ...os__snapshot_tests__k8s@shortnames.rs.snap | 16 ++++---- 8 files changed, 93 insertions(+), 93 deletions(-) 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 c3d4a7127..d29bf40ed 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -180,8 +180,8 @@ impl Struct { #convert_method - fn from_json_value(object: #serde_json_path::Value) -> ::std::result::Result { - let object_kind = object + fn try_from_json_object(object_value: #serde_json_path::Value) -> ::std::result::Result { + let object_kind = object_value .get("kind") .ok_or_else(|| #parse_object_error::FieldMissing{ field: "kind".to_owned() })? .as_str() @@ -199,7 +199,7 @@ impl Struct { }); } - let api_version = object + let api_version = object_value .get("apiVersion") .ok_or_else(|| #parse_object_error::FieldMissing{ field: "apiVersion".to_owned() })? .as_str() @@ -207,7 +207,7 @@ impl Struct { let object = match api_version { #(#api_versions => { - let object = #serde_json_path::from_value(object) + let object = #serde_json_path::from_value(object_value) .map_err(|source| #parse_object_error::Deserialize { source })?; Self::#variant_idents(object) @@ -478,7 +478,7 @@ impl Struct { for object in objects { // This clone is required because in the noop case we move the object into // the converted objects vec. - let current_object = Self::from_json_value(object.clone()) + let current_object = Self::try_from_json_object(object.clone()) .map_err(|source| #convert_object_error::Parse { source })?; match (current_object, &desired_api_version) { 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 36fa3ba38..f26d04cdb 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 @@ -205,7 +205,7 @@ impl Foo { })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let current_object = Self::from_json_value(object.clone()) + let current_object = Self::try_from_json_object(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; @@ -305,10 +305,10 @@ impl Foo { } ::std::result::Result::Ok(converted_objects) } - fn from_json_value( - object: ::serde_json::Value, + fn try_from_json_object( + object_value: ::serde_json::Value, ) -> ::std::result::Result { - let object_kind = object + let object_kind = object_value .get("kind") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "kind".to_owned(), @@ -319,11 +319,11 @@ impl Foo { })?; if object_kind != "Foo" { return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { - kind: object_kind.to_string(), - expected: "Foo".to_string(), + kind: object_kind.to_owned(), + expected: "Foo".to_owned(), }); } - let api_version = object + let api_version = object_value .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "apiVersion".to_owned(), @@ -334,21 +334,21 @@ impl Foo { })?; let object = match api_version { "stackable.tech/v1alpha1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } "stackable.tech/v1beta1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Beta1(object) } "stackable.tech/v1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; 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 b871e3856..9b19e85d5 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 @@ -175,7 +175,7 @@ impl Foo { })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let current_object = Self::from_json_value(object.clone()) + let current_object = Self::try_from_json_object(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; @@ -275,10 +275,10 @@ impl Foo { } ::std::result::Result::Ok(converted_objects) } - fn from_json_value( - object: ::serde_json::Value, + fn try_from_json_object( + object_value: ::serde_json::Value, ) -> ::std::result::Result { - let object_kind = object + let object_kind = object_value .get("kind") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "kind".to_owned(), @@ -289,11 +289,11 @@ impl Foo { })?; if object_kind != "Foo" { return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { - kind: object_kind.to_string(), - expected: "Foo".to_string(), + kind: object_kind.to_owned(), + expected: "Foo".to_owned(), }); } - let api_version = object + let api_version = object_value .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "apiVersion".to_owned(), @@ -304,21 +304,21 @@ impl Foo { })?; let object = match api_version { "stackable.tech/v1alpha1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } "stackable.tech/v1beta1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Beta1(object) } "stackable.tech/v1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; 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 08e7364cc..0ceb49fe8 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 @@ -196,7 +196,7 @@ impl Foo { })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let current_object = Self::from_json_value(object.clone()) + let current_object = Self::try_from_json_object(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; @@ -290,10 +290,10 @@ impl Foo { } ::std::result::Result::Ok(converted_objects) } - fn from_json_value( - object: ::serde_json::Value, + fn try_from_json_object( + object_value: ::serde_json::Value, ) -> ::std::result::Result { - let object_kind = object + let object_kind = object_value .get("kind") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "kind".to_owned(), @@ -304,11 +304,11 @@ impl Foo { })?; if object_kind != "Foo" { return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { - kind: object_kind.to_string(), - expected: "Foo".to_string(), + kind: object_kind.to_owned(), + expected: "Foo".to_owned(), }); } - let api_version = object + let api_version = object_value .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "apiVersion".to_owned(), @@ -319,21 +319,21 @@ impl Foo { })?; let object = match api_version { "foo.example.org/v1alpha1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } "foo.example.org/v1beta1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Beta1(object) } "foo.example.org/v1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; 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 cbc28426a..55db2ab82 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 @@ -368,7 +368,7 @@ impl Foo { })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let current_object = Self::from_json_value(object.clone()) + let current_object = Self::try_from_json_object(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; @@ -464,10 +464,10 @@ impl Foo { } ::std::result::Result::Ok(converted_objects) } - fn from_json_value( - object: ::serde_json::Value, + fn try_from_json_object( + object_value: ::serde_json::Value, ) -> ::std::result::Result { - let object_kind = object + let object_kind = object_value .get("kind") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "kind".to_owned(), @@ -478,11 +478,11 @@ impl Foo { })?; if object_kind != "Foo" { return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { - kind: object_kind.to_string(), - expected: "Foo".to_string(), + kind: object_kind.to_owned(), + expected: "Foo".to_owned(), }); } - let api_version = object + let api_version = object_value .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "apiVersion".to_owned(), @@ -493,21 +493,21 @@ impl Foo { })?; let object = match api_version { "foo.example.org/v1alpha1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } "foo.example.org/v1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1(object) } "foo.example.org/v2alpha1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; @@ -670,7 +670,7 @@ impl Bar { })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let current_object = Self::from_json_value(object.clone()) + let current_object = Self::try_from_json_object(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; @@ -766,10 +766,10 @@ impl Bar { } ::std::result::Result::Ok(converted_objects) } - fn from_json_value( - object: ::serde_json::Value, + fn try_from_json_object( + object_value: ::serde_json::Value, ) -> ::std::result::Result { - let object_kind = object + let object_kind = object_value .get("kind") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "kind".to_owned(), @@ -780,11 +780,11 @@ impl Bar { })?; if object_kind != "Bar" { return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { - kind: object_kind.to_string(), - expected: "Bar".to_string(), + kind: object_kind.to_owned(), + expected: "Bar".to_owned(), }); } - let api_version = object + let api_version = object_value .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "apiVersion".to_owned(), @@ -795,21 +795,21 @@ impl Bar { })?; let object = match api_version { "bar.example.org/v1alpha1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } "bar.example.org/v1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1(object) } "bar.example.org/v2alpha1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; 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 3c5bf624b..80ac2423a 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 @@ -351,7 +351,7 @@ pub(crate) mod versioned { })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let current_object = Self::from_json_value(object.clone()) + let current_object = Self::try_from_json_object(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; @@ -447,10 +447,10 @@ pub(crate) mod versioned { } ::std::result::Result::Ok(converted_objects) } - fn from_json_value( - object: ::serde_json::Value, + fn try_from_json_object( + object_value: ::serde_json::Value, ) -> ::std::result::Result { - let object_kind = object + let object_kind = object_value .get("kind") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "kind".to_owned(), @@ -461,11 +461,11 @@ pub(crate) mod versioned { })?; if object_kind != "Foo" { return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { - kind: object_kind.to_string(), - expected: "Foo".to_string(), + kind: object_kind.to_owned(), + expected: "Foo".to_owned(), }); } - let api_version = object + let api_version = object_value .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "apiVersion".to_owned(), @@ -476,21 +476,21 @@ pub(crate) mod versioned { })?; let object = match api_version { "foo.example.org/v1alpha1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } "foo.example.org/v1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1(object) } "foo.example.org/v2alpha1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; @@ -650,7 +650,7 @@ pub(crate) mod versioned { })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let current_object = Self::from_json_value(object.clone()) + let current_object = Self::try_from_json_object(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; @@ -746,10 +746,10 @@ pub(crate) mod versioned { } ::std::result::Result::Ok(converted_objects) } - fn from_json_value( - object: ::serde_json::Value, + fn try_from_json_object( + object_value: ::serde_json::Value, ) -> ::std::result::Result { - let object_kind = object + let object_kind = object_value .get("kind") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "kind".to_owned(), @@ -760,11 +760,11 @@ pub(crate) mod versioned { })?; if object_kind != "Bar" { return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { - kind: object_kind.to_string(), - expected: "Bar".to_string(), + kind: object_kind.to_owned(), + expected: "Bar".to_owned(), }); } - let api_version = object + let api_version = object_value .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "apiVersion".to_owned(), @@ -775,21 +775,21 @@ pub(crate) mod versioned { })?; let object = match api_version { "bar.example.org/v1alpha1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } "bar.example.org/v1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1(object) } "bar.example.org/v2alpha1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; 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 4ccba9680..69821f26b 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 @@ -183,7 +183,7 @@ impl FooBar { })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let current_object = Self::from_json_value(object.clone()) + let current_object = Self::try_from_json_object(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; @@ -279,10 +279,10 @@ impl FooBar { } ::std::result::Result::Ok(converted_objects) } - fn from_json_value( - object: ::serde_json::Value, + fn try_from_json_object( + object_value: ::serde_json::Value, ) -> ::std::result::Result { - let object_kind = object + let object_kind = object_value .get("kind") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "kind".to_owned(), @@ -293,11 +293,11 @@ impl FooBar { })?; if object_kind != "FooBar" { return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { - kind: object_kind.to_string(), - expected: "FooBar".to_string(), + kind: object_kind.to_owned(), + expected: "FooBar".to_owned(), }); } - let api_version = object + let api_version = object_value .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "apiVersion".to_owned(), @@ -308,21 +308,21 @@ impl FooBar { })?; let object = match api_version { "stackable.tech/v1alpha1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Alpha1(object) } "stackable.tech/v1beta1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; Self::V1Beta1(object) } "stackable.tech/v1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; 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 bafe700cb..2e6b955c9 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 @@ -110,7 +110,7 @@ impl Foo { })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let current_object = Self::from_json_value(object.clone()) + let current_object = Self::try_from_json_object(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; @@ -122,10 +122,10 @@ impl Foo { } ::std::result::Result::Ok(converted_objects) } - fn from_json_value( - object: ::serde_json::Value, + fn try_from_json_object( + object_value: ::serde_json::Value, ) -> ::std::result::Result { - let object_kind = object + let object_kind = object_value .get("kind") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "kind".to_owned(), @@ -136,11 +136,11 @@ impl Foo { })?; if object_kind != "Foo" { return Err(::stackable_versioned::ParseObjectError::UnexpectedKind { - kind: object_kind.to_string(), - expected: "Foo".to_string(), + kind: object_kind.to_owned(), + expected: "Foo".to_owned(), }); } - let api_version = object + let api_version = object_value .get("apiVersion") .ok_or_else(|| ::stackable_versioned::ParseObjectError::FieldMissing { field: "apiVersion".to_owned(), @@ -151,7 +151,7 @@ impl Foo { })?; let object = match api_version { "stackable.tech/v1alpha1" => { - let object = ::serde_json::from_value(object) + let object = ::serde_json::from_value(object_value) .map_err(|source| ::stackable_versioned::ParseObjectError::Deserialize { source, })?; From 83e2438b6aa55dd1da5f23bb0de3ef682b857652 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Tue, 24 Jun 2025 15:20:02 +0200 Subject: [PATCH 23/33] Remove try_prefix --- .../src/codegen/container/struct/k8s.rs | 4 ++-- ...rsioned_macros__snapshot_tests__k8s@basic.rs.snap | 4 ++-- ...__snapshot_tests__k8s@conversion_tracking.rs.snap | 4 ++-- ...cros__snapshot_tests__k8s@crate_overrides.rs.snap | 4 ++-- ...sioned_macros__snapshot_tests__k8s@module.rs.snap | 8 ++++---- ...cros__snapshot_tests__k8s@module_preserve.rs.snap | 12 ++++-------- ..._macros__snapshot_tests__k8s@renamed_kind.rs.snap | 6 ++---- ...ed_macros__snapshot_tests__k8s@shortnames.rs.snap | 4 ++-- 8 files changed, 20 insertions(+), 26 deletions(-) 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 d29bf40ed..c19bfa416 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -289,7 +289,7 @@ impl Struct { } } - pub fn try_from_api_version(api_version: &str) -> Result { + pub fn from_api_version(api_version: &str) -> Result { match api_version { #(#api_versions => Ok(Self::#variant_idents)),*, _ => Err(#unknown_desired_api_version_error { @@ -470,7 +470,7 @@ impl Struct { ) -> ::std::result::Result<::std::vec::Vec<#serde_json_path::Value>, #convert_object_error> { - let desired_api_version = #version_enum_ident::try_from_api_version(desired_api_version) + let desired_api_version = #version_enum_ident::from_api_version(desired_api_version) .map_err(|source| #convert_object_error::ParseDesiredApiVersion { source })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); 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 f26d04cdb..056031812 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 @@ -199,7 +199,7 @@ impl Foo { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { - let desired_api_version = FooVersion::try_from_api_version(desired_api_version) + let desired_api_version = FooVersion::from_api_version(desired_api_version) .map_err(|source| ::stackable_versioned::ConvertObjectError::ParseDesiredApiVersion { source, })?; @@ -403,7 +403,7 @@ impl FooVersion { V1 => "stackable.tech/v1", } } - pub fn try_from_api_version( + pub fn from_api_version( api_version: &str, ) -> Result { match api_version { 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 9b19e85d5..3bdd42319 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 @@ -169,7 +169,7 @@ impl Foo { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { - let desired_api_version = FooVersion::try_from_api_version(desired_api_version) + let desired_api_version = FooVersion::from_api_version(desired_api_version) .map_err(|source| ::stackable_versioned::ConvertObjectError::ParseDesiredApiVersion { source, })?; @@ -373,7 +373,7 @@ impl FooVersion { V1 => "stackable.tech/v1", } } - pub fn try_from_api_version( + pub fn from_api_version( api_version: &str, ) -> Result { match api_version { 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 0ceb49fe8..cd6db5bdb 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 @@ -190,7 +190,7 @@ impl Foo { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { - let desired_api_version = FooVersion::try_from_api_version(desired_api_version) + let desired_api_version = FooVersion::from_api_version(desired_api_version) .map_err(|source| ::stackable_versioned::ConvertObjectError::ParseDesiredApiVersion { source, })?; @@ -388,7 +388,7 @@ impl FooVersion { V1 => "foo.example.org/v1", } } - pub fn try_from_api_version( + pub fn from_api_version( api_version: &str, ) -> Result { match api_version { 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 55db2ab82..3ba723d80 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 @@ -362,7 +362,7 @@ impl Foo { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { - let desired_api_version = FooVersion::try_from_api_version(desired_api_version) + let desired_api_version = FooVersion::from_api_version(desired_api_version) .map_err(|source| ::stackable_versioned::ConvertObjectError::ParseDesiredApiVersion { source, })?; @@ -562,7 +562,7 @@ impl FooVersion { V2Alpha1 => "foo.example.org/v2alpha1", } } - pub fn try_from_api_version( + pub fn from_api_version( api_version: &str, ) -> Result { match api_version { @@ -664,7 +664,7 @@ impl Bar { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { - let desired_api_version = BarVersion::try_from_api_version(desired_api_version) + let desired_api_version = BarVersion::from_api_version(desired_api_version) .map_err(|source| ::stackable_versioned::ConvertObjectError::ParseDesiredApiVersion { source, })?; @@ -864,7 +864,7 @@ impl BarVersion { V2Alpha1 => "bar.example.org/v2alpha1", } } - pub fn try_from_api_version( + pub fn from_api_version( api_version: &str, ) -> Result { match api_version { 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 80ac2423a..363dd66d7 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 @@ -343,9 +343,7 @@ pub(crate) mod versioned { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { - let desired_api_version = FooVersion::try_from_api_version( - desired_api_version, - ) + let desired_api_version = FooVersion::from_api_version(desired_api_version) .map_err(|source| ::stackable_versioned::ConvertObjectError::ParseDesiredApiVersion { source, })?; @@ -542,7 +540,7 @@ pub(crate) mod versioned { V2Alpha1 => "foo.example.org/v2alpha1", } } - pub fn try_from_api_version( + pub fn from_api_version( api_version: &str, ) -> Result { match api_version { @@ -642,9 +640,7 @@ pub(crate) mod versioned { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { - let desired_api_version = BarVersion::try_from_api_version( - desired_api_version, - ) + let desired_api_version = BarVersion::from_api_version(desired_api_version) .map_err(|source| ::stackable_versioned::ConvertObjectError::ParseDesiredApiVersion { source, })?; @@ -841,7 +837,7 @@ pub(crate) mod versioned { V2Alpha1 => "bar.example.org/v2alpha1", } } - pub fn try_from_api_version( + pub fn from_api_version( api_version: &str, ) -> Result { match api_version { 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 69821f26b..d508fc339 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 @@ -175,9 +175,7 @@ impl FooBar { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { - let desired_api_version = FooBarVersion::try_from_api_version( - desired_api_version, - ) + let desired_api_version = FooBarVersion::from_api_version(desired_api_version) .map_err(|source| ::stackable_versioned::ConvertObjectError::ParseDesiredApiVersion { source, })?; @@ -377,7 +375,7 @@ impl FooBarVersion { V1 => "stackable.tech/v1", } } - pub fn try_from_api_version( + pub fn from_api_version( api_version: &str, ) -> Result { match api_version { 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 2e6b955c9..f63c6f5a7 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 @@ -104,7 +104,7 @@ impl Foo { ::std::vec::Vec<::serde_json::Value>, ::stackable_versioned::ConvertObjectError, > { - let desired_api_version = FooVersion::try_from_api_version(desired_api_version) + let desired_api_version = FooVersion::from_api_version(desired_api_version) .map_err(|source| ::stackable_versioned::ConvertObjectError::ParseDesiredApiVersion { source, })?; @@ -198,7 +198,7 @@ impl FooVersion { V1Alpha1 => "stackable.tech/v1alpha1", } } - pub fn try_from_api_version( + pub fn from_api_version( api_version: &str, ) -> Result { match api_version { From 7400d395049530bbe7d1a78a84b601ea22208c0a Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Tue, 24 Jun 2025 15:24:13 +0200 Subject: [PATCH 24/33] Move test inputs folder --- .../tests/{integration_test.rs => conversion.rs} | 4 ++-- .../inputs => inputs/conversions}/fail/request_missing.json | 0 .../conversions}/fail/unkown_current_version.json | 0 .../conversions}/fail/unkown_desired_version.json | 0 .../conversions}/fail/unparseable_missing_field.json | 0 .../inputs => inputs/conversions}/fail/wrong_kind.json | 0 .../conversions}/pass/persons_to_v1alpha1.json | 0 .../inputs => inputs/conversions}/pass/persons_to_v3.json | 0 ...g.json.snap => conversion__fail@request_missing.json.snap} | 4 ++-- ...snap => conversion__fail@unkown_current_version.json.snap} | 4 ++-- ...snap => conversion__fail@unkown_desired_version.json.snap} | 4 ++-- ...p => conversion__fail@unparseable_missing_field.json.snap} | 4 ++-- ...g_kind.json.snap => conversion__fail@wrong_kind.json.snap} | 4 ++-- ...on.snap => conversion__pass@persons_to_v1alpha1.json.snap} | 4 ++-- ..._v3.json.snap => conversion__pass@persons_to_v3.json.snap} | 4 ++-- 15 files changed, 16 insertions(+), 16 deletions(-) rename crates/stackable-versioned/tests/{integration_test.rs => conversion.rs} (96%) rename crates/stackable-versioned/tests/{fixtures/inputs => inputs/conversions}/fail/request_missing.json (100%) rename crates/stackable-versioned/tests/{fixtures/inputs => inputs/conversions}/fail/unkown_current_version.json (100%) rename crates/stackable-versioned/tests/{fixtures/inputs => inputs/conversions}/fail/unkown_desired_version.json (100%) rename crates/stackable-versioned/tests/{fixtures/inputs => inputs/conversions}/fail/unparseable_missing_field.json (100%) rename crates/stackable-versioned/tests/{fixtures/inputs => inputs/conversions}/fail/wrong_kind.json (100%) rename crates/stackable-versioned/tests/{fixtures/inputs => inputs/conversions}/pass/persons_to_v1alpha1.json (100%) rename crates/stackable-versioned/tests/{fixtures/inputs => inputs/conversions}/pass/persons_to_v3.json (100%) rename crates/stackable-versioned/tests/snapshots/{integration_test__fail@request_missing.json.snap => conversion__fail@request_missing.json.snap} (70%) rename crates/stackable-versioned/tests/snapshots/{integration_test__fail@unkown_current_version.json.snap => conversion__fail@unkown_current_version.json.snap} (76%) rename crates/stackable-versioned/tests/snapshots/{integration_test__fail@unkown_desired_version.json.snap => conversion__fail@unkown_desired_version.json.snap} (75%) rename crates/stackable-versioned/tests/snapshots/{integration_test__fail@unparseable_missing_field.json.snap => conversion__fail@unparseable_missing_field.json.snap} (75%) rename crates/stackable-versioned/tests/snapshots/{integration_test__fail@wrong_kind.json.snap => conversion__fail@wrong_kind.json.snap} (77%) rename crates/stackable-versioned/tests/snapshots/{integration_test__pass@persons_to_v1alpha1.json.snap => conversion__pass@persons_to_v1alpha1.json.snap} (89%) rename crates/stackable-versioned/tests/snapshots/{integration_test__pass@persons_to_v3.json.snap => conversion__pass@persons_to_v3.json.snap} (92%) diff --git a/crates/stackable-versioned/tests/integration_test.rs b/crates/stackable-versioned/tests/conversion.rs similarity index 96% rename from crates/stackable-versioned/tests/integration_test.rs rename to crates/stackable-versioned/tests/conversion.rs index d2f9a42c3..39df45e55 100644 --- a/crates/stackable-versioned/tests/integration_test.rs +++ b/crates/stackable-versioned/tests/conversion.rs @@ -85,7 +85,7 @@ impl From for Gender { #[test] fn pass() { - glob!("./fixtures/inputs/pass/", "*.json", |path| { + glob!("./inputs/conversions/pass/", "*.json", |path| { let (request, response) = run_for_file(path); let formatted = serde_json::to_string_pretty(&response) @@ -107,7 +107,7 @@ fn pass() { #[test] fn fail() { - glob!("./fixtures/inputs/fail/", "*.json", |path| { + glob!("./inputs/conversions/fail/", "*.json", |path| { let (request, response) = run_for_file(path); let formatted = serde_json::to_string_pretty(&response) diff --git a/crates/stackable-versioned/tests/fixtures/inputs/fail/request_missing.json b/crates/stackable-versioned/tests/inputs/conversions/fail/request_missing.json similarity index 100% rename from crates/stackable-versioned/tests/fixtures/inputs/fail/request_missing.json rename to crates/stackable-versioned/tests/inputs/conversions/fail/request_missing.json diff --git a/crates/stackable-versioned/tests/fixtures/inputs/fail/unkown_current_version.json b/crates/stackable-versioned/tests/inputs/conversions/fail/unkown_current_version.json similarity index 100% rename from crates/stackable-versioned/tests/fixtures/inputs/fail/unkown_current_version.json rename to crates/stackable-versioned/tests/inputs/conversions/fail/unkown_current_version.json diff --git a/crates/stackable-versioned/tests/fixtures/inputs/fail/unkown_desired_version.json b/crates/stackable-versioned/tests/inputs/conversions/fail/unkown_desired_version.json similarity index 100% rename from crates/stackable-versioned/tests/fixtures/inputs/fail/unkown_desired_version.json rename to crates/stackable-versioned/tests/inputs/conversions/fail/unkown_desired_version.json diff --git a/crates/stackable-versioned/tests/fixtures/inputs/fail/unparseable_missing_field.json b/crates/stackable-versioned/tests/inputs/conversions/fail/unparseable_missing_field.json similarity index 100% rename from crates/stackable-versioned/tests/fixtures/inputs/fail/unparseable_missing_field.json rename to crates/stackable-versioned/tests/inputs/conversions/fail/unparseable_missing_field.json diff --git a/crates/stackable-versioned/tests/fixtures/inputs/fail/wrong_kind.json b/crates/stackable-versioned/tests/inputs/conversions/fail/wrong_kind.json similarity index 100% rename from crates/stackable-versioned/tests/fixtures/inputs/fail/wrong_kind.json rename to crates/stackable-versioned/tests/inputs/conversions/fail/wrong_kind.json diff --git a/crates/stackable-versioned/tests/fixtures/inputs/pass/persons_to_v1alpha1.json b/crates/stackable-versioned/tests/inputs/conversions/pass/persons_to_v1alpha1.json similarity index 100% rename from crates/stackable-versioned/tests/fixtures/inputs/pass/persons_to_v1alpha1.json rename to crates/stackable-versioned/tests/inputs/conversions/pass/persons_to_v1alpha1.json diff --git a/crates/stackable-versioned/tests/fixtures/inputs/pass/persons_to_v3.json b/crates/stackable-versioned/tests/inputs/conversions/pass/persons_to_v3.json similarity index 100% rename from crates/stackable-versioned/tests/fixtures/inputs/pass/persons_to_v3.json rename to crates/stackable-versioned/tests/inputs/conversions/pass/persons_to_v3.json diff --git a/crates/stackable-versioned/tests/snapshots/integration_test__fail@request_missing.json.snap b/crates/stackable-versioned/tests/snapshots/conversion__fail@request_missing.json.snap similarity index 70% rename from crates/stackable-versioned/tests/snapshots/integration_test__fail@request_missing.json.snap rename to crates/stackable-versioned/tests/snapshots/conversion__fail@request_missing.json.snap index 657a1cd28..6946aab2f 100644 --- a/crates/stackable-versioned/tests/snapshots/integration_test__fail@request_missing.json.snap +++ b/crates/stackable-versioned/tests/snapshots/conversion__fail@request_missing.json.snap @@ -1,7 +1,7 @@ --- -source: crates/stackable-versioned/tests/integration_test.rs +source: crates/stackable-versioned/tests/conversion.rs expression: formatted -input_file: crates/stackable-versioned/tests/fixtures/inputs/fail/request_missing.json +input_file: crates/stackable-versioned/tests/inputs/conversions/fail/request_missing.json --- { "apiVersion": "apiextensions.k8s.io/v1", diff --git a/crates/stackable-versioned/tests/snapshots/integration_test__fail@unkown_current_version.json.snap b/crates/stackable-versioned/tests/snapshots/conversion__fail@unkown_current_version.json.snap similarity index 76% rename from crates/stackable-versioned/tests/snapshots/integration_test__fail@unkown_current_version.json.snap rename to crates/stackable-versioned/tests/snapshots/conversion__fail@unkown_current_version.json.snap index b04c8e9f1..5ac139d49 100644 --- a/crates/stackable-versioned/tests/snapshots/integration_test__fail@unkown_current_version.json.snap +++ b/crates/stackable-versioned/tests/snapshots/conversion__fail@unkown_current_version.json.snap @@ -1,7 +1,7 @@ --- -source: crates/stackable-versioned/tests/integration_test.rs +source: crates/stackable-versioned/tests/conversion.rs expression: formatted -input_file: crates/stackable-versioned/tests/fixtures/inputs/fail/unkown_current_version.json +input_file: crates/stackable-versioned/tests/inputs/conversions/fail/unkown_current_version.json --- { "apiVersion": "apiextensions.k8s.io/v1", diff --git a/crates/stackable-versioned/tests/snapshots/integration_test__fail@unkown_desired_version.json.snap b/crates/stackable-versioned/tests/snapshots/conversion__fail@unkown_desired_version.json.snap similarity index 75% rename from crates/stackable-versioned/tests/snapshots/integration_test__fail@unkown_desired_version.json.snap rename to crates/stackable-versioned/tests/snapshots/conversion__fail@unkown_desired_version.json.snap index e822af3aa..dcab27f23 100644 --- a/crates/stackable-versioned/tests/snapshots/integration_test__fail@unkown_desired_version.json.snap +++ b/crates/stackable-versioned/tests/snapshots/conversion__fail@unkown_desired_version.json.snap @@ -1,7 +1,7 @@ --- -source: crates/stackable-versioned/tests/integration_test.rs +source: crates/stackable-versioned/tests/conversion.rs expression: formatted -input_file: crates/stackable-versioned/tests/fixtures/inputs/fail/unkown_desired_version.json +input_file: crates/stackable-versioned/tests/inputs/conversions/fail/unkown_desired_version.json --- { "apiVersion": "apiextensions.k8s.io/v1", diff --git a/crates/stackable-versioned/tests/snapshots/integration_test__fail@unparseable_missing_field.json.snap b/crates/stackable-versioned/tests/snapshots/conversion__fail@unparseable_missing_field.json.snap similarity index 75% rename from crates/stackable-versioned/tests/snapshots/integration_test__fail@unparseable_missing_field.json.snap rename to crates/stackable-versioned/tests/snapshots/conversion__fail@unparseable_missing_field.json.snap index 82c24c462..3e329b643 100644 --- a/crates/stackable-versioned/tests/snapshots/integration_test__fail@unparseable_missing_field.json.snap +++ b/crates/stackable-versioned/tests/snapshots/conversion__fail@unparseable_missing_field.json.snap @@ -1,7 +1,7 @@ --- -source: crates/stackable-versioned/tests/integration_test.rs +source: crates/stackable-versioned/tests/conversion.rs expression: formatted -input_file: crates/stackable-versioned/tests/fixtures/inputs/fail/unparseable_missing_field.json +input_file: crates/stackable-versioned/tests/inputs/conversions/fail/unparseable_missing_field.json --- { "apiVersion": "apiextensions.k8s.io/v1", diff --git a/crates/stackable-versioned/tests/snapshots/integration_test__fail@wrong_kind.json.snap b/crates/stackable-versioned/tests/snapshots/conversion__fail@wrong_kind.json.snap similarity index 77% rename from crates/stackable-versioned/tests/snapshots/integration_test__fail@wrong_kind.json.snap rename to crates/stackable-versioned/tests/snapshots/conversion__fail@wrong_kind.json.snap index d6b19d8ab..f65d9b84f 100644 --- a/crates/stackable-versioned/tests/snapshots/integration_test__fail@wrong_kind.json.snap +++ b/crates/stackable-versioned/tests/snapshots/conversion__fail@wrong_kind.json.snap @@ -1,7 +1,7 @@ --- -source: crates/stackable-versioned/tests/integration_test.rs +source: crates/stackable-versioned/tests/conversion.rs expression: formatted -input_file: crates/stackable-versioned/tests/fixtures/inputs/fail/wrong_kind.json +input_file: crates/stackable-versioned/tests/inputs/conversions/fail/wrong_kind.json --- { "apiVersion": "apiextensions.k8s.io/v1", diff --git a/crates/stackable-versioned/tests/snapshots/integration_test__pass@persons_to_v1alpha1.json.snap b/crates/stackable-versioned/tests/snapshots/conversion__pass@persons_to_v1alpha1.json.snap similarity index 89% rename from crates/stackable-versioned/tests/snapshots/integration_test__pass@persons_to_v1alpha1.json.snap rename to crates/stackable-versioned/tests/snapshots/conversion__pass@persons_to_v1alpha1.json.snap index f9e9e06ec..bf70334da 100644 --- a/crates/stackable-versioned/tests/snapshots/integration_test__pass@persons_to_v1alpha1.json.snap +++ b/crates/stackable-versioned/tests/snapshots/conversion__pass@persons_to_v1alpha1.json.snap @@ -1,7 +1,7 @@ --- -source: crates/stackable-versioned/tests/integration_test.rs +source: crates/stackable-versioned/tests/conversion.rs expression: formatted -input_file: crates/stackable-versioned/tests/fixtures/inputs/pass/persons_to_v1alpha1.json +input_file: crates/stackable-versioned/tests/inputs/conversions/pass/persons_to_v1alpha1.json --- { "apiVersion": "apiextensions.k8s.io/v1", diff --git a/crates/stackable-versioned/tests/snapshots/integration_test__pass@persons_to_v3.json.snap b/crates/stackable-versioned/tests/snapshots/conversion__pass@persons_to_v3.json.snap similarity index 92% rename from crates/stackable-versioned/tests/snapshots/integration_test__pass@persons_to_v3.json.snap rename to crates/stackable-versioned/tests/snapshots/conversion__pass@persons_to_v3.json.snap index ed944f9cf..8d332b681 100644 --- a/crates/stackable-versioned/tests/snapshots/integration_test__pass@persons_to_v3.json.snap +++ b/crates/stackable-versioned/tests/snapshots/conversion__pass@persons_to_v3.json.snap @@ -1,7 +1,7 @@ --- -source: crates/stackable-versioned/tests/integration_test.rs +source: crates/stackable-versioned/tests/conversion.rs expression: formatted -input_file: crates/stackable-versioned/tests/fixtures/inputs/pass/persons_to_v3.json +input_file: crates/stackable-versioned/tests/inputs/conversions/pass/persons_to_v3.json --- { "apiVersion": "apiextensions.k8s.io/v1", From b7080ac03ca424a77338be86319cfee8e1600098 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Tue, 24 Jun 2025 15:32:25 +0200 Subject: [PATCH 25/33] Rename run_for_file -> convert_via_file --- crates/stackable-versioned/tests/conversion.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/stackable-versioned/tests/conversion.rs b/crates/stackable-versioned/tests/conversion.rs index 39df45e55..034454001 100644 --- a/crates/stackable-versioned/tests/conversion.rs +++ b/crates/stackable-versioned/tests/conversion.rs @@ -86,7 +86,7 @@ impl From for Gender { #[test] fn pass() { glob!("./inputs/conversions/pass/", "*.json", |path| { - let (request, response) = run_for_file(path); + let (request, response) = convert_via_file(path); let formatted = serde_json::to_string_pretty(&response) .expect("Failed to serialize ConversionResponse"); @@ -108,7 +108,7 @@ fn pass() { #[test] fn fail() { glob!("./inputs/conversions/fail/", "*.json", |path| { - let (request, response) = run_for_file(path); + let (request, response) = convert_via_file(path); let formatted = serde_json::to_string_pretty(&response) .expect("Failed to serialize ConversionResponse"); @@ -129,7 +129,7 @@ fn fail() { }) } -fn run_for_file(path: &Path) -> (ConversionReview, ConversionReview) { +fn convert_via_file(path: &Path) -> (ConversionReview, ConversionReview) { let request: ConversionReview = serde_json::from_reader(File::open(path).expect("failed to open test file")) .expect("failed to parse ConversionReview from test file"); From 3f9e21fe7f4586a0b93f88ffd7032d92ed7e11a3 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Tue, 24 Jun 2025 15:35:23 +0200 Subject: [PATCH 26/33] Derive copy, clone and debug --- .../src/codegen/container/struct/k8s.rs | 3 ++- ...able_versioned_macros__snapshot_tests__k8s@basic.rs.snap | 3 ++- ..._macros__snapshot_tests__k8s@conversion_tracking.rs.snap | 3 ++- ...oned_macros__snapshot_tests__k8s@crate_overrides.rs.snap | 3 ++- ...ble_versioned_macros__snapshot_tests__k8s@module.rs.snap | 6 ++++-- ...oned_macros__snapshot_tests__k8s@module_preserve.rs.snap | 6 ++++-- ...rsioned_macros__snapshot_tests__k8s@renamed_kind.rs.snap | 3 ++- ...versioned_macros__snapshot_tests__k8s@shortnames.rs.snap | 3 ++- 8 files changed, 20 insertions(+), 10 deletions(-) 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 c19bfa416..20e566a8a 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -263,6 +263,7 @@ impl Struct { quote! { #automatically_derived + #[derive(Copy, Clone, Debug)] #vis enum #enum_ident { #(#variant_idents),* } @@ -481,7 +482,7 @@ impl Struct { let current_object = Self::try_from_json_object(object.clone()) .map_err(|source| #convert_object_error::Parse { source })?; - match (current_object, &desired_api_version) { + match (current_object, desired_api_version) { #(#conversion_match_arms,)* // We explicitly list the remaining no-op cases, so the compiler ensures we // did not miss a conversion. 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 056031812..85f2362d8 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 @@ -209,7 +209,7 @@ impl Foo { .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; - match (current_object, &desired_api_version) { + match (current_object, desired_api_version) { (Self::V1Alpha1(__sv_foo), FooVersion::V1Beta1) => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Beta1(v1beta1::Foo { @@ -373,6 +373,7 @@ impl Foo { } } #[automatically_derived] +#[derive(Copy, Clone, Debug)] pub(crate) enum FooVersion { V1Alpha1, V1Beta1, 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 3bdd42319..481a5fed3 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 @@ -179,7 +179,7 @@ impl Foo { .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; - match (current_object, &desired_api_version) { + match (current_object, desired_api_version) { (Self::V1Alpha1(__sv_foo), FooVersion::V1Beta1) => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Beta1(v1beta1::Foo { @@ -343,6 +343,7 @@ impl Foo { } } #[automatically_derived] +#[derive(Copy, Clone, Debug)] pub(crate) enum FooVersion { V1Alpha1, V1Beta1, 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 cd6db5bdb..9e09db941 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 @@ -200,7 +200,7 @@ impl Foo { .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; - match (current_object, &desired_api_version) { + match (current_object, desired_api_version) { (Self::V1Alpha1(__sv_foo), FooVersion::V1Beta1) => { let converted: v1beta1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1Beta1(v1beta1::Foo { @@ -358,6 +358,7 @@ impl Foo { } } #[automatically_derived] +#[derive(Copy, Clone, Debug)] pub enum FooVersion { V1Alpha1, V1Beta1, 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 3ba723d80..3725d296c 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 @@ -372,7 +372,7 @@ impl Foo { .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; - match (current_object, &desired_api_version) { + match (current_object, desired_api_version) { (Self::V1Alpha1(__sv_foo), FooVersion::V1) => { let converted: v1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1(v1::Foo { @@ -532,6 +532,7 @@ impl Foo { } } #[automatically_derived] +#[derive(Copy, Clone, Debug)] pub(crate) enum FooVersion { V1Alpha1, V1, @@ -674,7 +675,7 @@ impl Bar { .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; - match (current_object, &desired_api_version) { + match (current_object, desired_api_version) { (Self::V1Alpha1(__sv_bar), BarVersion::V1) => { let converted: v1::BarSpec = __sv_bar.spec.into(); let desired_object = Self::V1(v1::Bar { @@ -834,6 +835,7 @@ impl Bar { } } #[automatically_derived] +#[derive(Copy, Clone, Debug)] pub(crate) enum BarVersion { V1Alpha1, V1, 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 363dd66d7..ca2e50475 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 @@ -353,7 +353,7 @@ pub(crate) mod versioned { .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; - match (current_object, &desired_api_version) { + match (current_object, desired_api_version) { (Self::V1Alpha1(__sv_foo), FooVersion::V1) => { let converted: v1::FooSpec = __sv_foo.spec.into(); let desired_object = Self::V1(v1::Foo { @@ -512,6 +512,7 @@ pub(crate) mod versioned { } } } + #[derive(Copy, Clone, Debug)] pub enum FooVersion { V1Alpha1, V1, @@ -650,7 +651,7 @@ pub(crate) mod versioned { .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; - match (current_object, &desired_api_version) { + match (current_object, desired_api_version) { (Self::V1Alpha1(__sv_bar), BarVersion::V1) => { let converted: v1::BarSpec = __sv_bar.spec.into(); let desired_object = Self::V1(v1::Bar { @@ -809,6 +810,7 @@ pub(crate) mod versioned { } } } + #[derive(Copy, Clone, Debug)] pub enum BarVersion { V1Alpha1, V1, 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 d508fc339..dc12ae504 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 @@ -185,7 +185,7 @@ impl FooBar { .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; - match (current_object, &desired_api_version) { + match (current_object, desired_api_version) { (Self::V1Alpha1(__sv_foobar), FooBarVersion::V1Beta1) => { let converted: v1beta1::FooSpec = __sv_foobar.spec.into(); let desired_object = Self::V1Beta1(v1beta1::FooBar { @@ -345,6 +345,7 @@ impl FooBar { } } #[automatically_derived] +#[derive(Copy, Clone, Debug)] pub enum FooBarVersion { V1Alpha1, V1Beta1, 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 f63c6f5a7..1e0c3340b 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 @@ -114,7 +114,7 @@ impl Foo { .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; - match (current_object, &desired_api_version) { + match (current_object, desired_api_version) { (Self::V1Alpha1(_), FooVersion::V1Alpha1) => { converted_objects.push(object) } @@ -174,6 +174,7 @@ impl Foo { } } #[automatically_derived] +#[derive(Copy, Clone, Debug)] pub(crate) enum FooVersion { V1Alpha1, } From 90884aa46df8b51478ee16c2ddc167bc73b25d6e Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Wed, 25 Jun 2025 09:55:23 +0200 Subject: [PATCH 27/33] try_from_json_object -> from_json_object --- .../src/codegen/container/struct/k8s.rs | 4 ++-- ...le_versioned_macros__snapshot_tests__k8s@basic.rs.snap | 4 ++-- ...acros__snapshot_tests__k8s@conversion_tracking.rs.snap | 4 ++-- ...ed_macros__snapshot_tests__k8s@crate_overrides.rs.snap | 4 ++-- ...e_versioned_macros__snapshot_tests__k8s@module.rs.snap | 8 ++++---- ...ed_macros__snapshot_tests__k8s@module_preserve.rs.snap | 8 ++++---- ...ioned_macros__snapshot_tests__k8s@renamed_kind.rs.snap | 4 ++-- ...rsioned_macros__snapshot_tests__k8s@shortnames.rs.snap | 4 ++-- 8 files changed, 20 insertions(+), 20 deletions(-) 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 20e566a8a..7b31962b1 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -180,7 +180,7 @@ impl Struct { #convert_method - fn try_from_json_object(object_value: #serde_json_path::Value) -> ::std::result::Result { + fn from_json_object(object_value: #serde_json_path::Value) -> ::std::result::Result { let object_kind = object_value .get("kind") .ok_or_else(|| #parse_object_error::FieldMissing{ field: "kind".to_owned() })? @@ -479,7 +479,7 @@ impl Struct { for object in objects { // This clone is required because in the noop case we move the object into // the converted objects vec. - let current_object = Self::try_from_json_object(object.clone()) + let current_object = Self::from_json_object(object.clone()) .map_err(|source| #convert_object_error::Parse { source })?; match (current_object, desired_api_version) { 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 85f2362d8..b9ef763e6 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 @@ -205,7 +205,7 @@ impl Foo { })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let current_object = Self::try_from_json_object(object.clone()) + let current_object = Self::from_json_object(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; @@ -305,7 +305,7 @@ impl Foo { } ::std::result::Result::Ok(converted_objects) } - fn try_from_json_object( + fn from_json_object( object_value: ::serde_json::Value, ) -> ::std::result::Result { let object_kind = object_value 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 481a5fed3..3a119e0a5 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 @@ -175,7 +175,7 @@ impl Foo { })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let current_object = Self::try_from_json_object(object.clone()) + let current_object = Self::from_json_object(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; @@ -275,7 +275,7 @@ impl Foo { } ::std::result::Result::Ok(converted_objects) } - fn try_from_json_object( + fn from_json_object( object_value: ::serde_json::Value, ) -> ::std::result::Result { let object_kind = object_value 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 9e09db941..573b459d5 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 @@ -196,7 +196,7 @@ impl Foo { })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let current_object = Self::try_from_json_object(object.clone()) + let current_object = Self::from_json_object(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; @@ -290,7 +290,7 @@ impl Foo { } ::std::result::Result::Ok(converted_objects) } - fn try_from_json_object( + fn from_json_object( object_value: ::serde_json::Value, ) -> ::std::result::Result { let object_kind = object_value 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 3725d296c..ad2f7cbc5 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 @@ -368,7 +368,7 @@ impl Foo { })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let current_object = Self::try_from_json_object(object.clone()) + let current_object = Self::from_json_object(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; @@ -464,7 +464,7 @@ impl Foo { } ::std::result::Result::Ok(converted_objects) } - fn try_from_json_object( + fn from_json_object( object_value: ::serde_json::Value, ) -> ::std::result::Result { let object_kind = object_value @@ -671,7 +671,7 @@ impl Bar { })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let current_object = Self::try_from_json_object(object.clone()) + let current_object = Self::from_json_object(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; @@ -767,7 +767,7 @@ impl Bar { } ::std::result::Result::Ok(converted_objects) } - fn try_from_json_object( + fn from_json_object( object_value: ::serde_json::Value, ) -> ::std::result::Result { let object_kind = object_value 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 ca2e50475..07dec5b22 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 @@ -349,7 +349,7 @@ pub(crate) mod versioned { })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let current_object = Self::try_from_json_object(object.clone()) + let current_object = Self::from_json_object(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; @@ -445,7 +445,7 @@ pub(crate) mod versioned { } ::std::result::Result::Ok(converted_objects) } - fn try_from_json_object( + fn from_json_object( object_value: ::serde_json::Value, ) -> ::std::result::Result { let object_kind = object_value @@ -647,7 +647,7 @@ pub(crate) mod versioned { })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let current_object = Self::try_from_json_object(object.clone()) + let current_object = Self::from_json_object(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; @@ -743,7 +743,7 @@ pub(crate) mod versioned { } ::std::result::Result::Ok(converted_objects) } - fn try_from_json_object( + fn from_json_object( object_value: ::serde_json::Value, ) -> ::std::result::Result { let object_kind = object_value 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 dc12ae504..754e08532 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 @@ -181,7 +181,7 @@ impl FooBar { })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let current_object = Self::try_from_json_object(object.clone()) + let current_object = Self::from_json_object(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; @@ -277,7 +277,7 @@ impl FooBar { } ::std::result::Result::Ok(converted_objects) } - fn try_from_json_object( + fn from_json_object( object_value: ::serde_json::Value, ) -> ::std::result::Result { let object_kind = object_value 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 1e0c3340b..7c2e8a5d6 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 @@ -110,7 +110,7 @@ impl Foo { })?; let mut converted_objects = ::std::vec::Vec::with_capacity(objects.len()); for object in objects { - let current_object = Self::try_from_json_object(object.clone()) + let current_object = Self::from_json_object(object.clone()) .map_err(|source| ::stackable_versioned::ConvertObjectError::Parse { source, })?; @@ -122,7 +122,7 @@ impl Foo { } ::std::result::Result::Ok(converted_objects) } - fn try_from_json_object( + fn from_json_object( object_value: ::serde_json::Value, ) -> ::std::result::Result { let object_kind = object_value From 426e1b7cfa22e236090bce840a4b63a62b66d162 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Wed, 25 Jun 2025 09:56:45 +0200 Subject: [PATCH 28/33] conversion.rs -> conversions.rs --- .../stackable-versioned/tests/{conversion.rs => conversions.rs} | 0 ...ng.json.snap => conversions__fail@request_missing.json.snap} | 2 +- ....snap => conversions__fail@unkown_current_version.json.snap} | 2 +- ....snap => conversions__fail@unkown_desired_version.json.snap} | 2 +- ...ap => conversions__fail@unparseable_missing_field.json.snap} | 2 +- ...ng_kind.json.snap => conversions__fail@wrong_kind.json.snap} | 2 +- ...son.snap => conversions__pass@persons_to_v1alpha1.json.snap} | 2 +- ...o_v3.json.snap => conversions__pass@persons_to_v3.json.snap} | 2 +- 8 files changed, 7 insertions(+), 7 deletions(-) rename crates/stackable-versioned/tests/{conversion.rs => conversions.rs} (100%) rename crates/stackable-versioned/tests/snapshots/{conversion__fail@request_missing.json.snap => conversions__fail@request_missing.json.snap} (88%) rename crates/stackable-versioned/tests/snapshots/{conversion__fail@unkown_current_version.json.snap => conversions__fail@unkown_current_version.json.snap} (91%) rename crates/stackable-versioned/tests/snapshots/{conversion__fail@unkown_desired_version.json.snap => conversions__fail@unkown_desired_version.json.snap} (91%) rename crates/stackable-versioned/tests/snapshots/{conversion__fail@unparseable_missing_field.json.snap => conversions__fail@unparseable_missing_field.json.snap} (91%) rename crates/stackable-versioned/tests/snapshots/{conversion__fail@wrong_kind.json.snap => conversions__fail@wrong_kind.json.snap} (91%) rename crates/stackable-versioned/tests/snapshots/{conversion__pass@persons_to_v1alpha1.json.snap => conversions__pass@persons_to_v1alpha1.json.snap} (96%) rename crates/stackable-versioned/tests/snapshots/{conversion__pass@persons_to_v3.json.snap => conversions__pass@persons_to_v3.json.snap} (97%) diff --git a/crates/stackable-versioned/tests/conversion.rs b/crates/stackable-versioned/tests/conversions.rs similarity index 100% rename from crates/stackable-versioned/tests/conversion.rs rename to crates/stackable-versioned/tests/conversions.rs diff --git a/crates/stackable-versioned/tests/snapshots/conversion__fail@request_missing.json.snap b/crates/stackable-versioned/tests/snapshots/conversions__fail@request_missing.json.snap similarity index 88% rename from crates/stackable-versioned/tests/snapshots/conversion__fail@request_missing.json.snap rename to crates/stackable-versioned/tests/snapshots/conversions__fail@request_missing.json.snap index 6946aab2f..1e4cf0256 100644 --- a/crates/stackable-versioned/tests/snapshots/conversion__fail@request_missing.json.snap +++ b/crates/stackable-versioned/tests/snapshots/conversions__fail@request_missing.json.snap @@ -1,5 +1,5 @@ --- -source: crates/stackable-versioned/tests/conversion.rs +source: crates/stackable-versioned/tests/conversions.rs expression: formatted input_file: crates/stackable-versioned/tests/inputs/conversions/fail/request_missing.json --- diff --git a/crates/stackable-versioned/tests/snapshots/conversion__fail@unkown_current_version.json.snap b/crates/stackable-versioned/tests/snapshots/conversions__fail@unkown_current_version.json.snap similarity index 91% rename from crates/stackable-versioned/tests/snapshots/conversion__fail@unkown_current_version.json.snap rename to crates/stackable-versioned/tests/snapshots/conversions__fail@unkown_current_version.json.snap index 5ac139d49..5a79d0179 100644 --- a/crates/stackable-versioned/tests/snapshots/conversion__fail@unkown_current_version.json.snap +++ b/crates/stackable-versioned/tests/snapshots/conversions__fail@unkown_current_version.json.snap @@ -1,5 +1,5 @@ --- -source: crates/stackable-versioned/tests/conversion.rs +source: crates/stackable-versioned/tests/conversions.rs expression: formatted input_file: crates/stackable-versioned/tests/inputs/conversions/fail/unkown_current_version.json --- diff --git a/crates/stackable-versioned/tests/snapshots/conversion__fail@unkown_desired_version.json.snap b/crates/stackable-versioned/tests/snapshots/conversions__fail@unkown_desired_version.json.snap similarity index 91% rename from crates/stackable-versioned/tests/snapshots/conversion__fail@unkown_desired_version.json.snap rename to crates/stackable-versioned/tests/snapshots/conversions__fail@unkown_desired_version.json.snap index dcab27f23..dc141268d 100644 --- a/crates/stackable-versioned/tests/snapshots/conversion__fail@unkown_desired_version.json.snap +++ b/crates/stackable-versioned/tests/snapshots/conversions__fail@unkown_desired_version.json.snap @@ -1,5 +1,5 @@ --- -source: crates/stackable-versioned/tests/conversion.rs +source: crates/stackable-versioned/tests/conversions.rs expression: formatted input_file: crates/stackable-versioned/tests/inputs/conversions/fail/unkown_desired_version.json --- diff --git a/crates/stackable-versioned/tests/snapshots/conversion__fail@unparseable_missing_field.json.snap b/crates/stackable-versioned/tests/snapshots/conversions__fail@unparseable_missing_field.json.snap similarity index 91% rename from crates/stackable-versioned/tests/snapshots/conversion__fail@unparseable_missing_field.json.snap rename to crates/stackable-versioned/tests/snapshots/conversions__fail@unparseable_missing_field.json.snap index 3e329b643..cb9ad38b1 100644 --- a/crates/stackable-versioned/tests/snapshots/conversion__fail@unparseable_missing_field.json.snap +++ b/crates/stackable-versioned/tests/snapshots/conversions__fail@unparseable_missing_field.json.snap @@ -1,5 +1,5 @@ --- -source: crates/stackable-versioned/tests/conversion.rs +source: crates/stackable-versioned/tests/conversions.rs expression: formatted input_file: crates/stackable-versioned/tests/inputs/conversions/fail/unparseable_missing_field.json --- diff --git a/crates/stackable-versioned/tests/snapshots/conversion__fail@wrong_kind.json.snap b/crates/stackable-versioned/tests/snapshots/conversions__fail@wrong_kind.json.snap similarity index 91% rename from crates/stackable-versioned/tests/snapshots/conversion__fail@wrong_kind.json.snap rename to crates/stackable-versioned/tests/snapshots/conversions__fail@wrong_kind.json.snap index f65d9b84f..9986793ce 100644 --- a/crates/stackable-versioned/tests/snapshots/conversion__fail@wrong_kind.json.snap +++ b/crates/stackable-versioned/tests/snapshots/conversions__fail@wrong_kind.json.snap @@ -1,5 +1,5 @@ --- -source: crates/stackable-versioned/tests/conversion.rs +source: crates/stackable-versioned/tests/conversions.rs expression: formatted input_file: crates/stackable-versioned/tests/inputs/conversions/fail/wrong_kind.json --- diff --git a/crates/stackable-versioned/tests/snapshots/conversion__pass@persons_to_v1alpha1.json.snap b/crates/stackable-versioned/tests/snapshots/conversions__pass@persons_to_v1alpha1.json.snap similarity index 96% rename from crates/stackable-versioned/tests/snapshots/conversion__pass@persons_to_v1alpha1.json.snap rename to crates/stackable-versioned/tests/snapshots/conversions__pass@persons_to_v1alpha1.json.snap index bf70334da..ced5fb427 100644 --- a/crates/stackable-versioned/tests/snapshots/conversion__pass@persons_to_v1alpha1.json.snap +++ b/crates/stackable-versioned/tests/snapshots/conversions__pass@persons_to_v1alpha1.json.snap @@ -1,5 +1,5 @@ --- -source: crates/stackable-versioned/tests/conversion.rs +source: crates/stackable-versioned/tests/conversions.rs expression: formatted input_file: crates/stackable-versioned/tests/inputs/conversions/pass/persons_to_v1alpha1.json --- diff --git a/crates/stackable-versioned/tests/snapshots/conversion__pass@persons_to_v3.json.snap b/crates/stackable-versioned/tests/snapshots/conversions__pass@persons_to_v3.json.snap similarity index 97% rename from crates/stackable-versioned/tests/snapshots/conversion__pass@persons_to_v3.json.snap rename to crates/stackable-versioned/tests/snapshots/conversions__pass@persons_to_v3.json.snap index 8d332b681..f6b9a7aec 100644 --- a/crates/stackable-versioned/tests/snapshots/conversion__pass@persons_to_v3.json.snap +++ b/crates/stackable-versioned/tests/snapshots/conversions__pass@persons_to_v3.json.snap @@ -1,5 +1,5 @@ --- -source: crates/stackable-versioned/tests/conversion.rs +source: crates/stackable-versioned/tests/conversions.rs expression: formatted input_file: crates/stackable-versioned/tests/inputs/conversions/pass/persons_to_v3.json --- From 0bf0039c6174816780f12eda2021e8155c479e2d Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Wed, 25 Jun 2025 13:28:48 +0200 Subject: [PATCH 29/33] simplify noop match --- .../src/codegen/container/struct/k8s.rs | 31 +++++++------------ ..._macros__snapshot_tests__k8s@basic.rs.snap | 8 ++--- ...hot_tests__k8s@conversion_tracking.rs.snap | 8 ++--- ...napshot_tests__k8s@crate_overrides.rs.snap | 8 ++--- ...macros__snapshot_tests__k8s@module.rs.snap | 16 ++++------ ...napshot_tests__k8s@module_preserve.rs.snap | 16 ++++------ ...__snapshot_tests__k8s@renamed_kind.rs.snap | 10 ++---- 7 files changed, 36 insertions(+), 61 deletions(-) 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 7b31962b1..2541ea768 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -373,7 +373,7 @@ impl Struct { // Generate conversion paths and the match arms for these paths let conversion_match_arms = self.generate_kubernetes_conversion_match_arms(versions, kubernetes_arguments); - let noop_match_arms = self.generate_kubernetes_noop_match_arms(versions); + let noop_match_arm = self.generate_kubernetes_noop_match_arm(versions); // TODO (@Techassi): Make this a feature, drop the option from the macro arguments // Generate tracing attributes and events if tracing is enabled @@ -486,7 +486,7 @@ impl Struct { #(#conversion_match_arms,)* // We explicitly list the remaining no-op cases, so the compiler ensures we // did not miss a conversion. - #(#noop_match_arms,)* + #noop_match_arm, } } @@ -579,25 +579,18 @@ impl Struct { .collect() } - fn generate_kubernetes_noop_match_arms( - &self, - versions: &[VersionDefinition], - ) -> Vec { + fn generate_kubernetes_noop_match_arm(&self, versions: &[VersionDefinition]) -> TokenStream { let version_enum_ident = &self.common.idents.kubernetes_version; + let version_idents = versions.iter().map(|v| &v.idents.variant); - versions - .iter() - .map(|version| { - let version_ident = &version.idents.variant; - - quote! { - // This is the case if the desired version matches the current object api version. - // NOTE (@Techassi): I'm curious if this will ever happen? In theory the K8s - // apiserver should never send such a conversion review. - (Self::#version_ident(_), #version_enum_ident::#version_ident) => converted_objects.push(object) - } - }) - .collect() + quote! { + // This is the case if the desired version matches the current object api version. + // NOTE (@Techassi): I'm curious if this will ever happen? In theory the K8s + // apiserver should never send such a conversion review. + #( + (Self::#version_idents(_), #version_enum_ident::#version_idents) + )|* => converted_objects.push(object) + } } fn generate_kubernetes_conversion_tracing( 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 b9ef763e6..f78d5acbe 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 @@ -296,11 +296,9 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), FooVersion::V1Alpha1) => { - converted_objects.push(object) - } - (Self::V1Beta1(_), FooVersion::V1Beta1) => converted_objects.push(object), - (Self::V1(_), FooVersion::V1) => converted_objects.push(object), + (Self::V1Alpha1(_), FooVersion::V1Alpha1) + | (Self::V1Beta1(_), FooVersion::V1Beta1) + | (Self::V1(_), FooVersion::V1) => converted_objects.push(object), } } ::std::result::Result::Ok(converted_objects) 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 3a119e0a5..fde1ea482 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 @@ -266,11 +266,9 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), FooVersion::V1Alpha1) => { - converted_objects.push(object) - } - (Self::V1Beta1(_), FooVersion::V1Beta1) => converted_objects.push(object), - (Self::V1(_), FooVersion::V1) => converted_objects.push(object), + (Self::V1Alpha1(_), FooVersion::V1Alpha1) + | (Self::V1Beta1(_), FooVersion::V1Beta1) + | (Self::V1(_), FooVersion::V1) => converted_objects.push(object), } } ::std::result::Result::Ok(converted_objects) 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 573b459d5..581432a5a 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 @@ -281,11 +281,9 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), FooVersion::V1Alpha1) => { - converted_objects.push(object) - } - (Self::V1Beta1(_), FooVersion::V1Beta1) => converted_objects.push(object), - (Self::V1(_), FooVersion::V1) => converted_objects.push(object), + (Self::V1Alpha1(_), FooVersion::V1Alpha1) + | (Self::V1Beta1(_), FooVersion::V1Beta1) + | (Self::V1(_), FooVersion::V1) => converted_objects.push(object), } } ::std::result::Result::Ok(converted_objects) 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 ad2f7cbc5..706b6d9b1 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 @@ -453,11 +453,9 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), FooVersion::V1Alpha1) => { - converted_objects.push(object) - } - (Self::V1(_), FooVersion::V1) => converted_objects.push(object), - (Self::V2Alpha1(_), FooVersion::V2Alpha1) => { + (Self::V1Alpha1(_), FooVersion::V1Alpha1) + | (Self::V1(_), FooVersion::V1) + | (Self::V2Alpha1(_), FooVersion::V2Alpha1) => { converted_objects.push(object) } } @@ -756,11 +754,9 @@ impl Bar { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), BarVersion::V1Alpha1) => { - converted_objects.push(object) - } - (Self::V1(_), BarVersion::V1) => converted_objects.push(object), - (Self::V2Alpha1(_), BarVersion::V2Alpha1) => { + (Self::V1Alpha1(_), BarVersion::V1Alpha1) + | (Self::V1(_), BarVersion::V1) + | (Self::V2Alpha1(_), BarVersion::V2Alpha1) => { converted_objects.push(object) } } 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 07dec5b22..74d7cf906 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 @@ -434,11 +434,9 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), FooVersion::V1Alpha1) => { - converted_objects.push(object) - } - (Self::V1(_), FooVersion::V1) => converted_objects.push(object), - (Self::V2Alpha1(_), FooVersion::V2Alpha1) => { + (Self::V1Alpha1(_), FooVersion::V1Alpha1) + | (Self::V1(_), FooVersion::V1) + | (Self::V2Alpha1(_), FooVersion::V2Alpha1) => { converted_objects.push(object) } } @@ -732,11 +730,9 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), BarVersion::V1Alpha1) => { - converted_objects.push(object) - } - (Self::V1(_), BarVersion::V1) => converted_objects.push(object), - (Self::V2Alpha1(_), BarVersion::V2Alpha1) => { + (Self::V1Alpha1(_), BarVersion::V1Alpha1) + | (Self::V1(_), BarVersion::V1) + | (Self::V2Alpha1(_), BarVersion::V2Alpha1) => { converted_objects.push(object) } } 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 754e08532..fa277383b 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 @@ -266,13 +266,9 @@ impl FooBar { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), FooBarVersion::V1Alpha1) => { - converted_objects.push(object) - } - (Self::V1Beta1(_), FooBarVersion::V1Beta1) => { - converted_objects.push(object) - } - (Self::V1(_), FooBarVersion::V1) => converted_objects.push(object), + (Self::V1Alpha1(_), FooBarVersion::V1Alpha1) + | (Self::V1Beta1(_), FooBarVersion::V1Beta1) + | (Self::V1(_), FooBarVersion::V1) => converted_objects.push(object), } } ::std::result::Result::Ok(converted_objects) From 1f6a7eff340553f7a807910975d47c14c166b0df Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Wed, 25 Jun 2025 13:49:50 +0200 Subject: [PATCH 30/33] Simply noop branch --- .../src/codegen/container/struct/k8s.rs | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) 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 2541ea768..60c1fd06d 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -362,6 +362,7 @@ impl Struct { let struct_ident = &self.common.idents.kubernetes; let version_enum_ident = &self.common.idents.kubernetes_version; + let version_idents = versions.iter().map(|v| &v.idents.variant); let kube_client_path = &*kubernetes_arguments.crates.kube_client; let serde_json_path = &*kubernetes_arguments.crates.serde_json; @@ -373,7 +374,6 @@ impl Struct { // Generate conversion paths and the match arms for these paths let conversion_match_arms = self.generate_kubernetes_conversion_match_arms(versions, kubernetes_arguments); - let noop_match_arm = self.generate_kubernetes_noop_match_arm(versions); // TODO (@Techassi): Make this a feature, drop the option from the macro arguments // Generate tracing attributes and events if tracing is enabled @@ -484,9 +484,17 @@ impl Struct { match (current_object, desired_api_version) { #(#conversion_match_arms,)* + // In case the desired version matches the current object api version, we + // don't need to do anything. + // // We explicitly list the remaining no-op cases, so the compiler ensures we // did not miss a conversion. - #noop_match_arm, + // + // NOTE (@Techassi): I'm curious if this will ever happen? In theory the K8s + // apiserver should never send such a conversion review. + #( + (Self::#version_idents(_), #version_enum_ident::#version_idents) + )|* => converted_objects.push(object) } } @@ -579,20 +587,6 @@ impl Struct { .collect() } - fn generate_kubernetes_noop_match_arm(&self, versions: &[VersionDefinition]) -> TokenStream { - let version_enum_ident = &self.common.idents.kubernetes_version; - let version_idents = versions.iter().map(|v| &v.idents.variant); - - quote! { - // This is the case if the desired version matches the current object api version. - // NOTE (@Techassi): I'm curious if this will ever happen? In theory the K8s - // apiserver should never send such a conversion review. - #( - (Self::#version_idents(_), #version_enum_ident::#version_idents) - )|* => converted_objects.push(object) - } - } - fn generate_kubernetes_conversion_tracing( &self, kubernetes_arguments: &KubernetesArguments, From ab02a5eb9b813414662d56d07bf9514276045778 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Wed, 25 Jun 2025 13:53:59 +0200 Subject: [PATCH 31/33] YOLO --- .../src/codegen/container/struct/k8s.rs | 15 ++++++++------- ...oned_macros__snapshot_tests__k8s@basic.rs.snap | 4 +--- ...napshot_tests__k8s@conversion_tracking.rs.snap | 4 +--- ...s__snapshot_tests__k8s@crate_overrides.rs.snap | 4 +--- ...ned_macros__snapshot_tests__k8s@module.rs.snap | 12 ++---------- ...s__snapshot_tests__k8s@module_preserve.rs.snap | 12 ++---------- ...cros__snapshot_tests__k8s@renamed_kind.rs.snap | 4 +--- ...macros__snapshot_tests__k8s@shortnames.rs.snap | 4 +--- 8 files changed, 17 insertions(+), 42 deletions(-) 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 60c1fd06d..c9fa59e3a 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct/k8s.rs @@ -362,7 +362,6 @@ impl Struct { let struct_ident = &self.common.idents.kubernetes; let version_enum_ident = &self.common.idents.kubernetes_version; - let version_idents = versions.iter().map(|v| &v.idents.variant); let kube_client_path = &*kubernetes_arguments.crates.kube_client; let serde_json_path = &*kubernetes_arguments.crates.serde_json; @@ -487,14 +486,16 @@ impl Struct { // In case the desired version matches the current object api version, we // don't need to do anything. // - // We explicitly list the remaining no-op cases, so the compiler ensures we - // did not miss a conversion. - // // NOTE (@Techassi): I'm curious if this will ever happen? In theory the K8s // apiserver should never send such a conversion review. - #( - (Self::#version_idents(_), #version_enum_ident::#version_idents) - )|* => converted_objects.push(object) + // + // Note(@sbernauer): I would prefer to explicitly list the remaining no-op + // cases, so the compiler ensures we did not miss a conversion + // // let version_idents = versions.iter().map(|v| &v.idents.variant); + // #( + // (Self::#version_idents(_), #version_enum_ident::#version_idents) + // )|* => converted_objects.push(object) + _ => converted_objects.push(object), } } 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 f78d5acbe..fc3a3f401 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 @@ -296,9 +296,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), FooVersion::V1Alpha1) - | (Self::V1Beta1(_), FooVersion::V1Beta1) - | (Self::V1(_), FooVersion::V1) => converted_objects.push(object), + _ => converted_objects.push(object), } } ::std::result::Result::Ok(converted_objects) 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 fde1ea482..dc0969972 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 @@ -266,9 +266,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), FooVersion::V1Alpha1) - | (Self::V1Beta1(_), FooVersion::V1Beta1) - | (Self::V1(_), FooVersion::V1) => converted_objects.push(object), + _ => converted_objects.push(object), } } ::std::result::Result::Ok(converted_objects) 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 581432a5a..4a5d94073 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 @@ -281,9 +281,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), FooVersion::V1Alpha1) - | (Self::V1Beta1(_), FooVersion::V1Beta1) - | (Self::V1(_), FooVersion::V1) => converted_objects.push(object), + _ => converted_objects.push(object), } } ::std::result::Result::Ok(converted_objects) 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 706b6d9b1..9c3d2a6df 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 @@ -453,11 +453,7 @@ impl Foo { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), FooVersion::V1Alpha1) - | (Self::V1(_), FooVersion::V1) - | (Self::V2Alpha1(_), FooVersion::V2Alpha1) => { - converted_objects.push(object) - } + _ => converted_objects.push(object), } } ::std::result::Result::Ok(converted_objects) @@ -754,11 +750,7 @@ impl Bar { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), BarVersion::V1Alpha1) - | (Self::V1(_), BarVersion::V1) - | (Self::V2Alpha1(_), BarVersion::V2Alpha1) => { - converted_objects.push(object) - } + _ => converted_objects.push(object), } } ::std::result::Result::Ok(converted_objects) 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 74d7cf906..6208b1042 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 @@ -434,11 +434,7 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), FooVersion::V1Alpha1) - | (Self::V1(_), FooVersion::V1) - | (Self::V2Alpha1(_), FooVersion::V2Alpha1) => { - converted_objects.push(object) - } + _ => converted_objects.push(object), } } ::std::result::Result::Ok(converted_objects) @@ -730,11 +726,7 @@ pub(crate) mod versioned { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), BarVersion::V1Alpha1) - | (Self::V1(_), BarVersion::V1) - | (Self::V2Alpha1(_), BarVersion::V2Alpha1) => { - converted_objects.push(object) - } + _ => converted_objects.push(object), } } ::std::result::Result::Ok(converted_objects) 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 fa277383b..e71e3bfd2 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 @@ -266,9 +266,7 @@ impl FooBar { })?; converted_objects.push(desired_object); } - (Self::V1Alpha1(_), FooBarVersion::V1Alpha1) - | (Self::V1Beta1(_), FooBarVersion::V1Beta1) - | (Self::V1(_), FooBarVersion::V1) => converted_objects.push(object), + _ => converted_objects.push(object), } } ::std::result::Result::Ok(converted_objects) 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 7c2e8a5d6..111436af9 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 @@ -115,9 +115,7 @@ impl Foo { source, })?; match (current_object, desired_api_version) { - (Self::V1Alpha1(_), FooVersion::V1Alpha1) => { - converted_objects.push(object) - } + _ => converted_objects.push(object), } } ::std::result::Result::Ok(converted_objects) From 75ade7ac8c2a5c0703e313a9935c4551efb17b36 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Wed, 25 Jun 2025 14:30:34 +0200 Subject: [PATCH 32/33] Add changelog entry --- crates/stackable-versioned/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/stackable-versioned/CHANGELOG.md b/crates/stackable-versioned/CHANGELOG.md index 2f84f096b..4cc886284 100644 --- a/crates/stackable-versioned/CHANGELOG.md +++ b/crates/stackable-versioned/CHANGELOG.md @@ -9,6 +9,8 @@ All notable changes to this project will be documented in this file. - Add support for CRD conversions via ConversionReviews ([#1050], [#1061]). - Add new `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 - Implement basic ground work for downgrading custom resources ([#1033]). - Emit `From` implementations to downgrade custom resource specs. - Emit a status struct to be able to track values required during downgrades and upgrades of From cb26df90e089804aba11001f1b324cde3917e38c Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Wed, 25 Jun 2025 14:31:19 +0200 Subject: [PATCH 33/33] changelog --- crates/stackable-versioned/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/stackable-versioned/CHANGELOG.md b/crates/stackable-versioned/CHANGELOG.md index 4cc886284..58968d114 100644 --- a/crates/stackable-versioned/CHANGELOG.md +++ b/crates/stackable-versioned/CHANGELOG.md @@ -10,7 +10,7 @@ All notable changes to this project will be documented in this file. - Add new `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 + functions. - Implement basic ground work for downgrading custom resources ([#1033]). - Emit `From` implementations to downgrade custom resource specs. - Emit a status struct to be able to track values required during downgrades and upgrades of