@@ -153,7 +153,8 @@ impl Struct {
153
153
// Generate additional Kubernetes code, this is split out to reduce the complexity in this
154
154
// function.
155
155
let status_struct = self . generate_kubernetes_status_struct ( kubernetes_arguments, is_nested) ;
156
- let version_enum = self . generate_kubernetes_version_enum ( tokens, vis, is_nested) ;
156
+ let version_enum =
157
+ self . generate_kubernetes_version_enum ( kubernetes_arguments, tokens, vis, is_nested) ;
157
158
let convert_method = self . generate_kubernetes_conversion ( versions) ;
158
159
159
160
let parse_object_error = quote ! { #versioned_path:: ParseObjectError } ;
@@ -173,7 +174,7 @@ impl Struct {
173
174
#k8s_openapi_path:: apiextensions_apiserver:: pkg:: apis:: apiextensions:: v1:: CustomResourceDefinition ,
174
175
#kube_core_path:: crd:: MergeError >
175
176
{
176
- #kube_core_path:: crd:: merge_crds( vec![ #( #crd_fns) , * ] , stored_apiversion. as_str ( ) )
177
+ #kube_core_path:: crd:: merge_crds( vec![ #( #crd_fns) , * ] , stored_apiversion. as_version_str ( ) )
177
178
}
178
179
179
180
#convert_method
@@ -234,6 +235,7 @@ impl Struct {
234
235
235
236
fn generate_kubernetes_version_enum (
236
237
& self ,
238
+ kubernetes_arguments : & KubernetesArguments ,
237
239
tokens : & KubernetesTokens ,
238
240
vis : & Visibility ,
239
241
is_nested : bool ,
@@ -244,9 +246,16 @@ impl Struct {
244
246
// module (in standalone mode).
245
247
let automatically_derived = is_nested. not ( ) . then ( || quote ! { #[ automatically_derived] } ) ;
246
248
249
+ let versioned_path = & * kubernetes_arguments. crates . versioned ;
250
+ let convert_object_error = quote ! { #versioned_path:: ConvertObjectError } ;
251
+
247
252
// Get the per-version items to be able to iterate over them via quote
248
253
let variant_strings = & tokens. variant_strings ;
249
254
let variant_idents = & tokens. variant_idents ;
255
+ let api_versions = variant_strings
256
+ . iter ( )
257
+ . map ( |version| format ! ( "{group}/{version}" , group = & kubernetes_arguments. group) )
258
+ . collect :: < Vec < _ > > ( ) ;
250
259
251
260
quote ! {
252
261
#automatically_derived
@@ -257,17 +266,33 @@ impl Struct {
257
266
#automatically_derived
258
267
impl :: std:: fmt:: Display for #enum_ident {
259
268
fn fmt( & self , f: & mut :: std:: fmt:: Formatter <' _>) -> :: std:: result:: Result <( ) , :: std:: fmt:: Error > {
260
- f. write_str( self . as_str( ) )
269
+ // The version (without the Kubernetes group) is probably more human-readable
270
+ f. write_str( self . as_version_str( ) )
261
271
}
262
272
}
263
273
264
274
#automatically_derived
265
275
impl #enum_ident {
266
- pub fn as_str ( & self ) -> & str {
276
+ pub fn as_version_str ( & self ) -> & str {
267
277
match self {
268
278
#( #variant_idents => #variant_strings) , *
269
279
}
270
280
}
281
+
282
+ pub fn as_api_version_str( & self ) -> & str {
283
+ match self {
284
+ #( #variant_idents => #api_versions) , *
285
+ }
286
+ }
287
+
288
+ pub fn try_from_api_version( api_version: & str ) -> Result <Self , #convert_object_error> {
289
+ match api_version {
290
+ #( #api_versions => Ok ( Self :: #variant_idents) ) , * ,
291
+ _ => Err ( #convert_object_error:: DesiredApiVersionUnknown {
292
+ unknown_desired_api_version: api_version. to_string( ) ,
293
+ } ) ,
294
+ }
295
+ }
271
296
}
272
297
}
273
298
}
@@ -331,6 +356,7 @@ impl Struct {
331
356
let kubernetes_arguments = self . common . options . kubernetes_arguments . as_ref ( ) ?;
332
357
333
358
let struct_ident = & self . common . idents . kubernetes ;
359
+ let version_enum_ident = & self . common . idents . kubernetes_version ;
334
360
335
361
let kube_client_path = & * kubernetes_arguments. crates . kube_client ;
336
362
let serde_json_path = & * kubernetes_arguments. crates . serde_json ;
@@ -342,8 +368,7 @@ impl Struct {
342
368
// Generate conversion paths and the match arms for these paths
343
369
let conversion_match_arms =
344
370
self . generate_kubernetes_conversion_match_arms ( versions, kubernetes_arguments) ;
345
- let noop_match_arms =
346
- self . generate_kubernetes_noop_match_arms ( versions, kubernetes_arguments) ;
371
+ let noop_match_arms = self . generate_kubernetes_noop_match_arms ( versions) ;
347
372
348
373
// TODO (@Techassi): Make this a feature, drop the option from the macro arguments
349
374
// Generate tracing attributes and events if tracing is enabled
@@ -393,11 +418,8 @@ impl Struct {
393
418
}
394
419
} ;
395
420
396
- // Extract the desired api version
397
- let desired_api_version = request. desired_api_version. as_str( ) ;
398
-
399
421
// Convert all objects into the desired version
400
- let response = match Self :: convert_objects( request. objects, desired_api_version) {
422
+ let response = match Self :: convert_objects( request. objects, & request . desired_api_version) {
401
423
:: std:: result:: Result :: Ok ( converted_objects) => {
402
424
#successful_conversion_response_event
403
425
@@ -444,6 +466,9 @@ impl Struct {
444
466
)
445
467
-> :: std:: result:: Result <:: std:: vec:: Vec <#serde_json_path:: Value >, #convert_object_error>
446
468
{
469
+ let desired_api_version = #version_enum_ident:: try_from_api_version( desired_api_version) ?;
470
+ // let desired_api_version: #version_enum_ident = desired_api_version.try_into()?;
471
+
447
472
let mut converted_objects = :: std:: vec:: Vec :: with_capacity( objects. len( ) ) ;
448
473
449
474
for object in objects {
@@ -452,14 +477,11 @@ impl Struct {
452
477
let current_object = Self :: from_json_value( object. clone( ) )
453
478
. map_err( |source| #convert_object_error:: Parse { source } ) ?;
454
479
455
- match ( current_object, desired_api_version) {
480
+ match ( current_object, & desired_api_version) {
456
481
#( #conversion_match_arms, ) *
482
+ // We explicitly list the remaining no-op cases, so the compiler ensures we
483
+ // did not miss a conversion.
457
484
#( #noop_match_arms, ) *
458
- ( _, unknown_desired_api_version) => return :: std:: result:: Result :: Err (
459
- #convert_object_error:: DesiredApiVersionUnknown {
460
- unknown_desired_api_version: unknown_desired_api_version. to_string( )
461
- }
462
- )
463
485
}
464
486
}
465
487
@@ -476,6 +498,7 @@ impl Struct {
476
498
let group = & kubernetes_arguments. group ;
477
499
let variant_data_ident = & self . common . idents . kubernetes_parameter ;
478
500
let struct_ident = & self . common . idents . kubernetes ;
501
+ let version_enum_ident = & self . common . idents . kubernetes_version ;
479
502
let spec_ident = & self . common . idents . original ;
480
503
481
504
let versioned_path = & * kubernetes_arguments. crates . versioned ;
@@ -530,7 +553,7 @@ impl Struct {
530
553
. then ( || quote ! { status: #variant_data_ident. status, } ) ;
531
554
532
555
quote ! {
533
- ( Self :: #current_object_version_ident( #variant_data_ident) , #desired_object_api_version_string ) => {
556
+ ( Self :: #current_object_version_ident( #variant_data_ident) , #version_enum_ident :: #desired_object_variant_ident ) => {
534
557
#( #conversions) *
535
558
536
559
let desired_object = Self :: #desired_object_variant_ident( #desired_object_module_ident:: #struct_ident {
@@ -554,22 +577,19 @@ impl Struct {
554
577
fn generate_kubernetes_noop_match_arms (
555
578
& self ,
556
579
versions : & [ VersionDefinition ] ,
557
- kubernetes_arguments : & KubernetesArguments ,
558
580
) -> Vec < TokenStream > {
559
- let group = & kubernetes_arguments . group ;
581
+ let version_enum_ident = & self . common . idents . kubernetes_version ;
560
582
561
583
versions
562
584
. iter ( )
563
585
. map ( |version| {
564
586
let version_ident = & version. idents . variant ;
565
- let version_string = version. inner . to_string ( ) ;
566
- let api_version_string = format ! ( "{group}/{version_string}" ) ;
567
587
568
588
quote ! {
569
589
// This is the case if the desired version matches the current object api version.
570
590
// NOTE (@Techassi): I'm curious if this will ever happen? In theory the K8s
571
591
// apiserver should never send such a conversion review.
572
- ( Self :: #version_ident( _) , #api_version_string ) => converted_objects. push( object)
592
+ ( Self :: #version_ident( _) , #version_enum_ident :: #version_ident ) => converted_objects. push( object)
573
593
}
574
594
} )
575
595
. collect ( )
0 commit comments