diff --git a/crates/stackable-versioned-macros/fixtures/inputs/k8s/renamed_kind.rs b/crates/stackable-versioned-macros/fixtures/inputs/k8s/renamed_kind.rs new file mode 100644 index 00000000..8cfa272d --- /dev/null +++ b/crates/stackable-versioned-macros/fixtures/inputs/k8s/renamed_kind.rs @@ -0,0 +1,24 @@ +#[versioned( + version(name = "v1alpha1"), + version(name = "v1beta1"), + version(name = "v1"), + k8s( + group = "stackable.tech", + kind = "FooBar", + singular = "foo", + plural = "foos", + namespaced, + ) +)] +// --- +#[derive( + Clone, Debug, serde::Deserialize, serde::Serialize, schemars::JsonSchema, kube::CustomResource, +)] +pub struct FooSpec { + #[versioned( + added(since = "v1beta1"), + changed(since = "v1", from_name = "bah", from_type = "u16") + )] + bar: usize, + baz: bool, +} diff --git a/crates/stackable-versioned-macros/fixtures/snapshots/stackable_versioned_macros__test__k8s_snapshots@renamed_kind.rs.snap b/crates/stackable-versioned-macros/fixtures/snapshots/stackable_versioned_macros__test__k8s_snapshots@renamed_kind.rs.snap new file mode 100644 index 00000000..a64f9a35 --- /dev/null +++ b/crates/stackable-versioned-macros/fixtures/snapshots/stackable_versioned_macros__test__k8s_snapshots@renamed_kind.rs.snap @@ -0,0 +1,177 @@ +--- +source: crates/stackable-versioned-macros/src/lib.rs +expression: formatted +input_file: crates/stackable-versioned-macros/fixtures/inputs/k8s/renamed_kind.rs +--- +#[automatically_derived] +pub mod v1alpha1 { + use super::*; + #[derive( + Clone, + Debug, + serde::Deserialize, + serde::Serialize, + schemars::JsonSchema, + kube::CustomResource, + )] + #[kube( + group = "stackable.tech", + version = "v1alpha1", + kind = "FooBar", + singular = "foo", + plural = "foos", + namespaced + )] + pub struct FooSpec { + pub baz: bool, + } +} +#[automatically_derived] +impl ::std::convert::From for v1beta1::FooSpec { + fn from(__sv_foospec: v1alpha1::FooSpec) -> Self { + Self { + bah: ::std::default::Default::default(), + baz: __sv_foospec.baz, + } + } +} +#[automatically_derived] +pub mod v1beta1 { + use super::*; + #[derive( + Clone, + Debug, + serde::Deserialize, + serde::Serialize, + schemars::JsonSchema, + kube::CustomResource, + )] + #[kube( + group = "stackable.tech", + version = "v1beta1", + kind = "FooBar", + singular = "foo", + plural = "foos", + namespaced + )] + pub struct FooSpec { + pub bah: u16, + pub baz: bool, + } +} +#[automatically_derived] +impl ::std::convert::From for v1::FooSpec { + fn from(__sv_foospec: v1beta1::FooSpec) -> Self { + Self { + bar: __sv_foospec.bah.into(), + baz: __sv_foospec.baz, + } + } +} +#[automatically_derived] +pub mod v1 { + use super::*; + #[derive( + Clone, + Debug, + serde::Deserialize, + serde::Serialize, + schemars::JsonSchema, + kube::CustomResource, + )] + #[kube( + group = "stackable.tech", + version = "v1", + kind = "FooBar", + singular = "foo", + plural = "foos", + namespaced + )] + pub struct FooSpec { + pub bar: usize, + pub baz: bool, + } +} +#[automatically_derived] +pub enum FooBar { + V1Alpha1, + V1Beta1, + V1, +} +#[automatically_derived] +impl ::std::fmt::Display for FooBar { + fn fmt( + &self, + f: &mut ::std::fmt::Formatter<'_>, + ) -> ::std::result::Result<(), ::std::fmt::Error> { + match self { + Self::V1Alpha1 => f.write_str("v1alpha1"), + Self::V1Beta1 => f.write_str("v1beta1"), + Self::V1 => f.write_str("v1"), + } + } +} +#[automatically_derived] +impl FooBar { + /// Generates a merged CRD which contains all versions defined using the `#[versioned()]` macro. + pub fn merged_crd( + stored_apiversion: Self, + ) -> ::std::result::Result< + ::k8s_openapi::apiextensions_apiserver::pkg::apis::apiextensions::v1::CustomResourceDefinition, + ::kube::core::crd::MergeError, + > { + ::kube::core::crd::merge_crds( + vec![ + < v1alpha1::FooBar as ::kube::core::CustomResourceExt > ::crd(), < + v1beta1::FooBar as ::kube::core::CustomResourceExt > ::crd(), < + v1::FooBar as ::kube::core::CustomResourceExt > ::crd() + ], + &stored_apiversion.to_string(), + ) + } + /// Generates and writes a merged CRD which contains all versions defined using the `#[versioned()]` + /// macro to a file located at `path`. + pub fn write_merged_crd

( + path: P, + stored_apiversion: Self, + operator_version: &str, + ) -> Result<(), ::stackable_versioned::Error> + where + P: AsRef<::std::path::Path>, + { + use ::stackable_shared::yaml::{YamlSchema, SerializeOptions}; + let merged_crd = Self::merged_crd(stored_apiversion) + .map_err(|err| ::stackable_versioned::Error::MergeCrd { + source: err, + })?; + YamlSchema::write_yaml_schema( + &merged_crd, + path, + operator_version, + SerializeOptions::default(), + ) + .map_err(|err| ::stackable_versioned::Error::SerializeYaml { + source: err, + }) + } + /// Generates and writes a merged CRD which contains all versions defined using the `#[versioned()]` + /// macro to stdout. + pub fn print_merged_crd( + stored_apiversion: Self, + operator_version: &str, + ) -> Result<(), ::stackable_versioned::Error> { + use ::stackable_shared::yaml::{YamlSchema, SerializeOptions}; + let merged_crd = Self::merged_crd(stored_apiversion) + .map_err(|err| ::stackable_versioned::Error::MergeCrd { + source: err, + })?; + YamlSchema::print_yaml_schema( + &merged_crd, + operator_version, + SerializeOptions::default(), + ) + .map_err(|err| ::stackable_versioned::Error::SerializeYaml { + source: err, + }) + } +} diff --git a/crates/stackable-versioned-macros/src/codegen/container/enum.rs b/crates/stackable-versioned-macros/src/codegen/container/enum.rs index ed2244e6..052706f6 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/enum.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/enum.rs @@ -37,7 +37,7 @@ impl Container { .map_or(false, |s| s.from.is_present()), }; - let idents: ContainerIdents = item_enum.ident.into(); + let idents = ContainerIdents::from(item_enum.ident, None); let common = CommonContainerData { original_attributes: item_enum.attrs, @@ -73,7 +73,7 @@ impl Container { .map_or(false, |s| s.from.is_present()), }; - let idents: ContainerIdents = item_enum.ident.into(); + let idents = ContainerIdents::from(item_enum.ident, None); let common = CommonContainerData { original_attributes: item_enum.attrs, diff --git a/crates/stackable-versioned-macros/src/codegen/container/mod.rs b/crates/stackable-versioned-macros/src/codegen/container/mod.rs index 893f4885..f05cef9a 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/mod.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/mod.rs @@ -1,7 +1,7 @@ use std::ops::Deref; use darling::{util::IdentString, Result}; -use proc_macro2::TokenStream; +use proc_macro2::{Span, TokenStream}; use quote::{quote, ToTokens}; use syn::{parse_quote, Attribute, Ident, ItemEnum, ItemStruct, Path, Visibility}; @@ -237,12 +237,22 @@ pub(crate) struct ContainerIdents { pub(crate) from: IdentString, } -impl From for ContainerIdents { - fn from(ident: Ident) -> Self { +impl ContainerIdents { + pub(crate) fn from(ident: Ident, kubernetes_options: Option<&KubernetesOptions>) -> Self { + let kubernetes = kubernetes_options.map_or_else( + || ident.as_cleaned_kubernetes_ident(), + |options| { + options.kind.as_ref().map_or_else( + || ident.as_cleaned_kubernetes_ident(), + |kind| IdentString::from(Ident::new(kind, Span::call_site())), + ) + }, + ); + Self { - kubernetes: ident.as_cleaned_kubernetes_ident(), from: ident.as_from_impl_ident(), original: ident.into(), + kubernetes, } } } diff --git a/crates/stackable-versioned-macros/src/codegen/container/struct.rs b/crates/stackable-versioned-macros/src/codegen/container/struct.rs index d09d0cee..2295ae9a 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/struct.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/struct.rs @@ -32,7 +32,7 @@ impl Container { } let kubernetes_options = attributes.kubernetes_arguments.map(Into::into); - let idents: ContainerIdents = item_struct.ident.into(); + let idents = ContainerIdents::from(item_struct.ident, kubernetes_options.as_ref()); // Validate K8s specific requirements // Ensure that the struct name includes the 'Spec' suffix. @@ -78,7 +78,7 @@ impl Container { } let kubernetes_options = attributes.kubernetes_arguments.map(Into::into); - let idents: ContainerIdents = item_struct.ident.into(); + let idents = ContainerIdents::from(item_struct.ident, kubernetes_options.as_ref()); // Validate K8s specific requirements // Ensure that the struct name includes the 'Spec' suffix. diff --git a/crates/stackable-versioned/CHANGELOG.md b/crates/stackable-versioned/CHANGELOG.md index 2ae594fe..bffa7bd9 100644 --- a/crates/stackable-versioned/CHANGELOG.md +++ b/crates/stackable-versioned/CHANGELOG.md @@ -24,6 +24,7 @@ All notable changes to this project will be documented in this file. ### Fixed +- Emit correct enum ident based on kube/k8s kind argument ([#920]). - Generate Kubernetes code independent of container order ([#913]). - Correctly emit Kubernetes code when macro is used on modules ([#912]). @@ -32,6 +33,7 @@ All notable changes to this project will be documented in this file. [#913]: https://github.com/stackabletech/operator-rs/pull/913 [#914]: https://github.com/stackabletech/operator-rs/pull/914 [#919]: https://github.com/stackabletech/operator-rs/pull/919 +[#920]: https://github.com/stackabletech/operator-rs/pull/920 [#922]: https://github.com/stackabletech/operator-rs/pull/922 ## [0.4.1] - 2024-10-23