@@ -410,13 +410,18 @@ func (r *Reconciler) Reconcile(req ctrl.Request) (res ctrl.Result, err error) {
410
410
411
411
actionClient , err := r .actionClientGetter .ActionClientFor (obj )
412
412
if err != nil {
413
- u .UpdateStatus (updater .EnsureCondition (conditions .Irreconcilable (corev1 .ConditionTrue , conditions .ReasonErrorGatheringState , err )))
413
+ u .UpdateStatus (updater .EnsureCondition (conditions .Irreconcilable (corev1 .ConditionTrue , conditions .ReasonErrorGettingClient , err )))
414
+ return ctrl.Result {}, err
415
+ }
416
+
417
+ if obj .GetDeletionTimestamp () != nil {
418
+ err := r .handleDeletion (ctx , actionClient , obj , log )
414
419
return ctrl.Result {}, err
415
420
}
416
421
417
422
vals , err := r .getValues (obj )
418
423
if err != nil {
419
- u .UpdateStatus (updater .EnsureCondition (conditions .Irreconcilable (corev1 .ConditionTrue , conditions .ReasonErrorGatheringState , err )))
424
+ u .UpdateStatus (updater .EnsureCondition (conditions .Irreconcilable (corev1 .ConditionTrue , conditions .ReasonErrorMappingValues , err )))
420
425
return ctrl.Result {}, err
421
426
}
422
427
@@ -428,50 +433,14 @@ func (r *Reconciler) Reconcile(req ctrl.Request) (res ctrl.Result, err error) {
428
433
429
434
rel , state , err := r .getReleaseState (actionClient , obj , vals .AsMap ())
430
435
if err != nil {
431
- u .UpdateStatus (updater .EnsureCondition (conditions .Irreconcilable (corev1 .ConditionTrue , conditions .ReasonErrorGatheringState , err )))
436
+ u .UpdateStatus (updater .EnsureCondition (conditions .Irreconcilable (corev1 .ConditionTrue , conditions .ReasonErrorGettingReleaseState , err )))
432
437
return ctrl.Result {}, err
433
438
}
434
- u .UpdateStatus (updater .EnsureCondition (conditions .Irreconcilable (corev1 .ConditionFalse , "" , "" )))
435
-
436
- switch state {
437
- case stateAlreadyUninstalled :
438
- log .Info ("Resource is terminated, skipping reconciliation" )
439
- return ctrl.Result {}, nil
440
- case stateNeedsUninstall :
441
- // Use defer in a closure so that it executes before we wait for
442
- // the deletion of the CR. This might seem unnecessary since we're
443
- // applying changes to the CR after is has a deletion timestamp.
444
- // However, if uninstall fails, the finalizer will not be removed
445
- // and we need to be able to update the conditions on the CR to
446
- // indicate that the uninstall failed.
447
- if err := func () (err error ) {
448
- uninstallUpdater := updater .New (r .client )
449
- defer func () {
450
- applyErr := uninstallUpdater .Apply (ctx , obj )
451
- if err == nil {
452
- err = applyErr
453
- }
454
- }()
455
- return r .doUninstall (actionClient , & uninstallUpdater , obj , log )
456
- }(); err != nil {
457
- return ctrl.Result {}, err
458
- }
459
-
460
- // Since the client is hitting a cache, waiting for the
461
- // deletion here will guarantee that the next reconciliation
462
- // will see that the CR has been deleted and that there's
463
- // nothing left to do.
464
- if err := controllerutil .WaitForDeletion (ctx , r .client , obj ); err != nil {
465
- return ctrl.Result {}, err
466
- }
467
-
468
- return ctrl.Result {}, nil
469
- }
470
-
471
- u .UpdateStatus (updater .EnsureCondition (conditions .Initialized (corev1 .ConditionTrue , "" , "" )))
472
439
if rel != nil {
473
440
ensureDeployedRelease (& u , rel )
474
441
}
442
+ u .UpdateStatus (updater .EnsureCondition (conditions .Irreconcilable (corev1 .ConditionFalse , "" , "" )))
443
+ u .UpdateStatus (updater .EnsureCondition (conditions .Initialized (corev1 .ConditionTrue , "" , "" )))
475
444
476
445
switch state {
477
446
case stateNeedsInstall :
@@ -495,7 +464,6 @@ func (r *Reconciler) Reconcile(req ctrl.Request) (res ctrl.Result, err error) {
495
464
}
496
465
497
466
ensureDeployedRelease (& u , rel )
498
-
499
467
u .Update (updater .EnsureFinalizer (uninstallFinalizer ))
500
468
u .UpdateStatus (
501
469
updater .EnsureCondition (conditions .ReleaseFailed (corev1 .ConditionFalse , "" , "" )),
@@ -530,34 +498,68 @@ func (r *Reconciler) getValues(obj *unstructured.Unstructured) (chartutil.Values
530
498
type helmReleaseState string
531
499
532
500
const (
533
- stateNeedsInstall helmReleaseState = "needs install"
534
- stateNeedsUpgrade helmReleaseState = "needs upgrade"
535
- stateNeedsUninstall helmReleaseState = "needs uninstall"
536
- stateUnchanged helmReleaseState = "unchanged"
537
- stateAlreadyUninstalled helmReleaseState = "already uninstalled"
538
- stateError helmReleaseState = "error"
501
+ stateNeedsInstall helmReleaseState = "needs install"
502
+ stateNeedsUpgrade helmReleaseState = "needs upgrade"
503
+ stateUnchanged helmReleaseState = "unchanged"
504
+ stateError helmReleaseState = "error"
539
505
)
540
506
507
+ func (r * Reconciler ) handleDeletion (ctx context.Context , actionClient helmclient.ActionInterface , obj * unstructured.Unstructured , log logr.Logger ) error {
508
+ if ! controllerutil .ContainsFinalizer (obj , uninstallFinalizer ) {
509
+ log .Info ("Resource is terminated, skipping reconciliation" )
510
+ return nil
511
+ }
512
+
513
+ // Use defer in a closure so that it executes before we wait for
514
+ // the deletion of the CR. This might seem unnecessary since we're
515
+ // applying changes to the CR after is has a deletion timestamp.
516
+ // However, if uninstall fails, the finalizer will not be removed
517
+ // and we need to be able to update the conditions on the CR to
518
+ // indicate that the uninstall failed.
519
+ if err := func () (err error ) {
520
+ uninstallUpdater := updater .New (r .client )
521
+ defer func () {
522
+ applyErr := uninstallUpdater .Apply (ctx , obj )
523
+ if err == nil {
524
+ err = applyErr
525
+ }
526
+ }()
527
+ return r .doUninstall (actionClient , & uninstallUpdater , obj , log )
528
+ }(); err != nil {
529
+ return err
530
+ }
531
+
532
+ // Since the client is hitting a cache, waiting for the
533
+ // deletion here will guarantee that the next reconciliation
534
+ // will see that the CR has been deleted and that there's
535
+ // nothing left to do.
536
+ if err := controllerutil .WaitForDeletion (ctx , r .client , obj ); err != nil {
537
+ return err
538
+ }
539
+ return nil
540
+ }
541
+
541
542
func (r * Reconciler ) getReleaseState (client helmclient.ActionInterface , obj metav1.Object , vals map [string ]interface {}) (* release.Release , helmReleaseState , error ) {
542
543
deployedRelease , err := client .Get (obj .GetName ())
543
544
if err != nil && ! errors .Is (err , driver .ErrReleaseNotFound ) {
544
545
return nil , stateError , err
545
546
}
546
547
547
- if obj .GetDeletionTimestamp () != nil {
548
- if controllerutil .ContainsFinalizer (obj , uninstallFinalizer ) {
549
- return deployedRelease , stateNeedsUninstall , nil
550
- }
551
- return deployedRelease , stateAlreadyUninstalled , nil
552
- }
553
548
if errors .Is (err , driver .ErrReleaseNotFound ) {
554
549
return nil , stateNeedsInstall , nil
555
550
}
556
551
557
- specRelease , err := client .Upgrade (obj .GetName (), obj .GetNamespace (), r .chrt , vals , func (u * action.Upgrade ) error {
552
+ var opts []helmclient.UpgradeOption
553
+ for name , annot := range r .upgradeAnnotations {
554
+ if v , ok := obj .GetAnnotations ()[name ]; ok {
555
+ opts = append (opts , annot .UpgradeOption (v ))
556
+ }
557
+ }
558
+ opts = append (opts , func (u * action.Upgrade ) error {
558
559
u .DryRun = true
559
560
return nil
560
561
})
562
+ specRelease , err := client .Upgrade (obj .GetName (), obj .GetNamespace (), r .chrt , vals , opts ... )
561
563
if err != nil {
562
564
return deployedRelease , stateError , err
563
565
}
0 commit comments