Skip to content

Commit a66da25

Browse files
authored
feat(versioned): Add support for the printcolumn argument (#1318)
* feat(versioned): Add support for the `printcolumn` argument The printcolumn arguments are passed through unchanged to the generated `#[kube(...)]` attribute, so kube-derive does the parsing and validation. This keeps us in sync with upstream without mirroring its PrintColumn struct, and also supports the legacy JSON string syntax. * changelog * refactor: Less boilerplate * docs: Warn about field moves
1 parent 17d294d commit a66da25

7 files changed

Lines changed: 413 additions & 17 deletions

File tree

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use darling::{Error, FromAttributes, FromMeta, Result, util::Flag};
2-
use syn::Path;
2+
use syn::{Meta, Path};
33

44
#[derive(Debug, FromAttributes)]
55
#[darling(attributes(versioned), and_then = ContainerAttributes::validate)]
@@ -51,6 +51,9 @@ pub struct ContainerSkipArguments {
5151
/// - `crates`: Override specific crates.
5252
/// - `status`: Set the specified struct as the status subresource.
5353
/// - `scale`: Configure the scale subresource for horizontal pod autoscaling integration.
54+
/// - `printcolumn`: Add an additional printer column, which is displayed by `kubectl get` and
55+
/// also nicely shows up in tools like k9s. This can be specified multiple times. The argument is
56+
/// passed through as-is, so it supports the same syntax as `#[kube(printcolumn(...))]`.
5457
/// - `shortname`: Set a shortname for the CR object. This can be specified multiple
5558
/// times.
5659
/// - `selectable`: Set the JSON path of a field which can be used as a field selector.
@@ -71,7 +74,10 @@ pub struct StructCrdArguments {
7174
// derive
7275
// schema
7376
pub scale: Option<Scale>,
74-
// printcolumn
77+
// Kept as raw meta and passed through verbatim, so that kube-derive does the parsing and
78+
// validation and we don't need to keep a copy of its printcolumn struct in sync.
79+
#[darling(multiple, rename = "printcolumn")]
80+
pub printcolumns: Vec<Meta>,
7581
#[darling(multiple, rename = "shortname")]
7682
pub shortnames: Vec<String>,
7783
// category

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

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -312,20 +312,9 @@ impl Struct {
312312
)}
313313
});
314314

315-
let shortnames: TokenStream = spec_gen_ctx
316-
.kubernetes_arguments
317-
.shortnames
318-
.iter()
319-
.map(|s| quote! { , shortname = #s })
320-
.collect();
321-
322-
let selectable_fields: TokenStream = spec_gen_ctx
323-
.kubernetes_arguments
324-
.selectable_fields
325-
.iter()
326-
.map(|s| quote! { , selectable = #s })
327-
.collect();
328-
315+
let printcolumns = &spec_gen_ctx.kubernetes_arguments.printcolumns;
316+
let shortnames = &spec_gen_ctx.kubernetes_arguments.shortnames;
317+
let selectable_fields = &spec_gen_ctx.kubernetes_arguments.selectable_fields;
329318
let doc = &spec_gen_ctx.kubernetes_arguments.doc;
330319

331320
quote! {
@@ -335,7 +324,10 @@ impl Struct {
335324
// These must be comma separated (except the last) as they always exist:
336325
group = #group, version = #version, kind = #kind, doc = #doc
337326
// These fields are optional, and therefore the token stream must prefix each with a comma:
338-
#singular #plural #namespaced #crates #status #scale #shortnames #selectable_fields
327+
#singular #plural #namespaced #crates #status #scale
328+
#(, #printcolumns)*
329+
#(, shortname = #shortnames)*
330+
#(, selectable = #selectable_fields)*
339331
)]
340332
}
341333
}

‎crates/stackable-versioned-macros/src/lib.rs‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,15 @@ mod utils;
347347
/// // tracking is enabled, this struct will be automatically merged into
348348
/// // the generated tracking status struct.
349349
/// status = "FooStatus",
350+
/// // Add an additional printer column, which is displayed by `kubectl
351+
/// // get` and also nicely shows up in tools like k9s. This can be
352+
/// // specified multiple times and supports the same syntax as
353+
/// // `#[kube(printcolumn(...))]`. The column is used for all versions,
354+
/// // so the JSON path must be valid in every version. Keep in mind
355+
/// // that changing (renaming) or deprecating a field also changes its
356+
/// // name. Kubernetes doesn't validate the path, the column just shows
357+
/// // `<none>` in versions where the field doesn't exist.
358+
/// printcolumn(name = "Baz", json_path = ".spec.baz", type_ = "boolean"),
350359
/// // Set a shortname. This can be specified multiple times.
351360
/// shortname = "...",
352361
/// // Set the JSON path of a field which can be used as a field
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use stackable_versioned::versioned;
2+
// ---
3+
#[versioned(version(name = "v1alpha1"), version(name = "v1beta1"))]
4+
// ---
5+
pub(crate) mod versioned {
6+
#[versioned(crd(
7+
group = "stackable.tech",
8+
printcolumn(name = "Bar", json_path = ".spec.bar", type_ = "string"),
9+
printcolumn(
10+
name = "Baz",
11+
json_path = ".spec.baz",
12+
type_ = "integer",
13+
description = "The baz value",
14+
format = "int32",
15+
priority = 1
16+
),
17+
doc = "Test"
18+
))]
19+
#[derive(
20+
Clone,
21+
Debug,
22+
serde::Deserialize,
23+
serde::Serialize,
24+
schemars::JsonSchema,
25+
kube::CustomResource,
26+
)]
27+
pub(crate) struct FooSpec {
28+
bar: String,
29+
baz: u16,
30+
}
31+
}
32+
// ---
33+
fn main() {}

0 commit comments

Comments
 (0)