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