@@ -45,7 +45,7 @@ impl Container {
45
45
// Ensure that the struct name includes the 'Spec' suffix.
46
46
if kubernetes_data. is_some ( ) && !idents. original . as_str ( ) . ends_with ( "Spec" ) {
47
47
return Err ( Error :: custom (
48
- "struct name needs to include the `Spec` suffix if Kubernetes features are enabled via `#[versioned(k8s ())]`"
48
+ "struct name needs to include the `Spec` suffix if CRD features are enabled via `#[versioned(crd ())]`"
49
49
) . with_span ( & idents. original . span ( ) ) ) ;
50
50
}
51
51
@@ -207,7 +207,7 @@ impl Struct {
207
207
fn generate_kube_attribute (
208
208
& self ,
209
209
ver_ctx : VersionContext < ' _ > ,
210
- gen_ctx : ModuleGenerationContext < ' _ > ,
210
+ mod_gen_ctx : ModuleGenerationContext < ' _ > ,
211
211
spec_gen_ctx : & SpecGenerationContext < ' _ > ,
212
212
) -> Option < TokenStream > {
213
213
// Required arguments
@@ -234,27 +234,37 @@ impl Struct {
234
234
. as_ref ( )
235
235
. map ( |p| quote ! { , plural = #p } ) ;
236
236
237
- let crates = gen_ctx . crates ;
237
+ let crates = mod_gen_ctx . crates ;
238
238
239
239
let namespaced = spec_gen_ctx
240
240
. kubernetes_arguments
241
241
. namespaced
242
242
. is_present ( )
243
243
. then_some ( quote ! { , namespaced } ) ;
244
244
245
+ // NOTE (@Techassi): What an abomination
245
246
let status = match (
246
- gen_ctx
247
+ mod_gen_ctx
247
248
. kubernetes_options
248
249
. experimental_conversion_tracking
249
250
. is_present ( ) ,
250
251
& spec_gen_ctx. kubernetes_arguments . status ,
251
252
) {
252
- ( true , _) => {
253
- let status_ident = & spec_gen_ctx. kubernetes_idents . status ;
254
- Some ( quote ! { , status = #status_ident } )
253
+ ( true , status_path) => {
254
+ if ( mod_gen_ctx. skip . merged_crd . is_present ( ) || self . common . options . skip_merged_crd )
255
+ && ( mod_gen_ctx. skip . try_convert . is_present ( )
256
+ || self . common . options . skip_try_convert )
257
+ {
258
+ status_path
259
+ . as_ref ( )
260
+ . map ( |status_path| quote ! { , status = #status_path } )
261
+ } else {
262
+ let status_ident = & spec_gen_ctx. kubernetes_idents . status ;
263
+ Some ( quote ! { , status = #status_ident } )
264
+ }
255
265
}
256
- ( _ , Some ( status_ident ) ) => Some ( quote ! { , status = #status_ident } ) ,
257
- ( _ , _ ) => None ,
266
+ ( false , Some ( status_path ) ) => Some ( quote ! { , status = #status_path } ) ,
267
+ _ => None ,
258
268
} ;
259
269
260
270
let shortnames: TokenStream = spec_gen_ctx
@@ -306,14 +316,7 @@ impl Struct {
306
316
) -> TokenStream {
307
317
let enum_ident = & spec_gen_ctx. kubernetes_idents . kind ;
308
318
309
- // Only generate merged_crd associated function if not opted out
310
- let merged_crd_fn =
311
- if !mod_gen_ctx. skip . merged_crd . is_present ( ) && !self . common . options . skip_merged_crd {
312
- Some ( self . generate_merged_crd_fn ( mod_gen_ctx, spec_gen_ctx) )
313
- } else {
314
- None
315
- } ;
316
-
319
+ let merged_crd_fn = self . generate_merged_crd_fn ( mod_gen_ctx, spec_gen_ctx) ;
317
320
let try_convert_fn = self . generate_try_convert_fn ( versions, mod_gen_ctx, spec_gen_ctx) ;
318
321
let from_json_value_fn = self . generate_from_json_value_fn ( mod_gen_ctx, spec_gen_ctx) ;
319
322
let into_json_value_fn = self . generate_into_json_value_fn ( mod_gen_ctx, spec_gen_ctx) ;
@@ -421,22 +424,84 @@ impl Struct {
421
424
return None ;
422
425
}
423
426
424
- if !mod_gen_ctx
425
- . kubernetes_options
426
- . experimental_conversion_tracking
427
- . is_present ( )
428
- {
429
- return None ;
430
- }
431
-
432
427
let next_version = ver_ctx. next_version ;
433
428
let version = ver_ctx. version ;
434
429
435
430
next_version. map ( |next_version| {
436
- self . generate_tracking_from_impl ( direction, version, next_version, mod_gen_ctx)
431
+ if mod_gen_ctx
432
+ . kubernetes_options
433
+ . experimental_conversion_tracking
434
+ . is_present ( )
435
+ {
436
+ self . generate_tracking_from_impl ( direction, version, next_version, mod_gen_ctx)
437
+ } else {
438
+ self . generate_plain_from_impl ( direction, version, next_version, mod_gen_ctx)
439
+ }
437
440
} )
438
441
}
439
442
443
+ fn generate_plain_from_impl (
444
+ & self ,
445
+ direction : Direction ,
446
+ version : & VersionDefinition ,
447
+ next_version : & VersionDefinition ,
448
+ mod_gen_ctx : ModuleGenerationContext < ' _ > ,
449
+ ) -> TokenStream {
450
+ // TODO (@Techassi): A bunch this stuff is duplicated in self.generate_tracking_from_impl.
451
+ // Ideally we remove that duplication.
452
+ let from_struct_ident = & self . common . idents . parameter ;
453
+ let struct_ident = & self . common . idents . original ;
454
+
455
+ // Include allow(deprecated) only when this or the next version is
456
+ // deprecated. Also include it, when a field in this or the next
457
+ // version is deprecated.
458
+ let allow_attribute = ( version. deprecated . is_some ( )
459
+ || next_version. deprecated . is_some ( )
460
+ || self . is_any_field_deprecated ( version)
461
+ || self . is_any_field_deprecated ( next_version) )
462
+ . then ( || quote ! { #[ allow( deprecated) ] } ) ;
463
+
464
+ // Only add the #[automatically_derived] attribute only if this impl is used
465
+ // outside of a module (in standalone mode).
466
+ let automatically_derived = mod_gen_ctx. automatically_derived_attr ( ) ;
467
+
468
+ let fields = |direction : Direction | -> TokenStream {
469
+ self . fields
470
+ . iter ( )
471
+ . filter_map ( |f| {
472
+ f. generate_for_from_impl ( direction, version, next_version, from_struct_ident)
473
+ } )
474
+ . collect ( )
475
+ } ;
476
+
477
+ let ( fields, for_module_ident, from_module_ident) = match direction {
478
+ direction @ Direction :: Upgrade => {
479
+ let from_module_ident = & version. idents . module ;
480
+ let for_module_ident = & next_version. idents . module ;
481
+
482
+ ( fields ( direction) , for_module_ident, from_module_ident)
483
+ }
484
+ direction @ Direction :: Downgrade => {
485
+ let from_module_ident = & next_version. idents . module ;
486
+ let for_module_ident = & version. idents . module ;
487
+
488
+ ( fields ( direction) , for_module_ident, from_module_ident)
489
+ }
490
+ } ;
491
+
492
+ quote ! {
493
+ #automatically_derived
494
+ #allow_attribute
495
+ impl :: core:: convert:: From <#from_module_ident:: #struct_ident> for #for_module_ident:: #struct_ident {
496
+ fn from( #from_struct_ident: #from_module_ident:: #struct_ident) -> Self {
497
+ Self {
498
+ #fields
499
+ }
500
+ }
501
+ }
502
+ }
503
+ }
504
+
440
505
/// Returns whether any field is deprecated in the provided `version`.
441
506
fn is_any_field_deprecated ( & self , version : & VersionDefinition ) -> bool {
442
507
// First, iterate over all fields. The `any` function will return true
0 commit comments