Skip to content

Commit bc7da2b

Browse files
committed
chore(stackable-versioned): Cleanup, move and improve conversion code
1 parent 86a1c66 commit bc7da2b

File tree

11 files changed

+750
-443
lines changed

11 files changed

+750
-443
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/stackable-versioned-macros/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ k8s-version = { path = "../k8s-version", features = ["darling"] }
3333

3434
convert_case.workspace = true
3535
darling.workspace = true
36+
indoc.workspace = true
3637
itertools.workspace = true
3738
k8s-openapi = { workspace = true, optional = true }
3839
kube = { workspace = true, optional = true }

crates/stackable-versioned-macros/src/attrs/container/k8s.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,4 +176,5 @@ impl ToTokens for KubernetesCrateArguments {
176176
#[derive(Clone, Default, Debug, FromMeta)]
177177
pub struct KubernetesConfigOptions {
178178
pub experimental_conversion_tracking: Flag,
179+
pub enable_tracing: Flag,
179180
}

crates/stackable-versioned-macros/src/codegen/container/enum.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,11 @@ impl Enum {
141141
// advise against using generic types, but if you have to, avoid removing it in
142142
// later versions.
143143
let (impl_generics, type_generics, where_clause) = self.generics.split_for_impl();
144+
let from_enum_ident = &self.common.idents.parameter;
144145
let enum_ident = &self.common.idents.original;
145-
let from_enum_ident = &self.common.idents.from;
146146

147-
let for_module_ident = &next_version.ident;
148-
let from_module_ident = &version.ident;
147+
let for_module_ident = &next_version.idents.module;
148+
let from_module_ident = &version.idents.module;
149149

150150
let variants: TokenStream = self
151151
.variants
@@ -201,11 +201,11 @@ impl Enum {
201201
match next_version {
202202
Some(next_version) => {
203203
let (impl_generics, type_generics, where_clause) = self.generics.split_for_impl();
204+
let from_enum_ident = &self.common.idents.parameter;
204205
let enum_ident = &self.common.idents.original;
205-
let from_enum_ident = &self.common.idents.from;
206206

207-
let for_module_ident = &version.ident;
208-
let from_module_ident = &next_version.ident;
207+
let from_module_ident = &next_version.idents.module;
208+
let for_module_ident = &version.idents.module;
209209

210210
let variants: TokenStream = self
211211
.variants

crates/stackable-versioned-macros/src/codegen/container/mod.rs

Lines changed: 56 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
use darling::{Result, util::IdentString};
22
use proc_macro2::{Span, TokenStream};
3-
use quote::quote;
3+
use quote::{format_ident, quote};
44
use syn::{Attribute, Ident, ItemEnum, ItemStruct, Visibility};
55

6-
use super::flux_converter::{generate_kubernetes_conversion, generate_kubernetes_conversion_tests};
76
use crate::{
87
attrs::container::{StandaloneContainerAttributes, k8s::KubernetesArguments},
98
codegen::{
10-
VersionDefinition,
9+
KubernetesTokens, VersionDefinition,
1110
container::{r#enum::Enum, r#struct::Struct},
1211
},
1312
utils::ContainerIdentExt,
@@ -81,84 +80,25 @@ impl Container {
8180
}
8281
}
8382

84-
/// Generates Kubernetes specific code snippets.
85-
///
86-
/// This function returns three values:
87-
///
88-
/// - an enum variant ident,
89-
/// - an enum variant display string,
90-
/// - and a `CustomResource::crd()` call
91-
///
92-
/// This function only returns `Some` if it is a struct. Enums cannot be used to define
93-
/// Kubernetes custom resources.
94-
pub fn generate_kubernetes_item(
95-
&self,
96-
version: &VersionDefinition,
97-
) -> Option<(IdentString, String, TokenStream)> {
98-
match self {
99-
Container::Struct(s) => s.generate_kubernetes_item(version),
100-
Container::Enum(_) => None,
101-
}
102-
}
103-
104-
/// Generates Kubernetes specific code to merge two CRDs or convert between different versions.
105-
///
106-
/// This function only returns `Some` if it is a struct. Enums cannot be used to define
107-
/// Kubernetes custom resources.
10883
pub fn generate_kubernetes_code(
10984
&self,
110-
enum_variant_idents: &[IdentString],
111-
enum_variant_strings: &[String],
112-
fn_calls: &[TokenStream],
85+
versions: &[VersionDefinition],
86+
tokens: &KubernetesTokens,
11387
vis: &Visibility,
11488
is_nested: bool,
11589
) -> Option<TokenStream> {
116-
let Container::Struct(s) = self else {
117-
return None;
118-
};
119-
let kubernetes_arguments = s.common.options.kubernetes_arguments.as_ref()?;
120-
121-
let mut tokens = TokenStream::new();
122-
123-
if !kubernetes_arguments
124-
.skip
125-
.as_ref()
126-
.is_some_and(|s| s.merged_crd.is_present())
127-
{
128-
tokens.extend(s.generate_kubernetes_merge_crds(
129-
enum_variant_idents,
130-
enum_variant_strings,
131-
fn_calls,
132-
vis,
133-
is_nested,
134-
));
135-
136-
tokens.extend(s.generate_from_functions(
137-
enum_variant_idents,
138-
enum_variant_strings,
139-
is_nested,
140-
));
141-
tokens.extend(generate_kubernetes_conversion(
142-
&s.common.idents.kubernetes,
143-
&s.common.idents.original,
144-
enum_variant_idents,
145-
enum_variant_strings,
146-
kubernetes_arguments,
147-
));
148-
tokens.extend(generate_kubernetes_conversion_tests(
149-
&s.common.idents.kubernetes,
150-
&s.common.idents.original,
151-
enum_variant_strings,
152-
kubernetes_arguments,
153-
));
90+
match self {
91+
Container::Struct(s) => s.generate_kubernetes_code(versions, tokens, vis, is_nested),
92+
Container::Enum(_) => None,
15493
}
155-
156-
Some(tokens)
15794
}
15895

159-
pub fn generate_kubernetes_status_struct(&self) -> Option<TokenStream> {
96+
pub fn generate_kubernetes_version_items(
97+
&self,
98+
version: &VersionDefinition,
99+
) -> Option<(TokenStream, IdentString, TokenStream, String)> {
160100
match self {
161-
Container::Struct(s) => s.generate_kubernetes_status_struct(),
101+
Container::Struct(s) => s.generate_kubernetes_version_items(version),
162102
Container::Enum(_) => None,
163103
}
164104
}
@@ -222,16 +162,14 @@ impl StandaloneContainer {
222162
pub fn generate_tokens(&self) -> TokenStream {
223163
let vis = &self.vis;
224164

165+
let mut kubernetes_tokens = KubernetesTokens::default();
225166
let mut tokens = TokenStream::new();
226167

227-
let mut kubernetes_merge_crds_fn_calls = Vec::new();
228-
let mut kubernetes_enum_variant_idents = Vec::new();
229-
let mut kubernetes_enum_variant_strings = Vec::new();
230-
231168
let mut versions = self.versions.iter().peekable();
232169

233170
while let Some(version) = versions.next() {
234171
let container_definition = self.container.generate_definition(version);
172+
let module_ident = &version.idents.module;
235173

236174
// NOTE (@Techassi): Using '.copied()' here does not copy or clone the data, but instead
237175
// removes one level of indirection of the double reference '&&'.
@@ -253,22 +191,16 @@ impl StandaloneContainer {
253191
.as_ref()
254192
.map(|note| quote! { #[deprecated = #note] });
255193

256-
// Generate Kubernetes specific code which is placed outside of the container
257-
// definition.
258-
if let Some((enum_variant_ident, enum_variant_string, fn_call)) =
259-
self.container.generate_kubernetes_item(version)
260-
{
261-
kubernetes_merge_crds_fn_calls.push(fn_call);
262-
kubernetes_enum_variant_idents.push(enum_variant_ident);
263-
kubernetes_enum_variant_strings.push(enum_variant_string);
194+
// Generate Kubernetes specific code (for a particular version) which is placed outside
195+
// of the container definition.
196+
if let Some(items) = self.container.generate_kubernetes_version_items(version) {
197+
kubernetes_tokens.push(items);
264198
}
265199

266-
let version_ident = &version.ident;
267-
268200
tokens.extend(quote! {
269201
#[automatically_derived]
270202
#deprecated_attribute
271-
#vis mod #version_ident {
203+
#vis mod #module_ident {
272204
use super::*;
273205
#container_definition
274206
}
@@ -278,49 +210,68 @@ impl StandaloneContainer {
278210
});
279211
}
280212

213+
// Finally add tokens outside of the container definitions
281214
tokens.extend(self.container.generate_kubernetes_code(
282-
&kubernetes_enum_variant_idents,
283-
&kubernetes_enum_variant_strings,
284-
&kubernetes_merge_crds_fn_calls,
215+
&self.versions,
216+
&kubernetes_tokens,
285217
vis,
286218
false,
287219
));
288220

289-
tokens.extend(self.container.generate_kubernetes_status_struct());
290-
291221
tokens
292222
}
293223
}
294224

295225
/// A collection of container idents used for different purposes.
296226
#[derive(Debug)]
297227
pub struct ContainerIdents {
298-
/// The ident used in the context of Kubernetes specific code. This ident
299-
/// removes the 'Spec' suffix present in the definition container.
228+
/// This ident removes the 'Spec' suffix present in the definition container.
229+
/// This ident is only used in the context of Kubernetes specific code.
300230
pub kubernetes: IdentString,
301231

232+
/// This ident uses the base Kubernetes ident to construct an appropriate ident
233+
/// for auto-generated status structs. This ident is only used in the context of
234+
/// Kubernetes specific code.
235+
pub kubernetes_status: IdentString,
236+
237+
/// This ident uses the base Kubernetes ident to construct an appropriate ident
238+
/// for auto-generated version enums. This enum is used to select the stored
239+
/// api version when merging CRDs. This ident is only used in the context of
240+
/// Kubernetes specific code.
241+
pub kubernetes_version: IdentString,
242+
243+
// TODO (@Techassi): Add comment
244+
pub kubernetes_parameter: IdentString,
245+
302246
/// The original ident, or name, of the versioned container.
303247
pub original: IdentString,
304248

305-
/// The ident used in the [`From`] impl.
306-
pub from: IdentString,
249+
/// The ident used as a parameter.
250+
pub parameter: IdentString,
307251
}
308252

309253
impl ContainerIdents {
310254
pub fn from(ident: Ident, kubernetes_arguments: Option<&KubernetesArguments>) -> Self {
311-
let kubernetes = kubernetes_arguments.map_or_else(
312-
|| ident.as_cleaned_kubernetes_ident(),
313-
|options| {
314-
options.kind.as_ref().map_or_else(
315-
|| ident.as_cleaned_kubernetes_ident(),
316-
|kind| IdentString::from(Ident::new(kind, Span::call_site())),
317-
)
255+
let kubernetes = match kubernetes_arguments {
256+
Some(args) => match &args.kind {
257+
Some(kind) => IdentString::from(Ident::new(kind, Span::call_site())),
258+
None => ident.as_cleaned_kubernetes_ident(),
318259
},
319-
);
260+
None => ident.as_cleaned_kubernetes_ident(),
261+
};
262+
263+
let kubernetes_status =
264+
IdentString::from(format_ident!("{kubernetes}StatusWithChangedValues"));
265+
266+
let kubernetes_version = IdentString::from(format_ident!("{kubernetes}Version"));
267+
let kubernetes_parameter = kubernetes.as_parameter_ident();
320268

321269
Self {
322-
from: ident.as_from_impl_ident(),
270+
parameter: ident.as_parameter_ident(),
323271
original: ident.into(),
272+
kubernetes_parameter,
273+
kubernetes_version,
274+
kubernetes_status,
324275
kubernetes,
325276
}
326277
}

0 commit comments

Comments
 (0)