@@ -8,13 +8,17 @@ use syn::{parse_quote, DataStruct, Error, Ident};
8
8
use crate :: {
9
9
attrs:: common:: ContainerAttributes ,
10
10
codegen:: {
11
- common:: { Container , ContainerInput , ContainerVersion , Item , VersionedContainer } ,
11
+ common:: {
12
+ Container , ContainerInput , ContainerVersion , Item , VersionExt , VersionedContainer ,
13
+ } ,
12
14
vstruct:: field:: VersionedField ,
13
15
} ,
14
16
} ;
15
17
16
18
pub ( crate ) mod field;
17
19
20
+ type GenerateVersionReturn = ( TokenStream , Option < ( TokenStream , ( Ident , String ) ) > ) ;
21
+
18
22
/// Stores individual versions of a single struct. Each version tracks field
19
23
/// actions, which describe if the field was added, renamed or deprecated in
20
24
/// that version. Fields which are not versioned, are included in every
@@ -85,24 +89,30 @@ impl Container<DataStruct, VersionedField> for VersionedStruct {
85
89
}
86
90
87
91
fn generate_tokens ( & self ) -> TokenStream {
88
- let mut kubernetes_crd_fn_calls = TokenStream :: new ( ) ;
89
- let mut container_definition = TokenStream :: new ( ) ;
92
+ let mut tokens = TokenStream :: new ( ) ;
93
+
94
+ let mut enum_variants = Vec :: new ( ) ;
95
+ let mut crd_fn_calls = Vec :: new ( ) ;
90
96
91
97
let mut versions = self . versions . iter ( ) . peekable ( ) ;
92
98
93
99
while let Some ( version) = versions. next ( ) {
94
- container_definition. extend ( self . generate_version ( version, versions. peek ( ) . copied ( ) ) ) ;
95
- kubernetes_crd_fn_calls. extend ( self . generate_kubernetes_crd_fn_call ( version) ) ;
100
+ let ( container_definition, merged_crd) =
101
+ self . generate_version ( version, versions. peek ( ) . copied ( ) ) ;
102
+
103
+ if let Some ( ( crd_fn_call, enum_variant) ) = merged_crd {
104
+ enum_variants. push ( enum_variant) ;
105
+ crd_fn_calls. push ( crd_fn_call) ;
106
+ }
107
+
108
+ tokens. extend ( container_definition) ;
96
109
}
97
110
98
- // If tokens for the 'crd()' function calls were generated, also generate
99
- // the 'merge_crds' call.
100
- if !kubernetes_crd_fn_calls. is_empty ( ) {
101
- container_definition
102
- . extend ( self . generate_kubernetes_merge_crds ( kubernetes_crd_fn_calls) ) ;
111
+ if !crd_fn_calls. is_empty ( ) {
112
+ tokens. extend ( self . generate_kubernetes_merge_crds ( crd_fn_calls, enum_variants) ) ;
103
113
}
104
114
105
- container_definition
115
+ tokens
106
116
}
107
117
}
108
118
@@ -112,7 +122,7 @@ impl VersionedStruct {
112
122
& self ,
113
123
version : & ContainerVersion ,
114
124
next_version : Option < & ContainerVersion > ,
115
- ) -> TokenStream {
125
+ ) -> GenerateVersionReturn {
116
126
let mut token_stream = TokenStream :: new ( ) ;
117
127
118
128
let original_attributes = & self . original_attributes ;
@@ -137,7 +147,27 @@ impl VersionedStruct {
137
147
let version_specific_docs = self . generate_struct_docs ( version) ;
138
148
139
149
// Generate K8s specific code
140
- let kubernetes_cr_derive = self . generate_kubernetes_cr_derive ( version) ;
150
+ let ( kubernetes_cr_derive, merged_crd) = match & self . options . kubernetes_options {
151
+ Some ( options) => {
152
+ // Generate the CustomResource derive macro with the appropriate
153
+ // attributes supplied using #[kube()].
154
+ let cr_derive = self . generate_kubernetes_cr_derive ( version) ;
155
+
156
+ // Generate merged_crd specific code when not opted out.
157
+ let merged_crd = if !options. skip_merged_crd {
158
+ let crd_fn_call = self . generate_kubernetes_crd_fn_call ( version) ;
159
+ let enum_variant = version. inner . as_variant_ident ( ) ;
160
+ let enum_display = version. inner . to_string ( ) ;
161
+
162
+ Some ( ( crd_fn_call, ( enum_variant, enum_display) ) )
163
+ } else {
164
+ None
165
+ } ;
166
+
167
+ ( Some ( cr_derive) , merged_crd)
168
+ }
169
+ None => ( None , None ) ,
170
+ } ;
141
171
142
172
// Generate tokens for the module and the contained struct
143
173
token_stream. extend ( quote ! {
@@ -160,7 +190,7 @@ impl VersionedStruct {
160
190
token_stream. extend ( self . generate_from_impl ( version, next_version) ) ;
161
191
}
162
192
163
- token_stream
193
+ ( token_stream, merged_crd )
164
194
}
165
195
166
196
/// Generates version specific doc comments for the struct.
@@ -253,61 +283,102 @@ impl VersionedStruct {
253
283
/// attributes.
254
284
fn generate_kubernetes_cr_derive ( & self , version : & ContainerVersion ) -> Option < TokenStream > {
255
285
if let Some ( kubernetes_options) = & self . options . kubernetes_options {
286
+ // Required arguments
256
287
let group = & kubernetes_options. group ;
257
288
let version = version. inner . to_string ( ) ;
258
289
let kind = kubernetes_options
259
290
. kind
260
291
. as_ref ( )
261
292
. map_or ( self . idents . kubernetes . to_string ( ) , |kind| kind. clone ( ) ) ;
262
293
294
+ // Optional arguments
295
+ let namespaced = kubernetes_options
296
+ . namespaced
297
+ . then_some ( quote ! { , namespaced } ) ;
298
+ let singular = kubernetes_options
299
+ . singular
300
+ . as_ref ( )
301
+ . map ( |s| quote ! { , singular = #s } ) ;
302
+ let plural = kubernetes_options
303
+ . plural
304
+ . as_ref ( )
305
+ . map ( |p| quote ! { , plural = #p } ) ;
306
+
263
307
return Some ( quote ! {
264
308
#[ derive( :: kube:: CustomResource ) ]
265
- #[ kube( group = #group, version = #version, kind = #kind) ]
309
+ #[ kube( group = #group, version = #version, kind = #kind #singular #plural #namespaced ) ]
266
310
} ) ;
267
311
}
268
312
269
313
None
270
314
}
271
315
272
316
/// Generates the `merge_crds` function call.
273
- fn generate_kubernetes_merge_crds ( & self , fn_calls : TokenStream ) -> TokenStream {
317
+ fn generate_kubernetes_merge_crds (
318
+ & self ,
319
+ crd_fn_calls : Vec < TokenStream > ,
320
+ enum_variants : Vec < ( Ident , String ) > ,
321
+ ) -> TokenStream {
274
322
let ident = & self . idents . kubernetes ;
275
323
324
+ let version_enum_definition = self . generate_kubernetes_version_enum ( enum_variants) ;
325
+
276
326
quote ! {
277
327
#[ automatically_derived]
278
328
pub struct #ident;
279
329
330
+ #version_enum_definition
331
+
280
332
#[ automatically_derived]
281
333
impl #ident {
282
334
/// Generates a merged CRD which contains all versions defined using the
283
335
/// `#[versioned()]` macro.
284
336
pub fn merged_crd(
285
- stored_apiversion: & str
337
+ stored_apiversion: Version
286
338
) -> :: std:: result:: Result <:: k8s_openapi:: apiextensions_apiserver:: pkg:: apis:: apiextensions:: v1:: CustomResourceDefinition , :: kube:: core:: crd:: MergeError > {
287
- :: kube:: core:: crd:: merge_crds( vec![ #fn_calls ] , stored_apiversion)
339
+ :: kube:: core:: crd:: merge_crds( vec![ #( #crd_fn_calls ) , * ] , & stored_apiversion. to_string ( ) )
288
340
}
289
341
}
290
342
}
291
343
}
292
344
293
345
/// Generates the inner `crd()` functions calls which get used in the
294
346
/// `merge_crds` function.
295
- fn generate_kubernetes_crd_fn_call ( & self , version : & ContainerVersion ) -> Option < TokenStream > {
296
- if self
297
- . options
298
- . kubernetes_options
299
- . as_ref ( )
300
- . is_some_and ( |o| !o. skip_merged_crd )
301
- {
302
- let struct_ident = & self . idents . kubernetes ;
303
- let version_ident = & version. ident ;
304
-
305
- let path: syn:: Path = parse_quote ! ( #version_ident:: #struct_ident) ;
306
- return Some ( quote ! {
307
- <#path as :: kube:: CustomResourceExt >:: crd( ) ,
347
+ fn generate_kubernetes_crd_fn_call ( & self , version : & ContainerVersion ) -> TokenStream {
348
+ let struct_ident = & self . idents . kubernetes ;
349
+ let version_ident = & version. ident ;
350
+ let path: syn:: Path = parse_quote ! ( #version_ident:: #struct_ident) ;
351
+
352
+ quote ! {
353
+ <#path as :: kube:: CustomResourceExt >:: crd( )
354
+ }
355
+ }
356
+
357
+ fn generate_kubernetes_version_enum ( & self , enum_variants : Vec < ( Ident , String ) > ) -> TokenStream {
358
+ let mut enum_variant_matches = TokenStream :: new ( ) ;
359
+ let mut enum_variant_idents = TokenStream :: new ( ) ;
360
+
361
+ for ( enum_variant_ident, enum_variant_display) in enum_variants {
362
+ enum_variant_idents. extend ( quote ! { #enum_variant_ident, } ) ;
363
+ enum_variant_matches. extend ( quote ! {
364
+ Version :: #enum_variant_ident => f. write_str( #enum_variant_display) ,
308
365
} ) ;
309
366
}
310
367
311
- None
368
+ quote ! {
369
+ #[ automatically_derived]
370
+ pub enum Version {
371
+ #enum_variant_idents
372
+ }
373
+
374
+ #[ automatically_derived]
375
+ impl :: std:: fmt:: Display for Version {
376
+ fn fmt( & self , f: & mut :: std:: fmt:: Formatter <' _>) -> :: std:: result:: Result <( ) , :: std:: fmt:: Error > {
377
+ match self {
378
+ #enum_variant_matches
379
+ }
380
+ }
381
+ }
382
+ }
312
383
}
313
384
}
0 commit comments