Skip to content

Commit

Permalink
add replace remediated with released helper
Browse files Browse the repository at this point in the history
replaceRemediatedWithReleased() replaces remediated condition with
released condition, retaining the transition time. This helps ensure
that the last transition time of releases don't change when a release is
marked from remediated to released.

Signed-off-by: Sunny <[email protected]>
  • Loading branch information
darkowlzz committed Dec 7, 2023
1 parent e627301 commit 616ce88
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 4 deletions.
23 changes: 19 additions & 4 deletions internal/reconcile/atomic_release.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/fluxcd/pkg/runtime/logger"
"github.com/fluxcd/pkg/runtime/patch"
"github.com/fluxcd/pkg/ssa/jsondiff"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

v2 "github.com/fluxcd/helm-controller/api/v2beta2"
"github.com/fluxcd/helm-controller/internal/action"
Expand Down Expand Up @@ -322,10 +323,9 @@ func (r *AtomicRelease) actionForState(ctx context.Context, req *Request, state
// having the same chart version and values. As a result, we are already
// in-sync without performing a release action.
if conditions.IsTrue(req.Object, v2.RemediatedCondition) {
conditions.Delete(req.Object, v2.RemediatedCondition)
cur := req.Object.Status.History.Latest()
msg := fmt.Sprintf(fmtUpgradeSuccess, cur.FullReleaseName(), cur.VersionedChartName())
conditions.MarkTrue(req.Object, v2.ReleasedCondition, v2.UpgradeSucceededReason, msg)
replaceRemediatedWithReleased(req.Object, metav1.ConditionTrue, v2.UpgradeSucceededReason, msg)
}

return nil, nil
Expand Down Expand Up @@ -401,10 +401,9 @@ func (r *AtomicRelease) actionForState(ctx context.Context, req *Request, state
// a result, we are already in-sync without performing a release action,
// the existing release needs to undergo testing.
if conditions.IsTrue(req.Object, v2.RemediatedCondition) {
conditions.Delete(req.Object, v2.RemediatedCondition)
cur := req.Object.Status.History.Latest()
msg := fmt.Sprintf(fmtUpgradeSuccess, cur.FullReleaseName(), cur.VersionedChartName())
conditions.MarkTrue(req.Object, v2.ReleasedCondition, v2.UpgradeSucceededReason, msg)
replaceRemediatedWithReleased(req.Object, metav1.ConditionTrue, v2.UpgradeSucceededReason, msg)
}

return NewTest(r.configFactory, r.eventRecorder), nil
Expand Down Expand Up @@ -520,3 +519,19 @@ func timeoutForAction(action ActionReconciler, obj *v2.HelmRelease) time.Duratio
return obj.GetTimeout().Duration
}
}

// replaceRemediatedWithRelease replaces existing Remediated condition with
// Released condition, if present, for the given values, retaining the
// LastTransitionTime.
func replaceRemediatedWithReleased(obj *v2.HelmRelease, status metav1.ConditionStatus, reason, msg string) {
released := conditions.Get(obj, v2.RemediatedCondition)
if released != nil {
conditions.Delete(obj, v2.ReleasedCondition)
released.Status = status
released.Type = v2.ReleasedCondition
released.Reason = reason
released.Message = msg
conditions.Set(obj, released)
conditions.Delete(obj, v2.RemediatedCondition)
}
}
104 changes: 104 additions & 0 deletions internal/reconcile/atomic_release_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1557,3 +1557,107 @@ func TestAtomicRelease_actionForState(t *testing.T) {
})
}
}

func Test_replaceRemediatedWithRelease(t *testing.T) {
g := NewWithT(t)
timestamp, err := time.Parse(time.UnixDate, "Wed Feb 25 11:06:39 GMT 2015")
g.Expect(err).ToNot(HaveOccurred())

tests := []struct {
name string
conditions []metav1.Condition
wantConditions []metav1.Condition
}{
{
name: "existing released and remediated conditions",
conditions: []metav1.Condition{
{
Type: v2.ReleasedCondition,
Status: metav1.ConditionFalse,
Reason: v2.UpgradeFailedReason,
Message: "upgrade failed",
ObservedGeneration: 1,
LastTransitionTime: metav1.NewTime(timestamp),
},
{
Type: v2.RemediatedCondition,
Status: metav1.ConditionTrue,
Reason: v2.RollbackSucceededReason,
Message: "rollback",
ObservedGeneration: 1,
LastTransitionTime: metav1.NewTime(timestamp),
},
},
wantConditions: []metav1.Condition{
{
Type: v2.ReleasedCondition,
Status: metav1.ConditionTrue,
Reason: v2.UpgradeSucceededReason,
Message: "foo",
ObservedGeneration: 1,
LastTransitionTime: metav1.NewTime(timestamp),
},
},
},
{
name: "no released condition",
conditions: []metav1.Condition{
{
Type: v2.RemediatedCondition,
Status: metav1.ConditionTrue,
Reason: v2.RollbackSucceededReason,
Message: "rollback",
ObservedGeneration: 1,
LastTransitionTime: metav1.NewTime(timestamp),
},
},
wantConditions: []metav1.Condition{
{
Type: v2.ReleasedCondition,
Status: metav1.ConditionTrue,
Reason: v2.UpgradeSucceededReason,
Message: "foo",
ObservedGeneration: 1,
LastTransitionTime: metav1.NewTime(timestamp),
},
},
},
{
name: "no remediated condition",
conditions: []metav1.Condition{
{
Type: v2.ReleasedCondition,
Status: metav1.ConditionFalse,
Reason: v2.UpgradeFailedReason,
Message: "upgrade failed",
ObservedGeneration: 1,
LastTransitionTime: metav1.NewTime(timestamp),
},
},
wantConditions: []metav1.Condition{
{
Type: v2.ReleasedCondition,
Status: metav1.ConditionFalse,
Reason: v2.UpgradeFailedReason,
Message: "upgrade failed",
ObservedGeneration: 1,
LastTransitionTime: metav1.NewTime(timestamp),
},
},
},
{
name: "no released and remediated conditions",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)

obj := &v2.HelmRelease{}
obj.Generation = 1
obj.Status.Conditions = tt.conditions
replaceRemediatedWithReleased(obj, metav1.ConditionTrue, v2.UpgradeSucceededReason, "foo")
g.Expect(obj.Status.Conditions).To(Equal(tt.wantConditions))
})
}
}

0 comments on commit 616ce88

Please sign in to comment.