Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/libs/status.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ The `ReconcileResult` that is passed into the status updater is expected to cont
- `Reason` and `Message` can be set to set the status' corresponding fields.
- If either one is nil, but `ReconcileError` is not, it will be filled with a value derived from the error.
- `Conditions` contains the updated conditions. Depending on with which arguments `WithConditionUpdater` was called, the existing conditions will be either updated with these ones (keeping the other ones), or be replaced by them.
- `ConditionsToRemove` is a list of condition types that should be removed from the conditions. This is mostly useful if the condition updater is used in the 'keep untouched conditions' mode.
- `Object` contains the object to be updated.
- If `Object` is nil, no status update will be performed.
- `OldObject` holds the version of the object that will be used as a base for constructing the patch during the status update.
Expand Down
8 changes: 8 additions & 0 deletions pkg/controller/status_updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,11 @@ func (s *statusUpdater[Obj]) UpdateStatus(ctx context.Context, c client.Client,
}
cu.UpdateCondition(con.Type, con.Status, gen, con.Reason, con.Message)
}
if len(rr.ConditionsToRemove) > 0 {
for _, conType := range rr.ConditionsToRemove {
cu.RemoveCondition(conType)
}
}
newCons, _ := cu.Record(rr.Object).Conditions()
SetField(status, s.fieldNames[STATUS_FIELD_CONDITIONS], newCons)
}
Expand Down Expand Up @@ -416,6 +421,9 @@ type ReconcileResult[Obj client.Object] struct {
// Also note that names of conditions are globally unique, so take care to avoid conflicts with other objects.
// The lastTransition timestamp of the condition will be overwritten with the current time while updating.
Conditions []metav1.Condition
// ConditionsToRemove is an optional slice of condition types for which the corresponding conditions should be removed from the status.
// This is useful if you want to remove conditions that are no longer relevant.
ConditionsToRemove []string
}

// GenerateCreateConditionFunc returns a function that can be used to add a condition to the given ReconcileResult.
Expand Down
19 changes: 6 additions & 13 deletions pkg/controller/status_updater_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@ var _ = Describe("Status Updater", func() {
env := testutils.NewEnvironmentBuilder().WithFakeClient(coScheme).WithInitObjectPath("testdata", "test-02").WithDynamicObjectsWithStatus(&CustomObject{}).Build()
obj := &CustomObject{}
Expect(env.Client().Get(env.Ctx, controller.ObjectKey("status", "default"), obj)).To(Succeed())
oldTransitionTime := conditions.GetCondition(obj.Status.Conditions, "TestConditionTrue").LastTransitionTime
before := obj.DeepCopy()
for _, disabledField := range controller.AllStatusFields() {
By(fmt.Sprintf("Testing disabled field %s", disabledField))
Expand All @@ -132,10 +131,11 @@ var _ = Describe("Status Updater", func() {
obj.Status = before.Status
Expect(env.Client().Status().Patch(env.Ctx, obj, client.MergeFrom(modified))).To(Succeed())
rr := controller.ReconcileResult[*CustomObject]{
Object: obj,
Conditions: dummyConditions(),
Reason: "TestReason",
Message: "TestMessage",
Object: obj,
Conditions: dummyConditions(),
Reason: "TestReason",
Message: "TestMessage",
ConditionsToRemove: []string{"TestConditionTrue"},
}
su := preconfiguredStatusUpdaterBuilder().WithPhaseUpdateFunc(func(obj *CustomObject, rr controller.ReconcileResult[*CustomObject]) (string, error) {
return PhaseSucceeded, nil
Expand Down Expand Up @@ -176,21 +176,14 @@ var _ = Describe("Status Updater", func() {
Expect(obj.Status.Conditions).To(Equal(before.Status.Conditions))
} else {
Expect(obj.Status.Conditions).To(ConsistOf(
MatchCondition(TestCondition().
WithType("TestConditionTrue").
WithStatus(metav1.ConditionTrue).
WithObservedGeneration(10).
WithReason("TestReasonTrue").
WithMessage("TestMessageTrue").
WithLastTransitionTime(oldTransitionTime)),
MatchCondition(TestCondition().
WithType("TestConditionFalse").
WithStatus(metav1.ConditionFalse).
WithObservedGeneration(10).
WithReason("TestReasonFalse").
WithMessage("TestMessageFalse").
WithLastTransitionTime(now).
WithTimestampTolerance(1*time.Second)),
WithTimestampTolerance(1 * time.Second)),
))
}
}
Expand Down