@@ -45,6 +45,7 @@ use stackable_operator::{
45
45
DeepMerge ,
46
46
} ,
47
47
kube:: {
48
+ core:: { error_boundary, DeserializeGuard } ,
48
49
runtime:: { controller:: Action , reflector:: ObjectRef } ,
49
50
Resource , ResourceExt ,
50
51
} ,
@@ -289,6 +290,11 @@ pub enum Error {
289
290
"failed to write to String (Vec<u8> to be precise) containing Airflow config"
290
291
) ) ]
291
292
WriteToConfigFileString { source : std:: io:: Error } ,
293
+
294
+ #[ snafu( display( "AirflowCluster object is invalid" ) ) ]
295
+ InvalidAirflowCluster {
296
+ source : error_boundary:: InvalidObject ,
297
+ } ,
292
298
}
293
299
294
300
type Result < T , E = Error > = std:: result:: Result < T , E > ;
@@ -299,9 +305,18 @@ impl ReconcilerError for Error {
299
305
}
300
306
}
301
307
302
- pub async fn reconcile_airflow ( airflow : Arc < AirflowCluster > , ctx : Arc < Ctx > ) -> Result < Action > {
308
+ pub async fn reconcile_airflow (
309
+ airflow : Arc < DeserializeGuard < AirflowCluster > > ,
310
+ ctx : Arc < Ctx > ,
311
+ ) -> Result < Action > {
303
312
tracing:: info!( "Starting reconcile" ) ;
304
313
314
+ let airflow = airflow
315
+ . 0
316
+ . as_ref ( )
317
+ . map_err ( error_boundary:: InvalidObject :: clone)
318
+ . context ( InvalidAirflowClusterSnafu ) ?;
319
+
305
320
let client = & ctx. client ;
306
321
let resolved_product_image: ResolvedProductImage = airflow
307
322
. spec
@@ -338,7 +353,7 @@ pub async fn reconcile_airflow(airflow: Arc<AirflowCluster>, ctx: Arc<Ctx>) -> R
338
353
}
339
354
}
340
355
341
- let role_config = transform_all_roles_to_config :: < AirflowConfigFragment , _ > ( & airflow, roles) ;
356
+ let role_config = transform_all_roles_to_config :: < AirflowConfigFragment , _ > ( airflow, roles) ;
342
357
let validated_role_config = validate_all_roles_and_groups_config (
343
358
& resolved_product_image. product_version ,
344
359
& role_config. context ( ProductConfigTransformSnafu ) ?,
@@ -350,7 +365,7 @@ pub async fn reconcile_airflow(airflow: Arc<AirflowCluster>, ctx: Arc<Ctx>) -> R
350
365
351
366
let vector_aggregator_address = resolve_vector_aggregator_address (
352
367
client,
353
- airflow. as_ref ( ) ,
368
+ airflow,
354
369
airflow
355
370
. spec
356
371
. cluster_config
@@ -374,8 +389,7 @@ pub async fn reconcile_airflow(airflow: Arc<AirflowCluster>, ctx: Arc<Ctx>) -> R
374
389
. context ( BuildLabelSnafu ) ?;
375
390
376
391
let ( rbac_sa, rbac_rolebinding) =
377
- build_rbac_resources ( airflow. as_ref ( ) , APP_NAME , required_labels)
378
- . context ( BuildRBACObjectsSnafu ) ?;
392
+ build_rbac_resources ( airflow, APP_NAME , required_labels) . context ( BuildRBACObjectsSnafu ) ?;
379
393
380
394
let rbac_sa = cluster_resources
381
395
. add ( client, rbac_sa)
@@ -397,7 +411,7 @@ pub async fn reconcile_airflow(airflow: Arc<AirflowCluster>, ctx: Arc<Ctx>) -> R
397
411
} = & airflow_executor
398
412
{
399
413
build_executor_template (
400
- & airflow,
414
+ airflow,
401
415
common_configuration,
402
416
& resolved_product_image,
403
417
& authentication_config,
@@ -418,7 +432,7 @@ pub async fn reconcile_airflow(airflow: Arc<AirflowCluster>, ctx: Arc<Ctx>) -> R
418
432
// some roles will only run "internally" and do not need to be created as services
419
433
if let Some ( resolved_port) = role_port ( role_name) {
420
434
let role_service =
421
- build_role_service ( & airflow, & resolved_product_image, role_name, resolved_port) ?;
435
+ build_role_service ( airflow, & resolved_product_image, role_name, resolved_port) ?;
422
436
cluster_resources
423
437
. add ( client, role_service)
424
438
. await
@@ -427,7 +441,7 @@ pub async fn reconcile_airflow(airflow: Arc<AirflowCluster>, ctx: Arc<Ctx>) -> R
427
441
428
442
for ( rolegroup_name, rolegroup_config) in role_config. iter ( ) {
429
443
let rolegroup = RoleGroupRef {
430
- cluster : ObjectRef :: from_obj ( & * airflow) ,
444
+ cluster : ObjectRef :: from_obj ( airflow) ,
431
445
role : role_name. into ( ) ,
432
446
role_group : rolegroup_name. into ( ) ,
433
447
} ;
@@ -436,16 +450,15 @@ pub async fn reconcile_airflow(airflow: Arc<AirflowCluster>, ctx: Arc<Ctx>) -> R
436
450
. merged_config ( & airflow_role, & rolegroup)
437
451
. context ( FailedToResolveConfigSnafu ) ?;
438
452
439
- let rg_service =
440
- build_rolegroup_service ( & airflow, & resolved_product_image, & rolegroup) ?;
453
+ let rg_service = build_rolegroup_service ( airflow, & resolved_product_image, & rolegroup) ?;
441
454
cluster_resources. add ( client, rg_service) . await . context (
442
455
ApplyRoleGroupServiceSnafu {
443
456
rolegroup : rolegroup. clone ( ) ,
444
457
} ,
445
458
) ?;
446
459
447
460
let rg_statefulset = build_server_rolegroup_statefulset (
448
- & airflow,
461
+ airflow,
449
462
& resolved_product_image,
450
463
& airflow_role,
451
464
& rolegroup,
@@ -466,7 +479,7 @@ pub async fn reconcile_airflow(airflow: Arc<AirflowCluster>, ctx: Arc<Ctx>) -> R
466
479
) ;
467
480
468
481
let rg_configmap = build_rolegroup_config_map (
469
- & airflow,
482
+ airflow,
470
483
& resolved_product_image,
471
484
& rolegroup,
472
485
rolegroup_config,
@@ -488,7 +501,7 @@ pub async fn reconcile_airflow(airflow: Arc<AirflowCluster>, ctx: Arc<Ctx>) -> R
488
501
pod_disruption_budget : pdb,
489
502
} ) = role_config
490
503
{
491
- add_pdbs ( pdb, & airflow, & airflow_role, client, & mut cluster_resources)
504
+ add_pdbs ( pdb, airflow, & airflow_role, client, & mut cluster_resources)
492
505
. await
493
506
. context ( FailedToCreatePdbSnafu ) ?;
494
507
}
@@ -501,13 +514,13 @@ pub async fn reconcile_airflow(airflow: Arc<AirflowCluster>, ctx: Arc<Ctx>) -> R
501
514
502
515
let status = AirflowClusterStatus {
503
516
conditions : compute_conditions (
504
- airflow. as_ref ( ) ,
517
+ airflow,
505
518
& [ & ss_cond_builder, & cluster_operation_cond_builder] ,
506
519
) ,
507
520
} ;
508
521
509
522
client
510
- . apply_patch_status ( OPERATOR_NAME , & * airflow, & status)
523
+ . apply_patch_status ( OPERATOR_NAME , airflow, & status)
511
524
. await
512
525
. context ( ApplyStatusSnafu ) ?;
513
526
@@ -516,7 +529,7 @@ pub async fn reconcile_airflow(airflow: Arc<AirflowCluster>, ctx: Arc<Ctx>) -> R
516
529
517
530
#[ allow( clippy:: too_many_arguments) ]
518
531
async fn build_executor_template (
519
- airflow : & Arc < AirflowCluster > ,
532
+ airflow : & AirflowCluster ,
520
533
common_config : & CommonConfiguration < ExecutorConfigFragment > ,
521
534
resolved_product_image : & ResolvedProductImage ,
522
535
authentication_config : & Vec < AirflowAuthenticationConfigResolved > ,
@@ -529,7 +542,7 @@ async fn build_executor_template(
529
542
. merged_executor_config ( & common_config. config )
530
543
. context ( FailedToResolveConfigSnafu ) ?;
531
544
let rolegroup = RoleGroupRef {
532
- cluster : ObjectRef :: from_obj ( & * * airflow) ,
545
+ cluster : ObjectRef :: from_obj ( airflow) ,
533
546
role : "executor" . into ( ) ,
534
547
role_group : "kubernetes" . into ( ) ,
535
548
} ;
@@ -1223,8 +1236,17 @@ fn build_gitsync_container(
1223
1236
Ok ( gitsync_container)
1224
1237
}
1225
1238
1226
- pub fn error_policy ( _obj : Arc < AirflowCluster > , _error : & Error , _ctx : Arc < Ctx > ) -> Action {
1227
- Action :: requeue ( * Duration :: from_secs ( 5 ) )
1239
+ pub fn error_policy (
1240
+ _obj : Arc < DeserializeGuard < AirflowCluster > > ,
1241
+ error : & Error ,
1242
+ _ctx : Arc < Ctx > ,
1243
+ ) -> Action {
1244
+ match error {
1245
+ // root object is invalid, will be requeued when modified anyway
1246
+ Error :: InvalidAirflowCluster { .. } => Action :: await_change ( ) ,
1247
+
1248
+ _ => Action :: requeue ( * Duration :: from_secs ( 10 ) ) ,
1249
+ }
1228
1250
}
1229
1251
1230
1252
fn add_authentication_volumes_and_volume_mounts (
0 commit comments