Skip to content

Commit 1b610a8

Browse files
authored
refactor(stackable-versioned): Simplify attribute handling (#1053)
* refactor(stackable-versioned): Simplify attribute handling * chore(stackable-versioned): Remove superfluous visibility modifiers * feat(stackable-versioned): Add new changed() validation This throws an error if both from_name and from_type are unset which suggests this action is not needed.
1 parent 494ec0b commit 1b610a8

File tree

22 files changed

+400
-444
lines changed

22 files changed

+400
-444
lines changed

crates/stackable-versioned-macros/src/attrs/common.rs

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
use std::ops::Deref;
2+
13
use darling::{
24
Error, FromMeta, Result,
3-
util::{Flag, Override, SpannedValue},
5+
util::{Flag, Override as FlagOrOverride, SpannedValue},
46
};
57
use itertools::Itertools;
68
use k8s_version::Version;
@@ -11,15 +13,15 @@ pub trait CommonOptions {
1113

1214
#[derive(Debug, FromMeta)]
1315
#[darling(and_then = CommonRootArguments::validate)]
14-
pub(crate) struct CommonRootArguments<T>
16+
pub struct CommonRootArguments<T>
1517
where
1618
T: CommonOptions + Default,
1719
{
1820
#[darling(default)]
19-
pub(crate) options: T,
21+
pub options: T,
2022

2123
#[darling(multiple, rename = "version")]
22-
pub(crate) versions: SpannedValue<Vec<VersionArguments>>,
24+
pub versions: SpannedValue<Vec<VersionArguments>>,
2325
}
2426

2527
impl<T> CommonRootArguments<T>
@@ -78,11 +80,11 @@ where
7880
/// - `skip` option to skip generating various pieces of code.
7981
/// - `doc` option to add version-specific documentation.
8082
#[derive(Clone, Debug, FromMeta)]
81-
pub(crate) struct VersionArguments {
82-
pub(crate) deprecated: Option<Override<String>>,
83-
pub(crate) name: Version,
84-
pub(crate) skip: Option<SkipArguments>,
85-
pub(crate) doc: Option<String>,
83+
pub struct VersionArguments {
84+
pub deprecated: Option<FlagOrOverride<String>>,
85+
pub skip: Option<SkipArguments>,
86+
pub doc: Option<String>,
87+
pub name: Version,
8688
}
8789

8890
/// This struct contains supported common skip arguments.
@@ -91,8 +93,35 @@ pub(crate) struct VersionArguments {
9193
///
9294
/// - `from` flag, which skips generating [`From`] implementations when provided.
9395
#[derive(Clone, Debug, Default, FromMeta)]
94-
pub(crate) struct SkipArguments {
96+
pub struct SkipArguments {
9597
/// Whether the [`From`] implementation generation should be skipped for all versions of this
9698
/// container.
97-
pub(crate) from: Flag,
99+
pub from: Flag,
100+
}
101+
102+
/// Wraps a value to indicate whether it is original or has been overridden.
103+
#[derive(Clone, Debug)]
104+
pub enum Override<T> {
105+
Default(T),
106+
Explicit(T),
107+
}
108+
109+
impl<T> FromMeta for Override<T>
110+
where
111+
T: FromMeta,
112+
{
113+
fn from_meta(item: &syn::Meta) -> Result<Self> {
114+
FromMeta::from_meta(item).map(Override::Explicit)
115+
}
116+
}
117+
118+
impl<T> Deref for Override<T> {
119+
type Target = T;
120+
121+
fn deref(&self) -> &Self::Target {
122+
match &self {
123+
Override::Default(inner) => inner,
124+
Override::Explicit(inner) => inner,
125+
}
126+
}
98127
}
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
use darling::{FromMeta, util::Flag};
2+
use proc_macro2::TokenStream;
3+
use quote::{ToTokens, quote};
4+
use syn::{Path, parse_quote};
5+
6+
use crate::attrs::common::Override;
7+
8+
/// This struct contains supported Kubernetes arguments.
9+
///
10+
/// The arguments are passed through to the `#[kube]` attribute. More details can be found in the
11+
/// official docs: <https://docs.rs/kube/latest/kube/derive.CustomResource.html>.
12+
///
13+
/// Supported arguments are:
14+
///
15+
/// - `group`: Set the group of the CR object, usually the domain of the company.
16+
/// This argument is Required.
17+
/// - `kind`: Override the kind field of the CR object. This defaults to the struct
18+
/// name (without the 'Spec' suffix).
19+
/// - `singular`: Set the singular name of the CR object.
20+
/// - `plural`: Set the plural name of the CR object.
21+
/// - `namespaced`: Indicate that this is a namespaced scoped resource rather than a
22+
/// cluster scoped resource.
23+
/// - `crates`: Override specific crates.
24+
/// - `status`: Set the specified struct as the status subresource.
25+
/// - `shortname`: Set a shortname for the CR object. This can be specified multiple
26+
/// times.
27+
/// - `skip`: Controls skipping parts of the generation.
28+
#[derive(Clone, Debug, FromMeta)]
29+
pub struct KubernetesArguments {
30+
pub group: String,
31+
pub kind: Option<String>,
32+
pub singular: Option<String>,
33+
pub plural: Option<String>,
34+
pub namespaced: Flag,
35+
// root
36+
#[darling(default)]
37+
pub crates: KubernetesCrateArguments,
38+
pub status: Option<Path>,
39+
// derive
40+
// schema
41+
// scale
42+
// printcolumn
43+
#[darling(multiple, rename = "shortname")]
44+
pub shortnames: Vec<String>,
45+
// category
46+
// selectable
47+
// doc
48+
// annotation
49+
// label
50+
pub skip: Option<KubernetesSkipArguments>,
51+
52+
#[darling(default)]
53+
pub options: KubernetesConfigOptions,
54+
}
55+
56+
/// This struct contains supported kubernetes skip arguments.
57+
///
58+
/// Supported arguments are:
59+
///
60+
/// - `merged_crd` flag, which skips generating the `crd()` and `merged_crd()` functions are
61+
/// generated.
62+
#[derive(Clone, Debug, FromMeta)]
63+
pub struct KubernetesSkipArguments {
64+
/// Whether the `crd()` and `merged_crd()` generation should be skipped for
65+
/// this container.
66+
pub merged_crd: Flag,
67+
}
68+
69+
/// This struct contains crate overrides to be passed to `#[kube]`.
70+
#[derive(Clone, Debug, FromMeta)]
71+
pub struct KubernetesCrateArguments {
72+
#[darling(default = default_kube_core)]
73+
pub kube_core: Override<Path>,
74+
75+
#[darling(default = default_kube_client)]
76+
pub kube_client: Override<Path>,
77+
78+
#[darling(default = default_k8s_openapi)]
79+
pub k8s_openapi: Override<Path>,
80+
81+
#[darling(default = default_schemars)]
82+
pub schemars: Override<Path>,
83+
84+
#[darling(default = default_serde)]
85+
pub serde: Override<Path>,
86+
87+
#[darling(default = default_serde_json)]
88+
pub serde_json: Override<Path>,
89+
90+
#[darling(default = default_versioned)]
91+
pub versioned: Override<Path>,
92+
}
93+
94+
impl Default for KubernetesCrateArguments {
95+
fn default() -> Self {
96+
Self {
97+
kube_core: default_kube_core(),
98+
kube_client: default_kube_client(),
99+
k8s_openapi: default_k8s_openapi(),
100+
schemars: default_schemars(),
101+
serde: default_serde(),
102+
serde_json: default_serde_json(),
103+
versioned: default_versioned(),
104+
}
105+
}
106+
}
107+
108+
fn default_kube_core() -> Override<Path> {
109+
Override::Default(parse_quote! { ::kube::core })
110+
}
111+
112+
fn default_kube_client() -> Override<Path> {
113+
Override::Default(parse_quote! { ::kube::client })
114+
}
115+
116+
fn default_k8s_openapi() -> Override<Path> {
117+
Override::Default(parse_quote! { ::k8s_openapi })
118+
}
119+
120+
fn default_schemars() -> Override<Path> {
121+
Override::Default(parse_quote! { ::schemars })
122+
}
123+
124+
fn default_serde() -> Override<Path> {
125+
Override::Default(parse_quote! { ::serde })
126+
}
127+
128+
fn default_serde_json() -> Override<Path> {
129+
Override::Default(parse_quote! { ::serde_json })
130+
}
131+
132+
fn default_versioned() -> Override<Path> {
133+
Override::Default(parse_quote! { ::stackable_versioned })
134+
}
135+
136+
impl ToTokens for KubernetesCrateArguments {
137+
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
138+
let mut crate_overrides = TokenStream::new();
139+
140+
let KubernetesCrateArguments {
141+
kube_client: _,
142+
k8s_openapi,
143+
serde_json,
144+
kube_core,
145+
schemars,
146+
serde,
147+
..
148+
} = self;
149+
150+
if let Override::Explicit(k8s_openapi) = k8s_openapi {
151+
crate_overrides.extend(quote! { k8s_openapi = #k8s_openapi, });
152+
}
153+
154+
if let Override::Explicit(serde_json) = serde_json {
155+
crate_overrides.extend(quote! { serde_json = #serde_json, });
156+
}
157+
158+
if let Override::Explicit(kube_core) = kube_core {
159+
crate_overrides.extend(quote! { kube_core = #kube_core, });
160+
}
161+
162+
if let Override::Explicit(schemars) = schemars {
163+
crate_overrides.extend(quote! { schemars = #schemars, });
164+
}
165+
166+
if let Override::Explicit(serde) = serde {
167+
crate_overrides.extend(quote! { serde = #serde, });
168+
}
169+
170+
if !crate_overrides.is_empty() {
171+
tokens.extend(quote! { , crates(#crate_overrides) });
172+
}
173+
}
174+
}
175+
176+
#[derive(Clone, Default, Debug, FromMeta)]
177+
pub struct KubernetesConfigOptions {
178+
pub experimental_conversion_tracking: Flag,
179+
}

crates/stackable-versioned-macros/src/attrs/container.rs renamed to crates/stackable-versioned-macros/src/attrs/container/mod.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,19 @@ use darling::{Error, FromAttributes, FromMeta, Result, util::Flag};
22

33
use crate::attrs::{
44
common::{CommonOptions, CommonRootArguments, SkipArguments},
5-
k8s::KubernetesArguments,
5+
container::k8s::KubernetesArguments,
66
};
77

8+
pub mod k8s;
9+
810
#[derive(Debug, FromMeta)]
911
#[darling(and_then = StandaloneContainerAttributes::validate)]
10-
pub(crate) struct StandaloneContainerAttributes {
12+
pub struct StandaloneContainerAttributes {
1113
#[darling(rename = "k8s")]
12-
pub(crate) kubernetes_arguments: Option<KubernetesArguments>,
14+
pub kubernetes_arguments: Option<KubernetesArguments>,
1315

1416
#[darling(flatten)]
15-
pub(crate) common: CommonRootArguments<StandaloneContainerOptions>,
17+
pub common: CommonRootArguments<StandaloneContainerOptions>,
1618
}
1719

1820
impl StandaloneContainerAttributes {
@@ -28,9 +30,9 @@ impl StandaloneContainerAttributes {
2830
}
2931

3032
#[derive(Debug, FromMeta, Default)]
31-
pub(crate) struct StandaloneContainerOptions {
32-
pub(crate) allow_unsorted: Flag,
33-
pub(crate) skip: Option<SkipArguments>,
33+
pub struct StandaloneContainerOptions {
34+
pub allow_unsorted: Flag,
35+
pub skip: Option<SkipArguments>,
3436
}
3537

3638
impl CommonOptions for StandaloneContainerOptions {
@@ -44,12 +46,12 @@ impl CommonOptions for StandaloneContainerOptions {
4446
attributes(versioned),
4547
and_then = NestedContainerAttributes::validate
4648
)]
47-
pub(crate) struct NestedContainerAttributes {
49+
pub struct NestedContainerAttributes {
4850
#[darling(rename = "k8s")]
49-
pub(crate) kubernetes_arguments: Option<KubernetesArguments>,
51+
pub kubernetes_arguments: Option<KubernetesArguments>,
5052

5153
#[darling(default)]
52-
pub(crate) options: NestedContainerOptionArguments,
54+
pub options: NestedContainerOptionArguments,
5355
}
5456

5557
impl NestedContainerAttributes {
@@ -65,6 +67,6 @@ impl NestedContainerAttributes {
6567
}
6668

6769
#[derive(Debug, Default, FromMeta)]
68-
pub(crate) struct NestedContainerOptionArguments {
69-
pub(crate) skip: Option<SkipArguments>,
70+
pub struct NestedContainerOptionArguments {
71+
pub skip: Option<SkipArguments>,
7072
}

crates/stackable-versioned-macros/src/attrs/item/field.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,20 @@ use crate::{attrs::item::CommonItemAttributes, codegen::VersionDefinition, utils
2222
forward_attrs,
2323
and_then = FieldAttributes::validate
2424
)]
25-
pub(crate) struct FieldAttributes {
25+
pub struct FieldAttributes {
2626
#[darling(flatten)]
27-
pub(crate) common: CommonItemAttributes,
27+
pub common: CommonItemAttributes,
2828

2929
// The ident (automatically extracted by darling) cannot be moved into the
3030
// shared item attributes because for struct fields, the type is
3131
// `Option<Ident>`, while for enum variants, the type is `Ident`.
32-
pub(crate) ident: Option<Ident>,
32+
pub ident: Option<Ident>,
3333

3434
// This must be named `attrs` for darling to populate it accordingly, and
3535
// cannot live in common because Vec<Attribute> is not implemented for
3636
// FromMeta.
3737
/// The original attributes for the field.
38-
pub(crate) attrs: Vec<Attribute>,
38+
pub attrs: Vec<Attribute>,
3939
}
4040

4141
impl FieldAttributes {
@@ -56,7 +56,7 @@ impl FieldAttributes {
5656
Ok(self)
5757
}
5858

59-
pub(crate) fn validate_versions(&self, versions: &[VersionDefinition]) -> Result<()> {
59+
pub fn validate_versions(&self, versions: &[VersionDefinition]) -> Result<()> {
6060
self.common.validate_versions(versions)
6161
}
6262
}

0 commit comments

Comments
 (0)