Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pkg/helm/controller/reconcile.go: finalizer fix #3039

Merged
merged 1 commit into from May 14, 2020

Conversation

joelanford
Copy link
Member

Description of the change:
Helm operator now applies its uninstall finalizer only when a release is deployed.

Motivation for the change:
This PR fixes a bug in the helm operator that caused the CR to be unable to be deleted without manually intervening to delete a prematurely added finalizer.

This PR fixes a bug in the helm operator that caused the
CR to be unable to be deleted without manually intervening
to delete a prematurely added finalizer.

Helm operator now applies its uninstall finalizer only when
a release is deployed.
Copy link
Member Author

@joelanford joelanford left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some notes to give context and explain the changes.

@@ -79,8 +78,7 @@ func Add(mgr manager.Manager, options WatchOptions) error {

o := &unstructured.Unstructured{}
o.SetGroupVersionKind(options.GVK)
if err := c.Watch(&source.Kind{Type: o}, &crthandler.EnqueueRequestForObject{},
predicate.GenerationChangedPredicate{}); err != nil {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GenerationChangedPredicate needed to be removed. Without it, the helm operator can now detect that the finalizer has been changed/deleted and reconcile so that it is re-added.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this predicate preventing detection of changes to the finalizer? Wouldn't a finalizer update change a CR's generation and pass through the predicate?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty sure generation is only changed for spec updates (and maybe status updates). It is not changed when metadata changes. I'm like 95% certain on this, so I'll double check to be sure.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep just confirmed that on master I can manually remove the finalizer and it doesn't show back up until I make another edit that changes the spec.

Comment on lines -97 to -107
deleted := o.GetDeletionTimestamp() != nil
pendingFinalizers := o.GetFinalizers()
if !deleted && !contains(pendingFinalizers, finalizer) {
log.V(1).Info("Adding finalizer", "finalizer", finalizer)
finalizers := append(pendingFinalizers, finalizer)
o.SetFinalizers(finalizers)
err = r.updateResource(o)

// Need to requeue because finalizer update does not change metadata.generation
return reconcile.Result{Requeue: true}, err
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section is moved so that we only add the finalizer after a successful install and then we ensure it is present when reconciling.

Comment on lines -109 to -125
status.SetCondition(types.HelmAppCondition{
Type: types.ConditionInitialized,
Status: types.StatusTrue,
})

if err := manager.Sync(context.TODO()); err != nil {
log.Error(err, "Failed to sync release")
status.SetCondition(types.HelmAppCondition{
Type: types.ConditionIrreconcilable,
Status: types.StatusTrue,
Reason: types.ReasonReconcileError,
Message: err.Error(),
})
_ = r.updateResourceStatus(o, status)
return reconcile.Result{}, err
}
status.RemoveCondition(types.ConditionIrreconcilable)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section is moved to after the deletion check and uninstall code. This is necessary to ensure that a CR can always be deleted. There were cases where the CR had a deletion timestamp, but this call to manager.Sync was failing so we always errored out before getting to the manager.Uninstall call.

Comment on lines +346 to +348
return retry.RetryOnConflict(retry.DefaultBackoff, func() error {
return r.Client.Update(context.TODO(), o)
})
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we're no longer using the GenerationChangedPredicate, we get more back-to-back reconciliations, so we need to retry on conflict since the cache may not have updated in time to return the latest version of the CR.

Copy link
Member

@estroz estroz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

@openshift-ci-robot openshift-ci-robot added the lgtm Indicates that a PR is ready to be merged. label May 14, 2020
@joelanford joelanford merged commit c703c8d into operator-framework:master May 14, 2020
@joelanford joelanford deleted the helm-fix-finalizer branch May 14, 2020 19:32
@joelanford
Copy link
Member Author

/cherry-pick v0.17.x

@openshift-cherrypick-robot

@joelanford: new pull request created: #3046

In response to this:

/cherry-pick v0.17.x

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
lgtm Indicates that a PR is ready to be merged.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants