-
Notifications
You must be signed in to change notification settings - Fork 2
[WIP] ROX-7352 unlock pending helm actions #13
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -20,6 +20,7 @@ import ( | |||||||||||||||||||||
"context" | ||||||||||||||||||||||
"errors" | ||||||||||||||||||||||
"fmt" | ||||||||||||||||||||||
"math/rand" | ||||||||||||||||||||||
"strings" | ||||||||||||||||||||||
"sync" | ||||||||||||||||||||||
"time" | ||||||||||||||||||||||
|
@@ -56,7 +57,13 @@ import ( | |||||||||||||||||||||
"github.com/joelanford/helm-operator/pkg/values" | ||||||||||||||||||||||
) | ||||||||||||||||||||||
|
||||||||||||||||||||||
const uninstallFinalizer = "uninstall-helm-release" | ||||||||||||||||||||||
const ( | ||||||||||||||||||||||
uninstallFinalizer = "uninstall-helm-release" | ||||||||||||||||||||||
// pendingReleaseTimeout defines the time frame after which a rollback is performed on a given release | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
pendingReleaseTimeout = time.Second * 30 | ||||||||||||||||||||||
// pendingRetryInterval defines the time waiting until the current reconciliation finished to avoid spamming helm actions | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you explain what you mean by "spamming helm actions"? |
||||||||||||||||||||||
pendingRetryInterval = time.Second * 5 | ||||||||||||||||||||||
) | ||||||||||||||||||||||
|
||||||||||||||||||||||
// Reconciler reconciles a Helm object | ||||||||||||||||||||||
type Reconciler struct { | ||||||||||||||||||||||
|
@@ -561,10 +568,22 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (res ctrl. | |||||||||||||||||||||
return ctrl.Result{}, err | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
case statedNeedsRollback: | ||||||||||||||||||||||
{ | ||||||||||||||||||||||
if err := r.doRollback(actionClient, &u, obj); err != nil { | ||||||||||||||||||||||
return ctrl.Result{}, err | ||||||||||||||||||||||
} | ||||||||||||||||||||||
} | ||||||||||||||||||||||
Comment on lines
+571
to
+576
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need the block?
Suggested change
|
||||||||||||||||||||||
|
||||||||||||||||||||||
case stateUnchanged: | ||||||||||||||||||||||
if err := r.doReconcile(actionClient, &u, rel, log); err != nil { | ||||||||||||||||||||||
return ctrl.Result{}, err | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
case stateNeedsSkip: | ||||||||||||||||||||||
// TODO(do-not-merge): set status custom resource status | ||||||||||||||||||||||
return ctrl.Result{Requeue: true, RequeueAfter: pendingRetryInterval}, nil | ||||||||||||||||||||||
|
||||||||||||||||||||||
default: | ||||||||||||||||||||||
return ctrl.Result{}, fmt.Errorf("unexpected release state: %s", state) | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
@@ -614,10 +633,12 @@ func (r *Reconciler) getValues(ctx context.Context, obj *unstructured.Unstructur | |||||||||||||||||||||
type helmReleaseState string | ||||||||||||||||||||||
|
||||||||||||||||||||||
const ( | ||||||||||||||||||||||
stateNeedsInstall helmReleaseState = "needs install" | ||||||||||||||||||||||
stateNeedsUpgrade helmReleaseState = "needs upgrade" | ||||||||||||||||||||||
stateUnchanged helmReleaseState = "unchanged" | ||||||||||||||||||||||
stateError helmReleaseState = "error" | ||||||||||||||||||||||
stateNeedsInstall helmReleaseState = "needs install" | ||||||||||||||||||||||
stateNeedsUpgrade helmReleaseState = "needs upgrade" | ||||||||||||||||||||||
stateUnchanged helmReleaseState = "unchanged" | ||||||||||||||||||||||
stateError helmReleaseState = "error" | ||||||||||||||||||||||
statedNeedsRollback helmReleaseState = "needs rollback" | ||||||||||||||||||||||
stateNeedsSkip helmReleaseState = "needs skip" | ||||||||||||||||||||||
) | ||||||||||||||||||||||
|
||||||||||||||||||||||
func (r *Reconciler) handleDeletion(ctx context.Context, actionClient helmclient.ActionInterface, obj *unstructured.Unstructured, log logr.Logger) error { | ||||||||||||||||||||||
|
@@ -665,6 +686,19 @@ func (r *Reconciler) getReleaseState(client helmclient.ActionInterface, obj meta | |||||||||||||||||||||
return nil, stateNeedsInstall, nil | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
// If the release is pending it is likely that it happened because the helm install/upgrade/rollback action | ||||||||||||||||||||||
// were cancelled unexpectedly. | ||||||||||||||||||||||
//TODO(do-not-merge): as pending releases are now rolled back it is necessary to ensure that an in-progress helm release is not cancelled | ||||||||||||||||||||||
// and this code is only executed to ensure aborted releases are rolled back. | ||||||||||||||||||||||
if currentRelease.Info.Status.IsPending() { | ||||||||||||||||||||||
t := time.Now().Sub(currentRelease.Info.LastDeployed.Time) | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should probably be prepared to the case when |
||||||||||||||||||||||
if t <= pendingReleaseTimeout { | ||||||||||||||||||||||
r.log.Info("Release pending, skipped", "name", currentRelease.Name, "version", currentRelease.Version, "retry_in", pendingRetryInterval.String()) | ||||||||||||||||||||||
return nil, stateNeedsSkip, nil | ||||||||||||||||||||||
} | ||||||||||||||||||||||
return nil, statedNeedsRollback, nil | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
var opts []helmclient.UpgradeOption | ||||||||||||||||||||||
for name, annot := range r.upgradeAnnotations { | ||||||||||||||||||||||
if v, ok := obj.GetAnnotations()[name]; ok { | ||||||||||||||||||||||
|
@@ -679,7 +713,7 @@ func (r *Reconciler) getReleaseState(client helmclient.ActionInterface, obj meta | |||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||
return currentRelease, stateError, err | ||||||||||||||||||||||
} | ||||||||||||||||||||||
if specRelease.Manifest != currentRelease.Manifest || | ||||||||||||||||||||||
if specRelease.Manifest != fmt.Sprintf("%d%s", rand.Int31(), currentRelease.Manifest) || | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Temporary hack, I assume? |
||||||||||||||||||||||
currentRelease.Info.Status == release.StatusFailed || | ||||||||||||||||||||||
currentRelease.Info.Status == release.StatusSuperseded { | ||||||||||||||||||||||
return currentRelease, stateNeedsUpgrade, nil | ||||||||||||||||||||||
|
@@ -737,6 +771,22 @@ func (r *Reconciler) reportOverrideEvents(obj runtime.Object) { | |||||||||||||||||||||
} | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
func (r *Reconciler) doRollback(actionClient helmclient.ActionInterface, u *updater.Updater, obj *unstructured.Unstructured) error { | ||||||||||||||||||||||
u.UpdateStatus( | ||||||||||||||||||||||
//TODO(do-not-merge): Add better error message indicating that release was maybe aborted | ||||||||||||||||||||||
updater.EnsureCondition(conditions.ReleasePending(corev1.ConditionFalse, "", "")), | ||||||||||||||||||||||
) | ||||||||||||||||||||||
|
||||||||||||||||||||||
if err := actionClient.Rollback(obj.GetName()); err != nil { | ||||||||||||||||||||||
u.UpdateStatus( | ||||||||||||||||||||||
//TODO(do-not-merge): Add better error message indicating that release was maybe aborted with manual steps | ||||||||||||||||||||||
updater.EnsureCondition(conditions.RollbackFailed(corev1.ConditionFalse, "", err)), | ||||||||||||||||||||||
) | ||||||||||||||||||||||
return err | ||||||||||||||||||||||
} | ||||||||||||||||||||||
return nil | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
func (r *Reconciler) doReconcile(actionClient helmclient.ActionInterface, u *updater.Updater, rel *release.Release, log logr.Logger) error { | ||||||||||||||||||||||
// If a change is made to the CR spec that causes a release failure, a | ||||||||||||||||||||||
// ConditionReleaseFailed is added to the status conditions. If that change | ||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
None of the other types starts with
Type
...