diff --git a/crates/stackable-versioned-macros/fixtures/inputs/k8s/module.rs b/crates/stackable-versioned-macros/fixtures/inputs/k8s/module.rs index 71186abf4..d37a5e5b0 100644 --- a/crates/stackable-versioned-macros/fixtures/inputs/k8s/module.rs +++ b/crates/stackable-versioned-macros/fixtures/inputs/k8s/module.rs @@ -5,6 +5,12 @@ )] // --- pub(crate) mod versioned { + // This struct is placed before the FooSpec one to ensure that the Kubernetes code generation + // works no matter the order. + pub struct Baz { + boom: Option, + } + #[versioned(k8s(group = "foo.example.org", plural = "foos", namespaced))] pub struct FooSpec { bar: usize, @@ -21,7 +27,8 @@ pub(crate) mod versioned { baz: String, } - pub struct Baz { - boom: Option, + pub enum Boom { + Big, + Shaq, } } diff --git a/crates/stackable-versioned-macros/fixtures/inputs/k8s/module_preserve.rs b/crates/stackable-versioned-macros/fixtures/inputs/k8s/module_preserve.rs index 3f0401365..58992b58c 100644 --- a/crates/stackable-versioned-macros/fixtures/inputs/k8s/module_preserve.rs +++ b/crates/stackable-versioned-macros/fixtures/inputs/k8s/module_preserve.rs @@ -6,6 +6,12 @@ )] // --- pub(crate) mod versioned { + // This struct is placed before the FooSpec one to ensure that the Kubernetes code generation + // works no matter the order. + pub struct Baz { + boom: Option, + } + #[versioned(k8s(group = "foo.example.org", plural = "foos", namespaced))] pub struct FooSpec { bar: usize, @@ -22,7 +28,8 @@ pub(crate) mod versioned { baz: String, } - pub struct Baz { - boom: Option, + pub enum Boom { + Big, + Shaq, } } diff --git a/crates/stackable-versioned-macros/fixtures/snapshots/stackable_versioned_macros__test__k8s_snapshots@module.rs.snap b/crates/stackable-versioned-macros/fixtures/snapshots/stackable_versioned_macros__test__k8s_snapshots@module.rs.snap index 48882f67d..c357340de 100644 --- a/crates/stackable-versioned-macros/fixtures/snapshots/stackable_versioned_macros__test__k8s_snapshots@module.rs.snap +++ b/crates/stackable-versioned-macros/fixtures/snapshots/stackable_versioned_macros__test__k8s_snapshots@module.rs.snap @@ -6,6 +6,9 @@ input_file: crates/stackable-versioned-macros/fixtures/inputs/k8s/module.rs #[automatically_derived] pub(crate) mod v1alpha1 { use super::*; + pub struct Baz { + pub boom: Option, + } #[derive(::kube::CustomResource)] #[kube( group = "foo.example.org", @@ -28,8 +31,15 @@ pub(crate) mod v1alpha1 { pub struct BarSpec { pub baz: String, } - pub struct Baz { - pub boom: Option, + pub enum Boom { + Big, + Shaq, + } +} +#[automatically_derived] +impl ::std::convert::From for v1::Baz { + fn from(__sv_baz: v1alpha1::Baz) -> Self { + Self { boom: __sv_baz.boom } } } #[automatically_derived] @@ -49,14 +59,20 @@ impl ::std::convert::From for v1::BarSpec { } } #[automatically_derived] -impl ::std::convert::From for v1::Baz { - fn from(__sv_baz: v1alpha1::Baz) -> Self { - Self { boom: __sv_baz.boom } +impl ::std::convert::From for v1::Boom { + fn from(__sv_boom: v1alpha1::Boom) -> Self { + match __sv_boom { + v1alpha1::Boom::Big => v1::Boom::Big, + v1alpha1::Boom::Shaq => v1::Boom::Shaq, + } } } #[automatically_derived] pub(crate) mod v1 { use super::*; + pub struct Baz { + pub boom: Option, + } #[derive(::kube::CustomResource)] #[kube( group = "foo.example.org", @@ -75,8 +91,15 @@ pub(crate) mod v1 { pub struct BarSpec { pub baz: String, } - pub struct Baz { - pub boom: Option, + pub enum Boom { + Big, + Shaq, + } +} +#[automatically_derived] +impl ::std::convert::From for v2alpha1::Baz { + fn from(__sv_baz: v1::Baz) -> Self { + Self { boom: __sv_baz.boom } } } #[automatically_derived] @@ -97,14 +120,20 @@ impl ::std::convert::From for v2alpha1::BarSpec { } } #[automatically_derived] -impl ::std::convert::From for v2alpha1::Baz { - fn from(__sv_baz: v1::Baz) -> Self { - Self { boom: __sv_baz.boom } +impl ::std::convert::From for v2alpha1::Boom { + fn from(__sv_boom: v1::Boom) -> Self { + match __sv_boom { + v1::Boom::Big => v2alpha1::Boom::Big, + v1::Boom::Shaq => v2alpha1::Boom::Shaq, + } } } #[automatically_derived] pub(crate) mod v2alpha1 { use super::*; + pub struct Baz { + pub boom: Option, + } #[derive(::kube::CustomResource)] #[kube( group = "foo.example.org", @@ -129,14 +158,16 @@ pub(crate) mod v2alpha1 { pub struct BarSpec { pub baz: String, } - pub struct Baz { - pub boom: Option, + pub enum Boom { + Big, + Shaq, } } #[automatically_derived] pub enum Foo { V1Alpha1, - V1Alpha1, + V1, + V2Alpha1, } #[automatically_derived] impl ::std::fmt::Display for Foo { @@ -146,7 +177,8 @@ impl ::std::fmt::Display for Foo { ) -> ::std::result::Result<(), ::std::fmt::Error> { match self { Self::V1Alpha1 => f.write_str("v1alpha1"), - Self::V1Alpha1 => f.write_str("v1alpha1"), + Self::V1 => f.write_str("v1"), + Self::V2Alpha1 => f.write_str("v2alpha1"), } } } @@ -161,8 +193,9 @@ impl Foo { > { ::kube::core::crd::merge_crds( vec![ - < v1alpha1::Foo as ::kube::CustomResourceExt > ::crd(), < v1alpha1::Bar - as ::kube::CustomResourceExt > ::crd() + < v1alpha1::Foo as ::kube::CustomResourceExt > ::crd(), < v1::Foo as + ::kube::CustomResourceExt > ::crd(), < v2alpha1::Foo as + ::kube::CustomResourceExt > ::crd() ], &stored_apiversion.to_string(), ) @@ -215,8 +248,9 @@ impl Foo { } #[automatically_derived] pub enum Bar { + V1Alpha1, V1, - V1, + V2Alpha1, } #[automatically_derived] impl ::std::fmt::Display for Bar { @@ -225,8 +259,9 @@ impl ::std::fmt::Display for Bar { f: &mut ::std::fmt::Formatter<'_>, ) -> ::std::result::Result<(), ::std::fmt::Error> { match self { + Self::V1Alpha1 => f.write_str("v1alpha1"), Self::V1 => f.write_str("v1"), - Self::V1 => f.write_str("v1"), + Self::V2Alpha1 => f.write_str("v2alpha1"), } } } @@ -241,7 +276,8 @@ impl Bar { > { ::kube::core::crd::merge_crds( vec![ - < v1::Foo as ::kube::CustomResourceExt > ::crd(), < v1::Bar as + < v1alpha1::Bar as ::kube::CustomResourceExt > ::crd(), < v1::Bar as + ::kube::CustomResourceExt > ::crd(), < v2alpha1::Bar as ::kube::CustomResourceExt > ::crd() ], &stored_apiversion.to_string(), @@ -293,83 +329,3 @@ impl Bar { }) } } -#[automatically_derived] -pub enum Baz { - V2Alpha1, - V2Alpha1, -} -#[automatically_derived] -impl ::std::fmt::Display for Baz { - fn fmt( - &self, - f: &mut ::std::fmt::Formatter<'_>, - ) -> ::std::result::Result<(), ::std::fmt::Error> { - match self { - Self::V2Alpha1 => f.write_str("v2alpha1"), - Self::V2Alpha1 => f.write_str("v2alpha1"), - } - } -} -#[automatically_derived] -impl Baz { - /// 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![ - < v2alpha1::Foo as ::kube::CustomResourceExt > ::crd(), < v2alpha1::Bar - as ::kube::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/fixtures/snapshots/stackable_versioned_macros__test__k8s_snapshots@module_preserve.rs.snap b/crates/stackable-versioned-macros/fixtures/snapshots/stackable_versioned_macros__test__k8s_snapshots@module_preserve.rs.snap index 57659da87..a56f6ce55 100644 --- a/crates/stackable-versioned-macros/fixtures/snapshots/stackable_versioned_macros__test__k8s_snapshots@module_preserve.rs.snap +++ b/crates/stackable-versioned-macros/fixtures/snapshots/stackable_versioned_macros__test__k8s_snapshots@module_preserve.rs.snap @@ -7,6 +7,9 @@ input_file: crates/stackable-versioned-macros/fixtures/inputs/k8s/module_preserv pub(crate) mod versioned { pub mod v1alpha1 { use super::*; + pub struct Baz { + pub boom: Option, + } #[derive(::kube::CustomResource)] #[kube( group = "foo.example.org", @@ -29,8 +32,14 @@ pub(crate) mod versioned { pub struct BarSpec { pub baz: String, } - pub struct Baz { - pub boom: Option, + pub enum Boom { + Big, + Shaq, + } + } + impl ::std::convert::From for v1::Baz { + fn from(__sv_baz: v1alpha1::Baz) -> Self { + Self { boom: __sv_baz.boom } } } impl ::std::convert::From for v1::FooSpec { @@ -47,13 +56,19 @@ pub(crate) mod versioned { Self { baz: __sv_barspec.baz } } } - impl ::std::convert::From for v1::Baz { - fn from(__sv_baz: v1alpha1::Baz) -> Self { - Self { boom: __sv_baz.boom } + impl ::std::convert::From for v1::Boom { + fn from(__sv_boom: v1alpha1::Boom) -> Self { + match __sv_boom { + v1alpha1::Boom::Big => v1::Boom::Big, + v1alpha1::Boom::Shaq => v1::Boom::Shaq, + } } } pub mod v1 { use super::*; + pub struct Baz { + pub boom: Option, + } #[derive(::kube::CustomResource)] #[kube( group = "foo.example.org", @@ -72,8 +87,14 @@ pub(crate) mod versioned { pub struct BarSpec { pub baz: String, } - pub struct Baz { - pub boom: Option, + pub enum Boom { + Big, + Shaq, + } + } + impl ::std::convert::From for v2alpha1::Baz { + fn from(__sv_baz: v1::Baz) -> Self { + Self { boom: __sv_baz.boom } } } #[allow(deprecated)] @@ -91,13 +112,19 @@ pub(crate) mod versioned { Self { baz: __sv_barspec.baz } } } - impl ::std::convert::From for v2alpha1::Baz { - fn from(__sv_baz: v1::Baz) -> Self { - Self { boom: __sv_baz.boom } + impl ::std::convert::From for v2alpha1::Boom { + fn from(__sv_boom: v1::Boom) -> Self { + match __sv_boom { + v1::Boom::Big => v2alpha1::Boom::Big, + v1::Boom::Shaq => v2alpha1::Boom::Shaq, + } } } pub mod v2alpha1 { use super::*; + pub struct Baz { + pub boom: Option, + } #[derive(::kube::CustomResource)] #[kube( group = "foo.example.org", @@ -122,13 +149,15 @@ pub(crate) mod versioned { pub struct BarSpec { pub baz: String, } - pub struct Baz { - pub boom: Option, + pub enum Boom { + Big, + Shaq, } } pub enum Foo { V1Alpha1, - V1Alpha1, + V1, + V2Alpha1, } impl ::std::fmt::Display for Foo { fn fmt( @@ -137,7 +166,8 @@ pub(crate) mod versioned { ) -> ::std::result::Result<(), ::std::fmt::Error> { match self { Self::V1Alpha1 => f.write_str("v1alpha1"), - Self::V1Alpha1 => f.write_str("v1alpha1"), + Self::V1 => f.write_str("v1"), + Self::V2Alpha1 => f.write_str("v2alpha1"), } } } @@ -151,8 +181,9 @@ pub(crate) mod versioned { > { ::kube::core::crd::merge_crds( vec![ - < v1alpha1::Foo as ::kube::CustomResourceExt > ::crd(), < - v1alpha1::Bar as ::kube::CustomResourceExt > ::crd() + < v1alpha1::Foo as ::kube::CustomResourceExt > ::crd(), < v1::Foo as + ::kube::CustomResourceExt > ::crd(), < v2alpha1::Foo as + ::kube::CustomResourceExt > ::crd() ], &stored_apiversion.to_string(), ) @@ -204,8 +235,9 @@ pub(crate) mod versioned { } } pub enum Bar { + V1Alpha1, V1, - V1, + V2Alpha1, } impl ::std::fmt::Display for Bar { fn fmt( @@ -213,8 +245,9 @@ pub(crate) mod versioned { f: &mut ::std::fmt::Formatter<'_>, ) -> ::std::result::Result<(), ::std::fmt::Error> { match self { + Self::V1Alpha1 => f.write_str("v1alpha1"), Self::V1 => f.write_str("v1"), - Self::V1 => f.write_str("v1"), + Self::V2Alpha1 => f.write_str("v2alpha1"), } } } @@ -228,7 +261,8 @@ pub(crate) mod versioned { > { ::kube::core::crd::merge_crds( vec![ - < v1::Foo as ::kube::CustomResourceExt > ::crd(), < v1::Bar as + < v1alpha1::Bar as ::kube::CustomResourceExt > ::crd(), < v1::Bar as + ::kube::CustomResourceExt > ::crd(), < v2alpha1::Bar as ::kube::CustomResourceExt > ::crd() ], &stored_apiversion.to_string(), @@ -280,81 +314,4 @@ pub(crate) mod versioned { }) } } - pub enum Baz { - V2Alpha1, - V2Alpha1, - } - impl ::std::fmt::Display for Baz { - fn fmt( - &self, - f: &mut ::std::fmt::Formatter<'_>, - ) -> ::std::result::Result<(), ::std::fmt::Error> { - match self { - Self::V2Alpha1 => f.write_str("v2alpha1"), - Self::V2Alpha1 => f.write_str("v2alpha1"), - } - } - } - impl Baz { - /// 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![ - < v2alpha1::Foo as ::kube::CustomResourceExt > ::crd(), < - v2alpha1::Bar as ::kube::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/mod.rs b/crates/stackable-versioned-macros/src/codegen/container/mod.rs index 45f9ad153..0bdaa3309 100644 --- a/crates/stackable-versioned-macros/src/codegen/container/mod.rs +++ b/crates/stackable-versioned-macros/src/codegen/container/mod.rs @@ -100,6 +100,13 @@ impl Container { Container::Enum(_) => None, } } + + pub(crate) fn get_original_ident(&self) -> &Ident { + match &self { + Container::Struct(s) => s.common.idents.original.as_ident(), + Container::Enum(e) => e.common.idents.original.as_ident(), + } + } } /// A versioned standalone container. diff --git a/crates/stackable-versioned-macros/src/codegen/module.rs b/crates/stackable-versioned-macros/src/codegen/module.rs index 9069dc8d8..709a69890 100644 --- a/crates/stackable-versioned-macros/src/codegen/module.rs +++ b/crates/stackable-versioned-macros/src/codegen/module.rs @@ -1,4 +1,4 @@ -use std::ops::Not; +use std::{collections::HashMap, ops::Not}; use darling::util::IdentString; use proc_macro2::TokenStream; @@ -7,6 +7,8 @@ use syn::{token::Pub, Ident, Visibility}; use crate::codegen::{container::Container, VersionDefinition}; +pub(crate) type KubernetesItems = (Vec, Vec, Vec); + pub(crate) struct ModuleInput { pub(crate) vis: Visibility, pub(crate) ident: Ident, @@ -63,15 +65,10 @@ impl Module { let mut kubernetes_tokens = TokenStream::new(); let mut tokens = TokenStream::new(); - let mut kubernetes_container_items = Vec::new(); - + let mut kubernetes_container_items: HashMap = HashMap::new(); let mut versions = self.versions.iter().peekable(); while let Some(version) = versions.next() { - let mut kubernetes_merge_crds_fn_calls = Vec::new(); - let mut kubernetes_enum_variant_idents = Vec::new(); - let mut kubernetes_enum_variant_strings = Vec::new(); - let mut container_definitions = TokenStream::new(); let mut from_impls = TokenStream::new(); @@ -91,9 +88,13 @@ impl Module { if let Some((enum_variant_ident, enum_variant_string, fn_call)) = container.generate_kubernetes_item(version) { - kubernetes_merge_crds_fn_calls.push(fn_call); - kubernetes_enum_variant_idents.push(enum_variant_ident); - kubernetes_enum_variant_strings.push(enum_variant_string); + let entry = kubernetes_container_items + .entry(container.get_original_ident().clone()) + .or_default(); + + entry.0.push(fn_call); + entry.1.push(enum_variant_ident); + entry.2.push(enum_variant_string); } } @@ -121,29 +122,24 @@ impl Module { #from_impls }); - - kubernetes_container_items.push(( - kubernetes_merge_crds_fn_calls, - kubernetes_enum_variant_idents, - kubernetes_enum_variant_strings, - )); } // Generate the final Kubernetes specific code for each container (which uses Kubernetes // specific features) which is appended to the end of container definitions. - for (index, container) in self.containers.iter().enumerate() { - let ( + for container in &self.containers { + if let Some(( kubernetes_merge_crds_fn_calls, kubernetes_enum_variant_idents, kubernetes_enum_variant_strings, - ) = kubernetes_container_items.get(index).unwrap(); - - kubernetes_tokens.extend(container.generate_kubernetes_merge_crds( - kubernetes_enum_variant_idents, - kubernetes_enum_variant_strings, - kubernetes_merge_crds_fn_calls, - self.preserve_module, - )); + )) = kubernetes_container_items.get(container.get_original_ident()) + { + kubernetes_tokens.extend(container.generate_kubernetes_merge_crds( + kubernetes_enum_variant_idents, + kubernetes_enum_variant_strings, + kubernetes_merge_crds_fn_calls, + self.preserve_module, + )); + } } if self.preserve_module { diff --git a/crates/stackable-versioned/CHANGELOG.md b/crates/stackable-versioned/CHANGELOG.md index 475ee82cc..e83c31fe2 100644 --- a/crates/stackable-versioned/CHANGELOG.md +++ b/crates/stackable-versioned/CHANGELOG.md @@ -15,10 +15,12 @@ All notable changes to this project will be documented in this file. ### Fixed +- Generate Kubernetes code independent of container order ([#913]). - Correctly emit Kubernetes code when macro is used on modules ([#912]). [#891]: https://github.com/stackabletech/operator-rs/pull/891 [#912]: https://github.com/stackabletech/operator-rs/pull/912 +[#913]: https://github.com/stackabletech/operator-rs/pull/913 ## [0.4.1] - 2024-10-23